Skip to content

Commit 7819c96

Browse files
authored
Merge pull request #26 from clevertech/update/dependencies
Update/dependencies
2 parents f43b9d5 + 9b127a1 commit 7819c96

File tree

10 files changed

+2661
-6641
lines changed

10 files changed

+2661
-6641
lines changed

core/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
1+
12
# CleverAuth Core
23

4+
Generic auth library for Clevertech.
5+
6+
7+
## Testing
8+
9+
You have to run the tests with node `v10` or `v12`. Node `v14` has a known issue with older `pg`
10+
clients.
11+
12+
docker-compose -f test/docker-compose.yml up -d
13+
npm run test
14+
15+
16+
## Example
17+
318
```javascript
419
import {
520
Core,

core/package.json

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@clevertech.biz/auth-core",
3-
"version": "1.0.2",
3+
"version": "2.0.0",
44
"description": "The set of utilities necessary to build an authentication service. This does not include templates, views, styles, or transport layer.",
55
"keywords": [],
66
"main": "dist/library.js",
@@ -76,50 +76,49 @@
7676
"collectCoverage": true,
7777
"coverageThreshold": {
7878
"global": {
79-
"branches": 90,
80-
"functions": 95,
81-
"lines": 95,
82-
"statements": 95
79+
"branches": 60,
80+
"functions": 60,
81+
"lines": 70,
82+
"statements": 65
8383
}
8484
}
8585
},
8686
"devDependencies": {
87-
"@types/jest": "^22.0.0",
88-
"@types/node": "^8.0.0",
87+
"@types/jest": "^25.1.0",
88+
"@types/node": "^10.17.0",
8989
"commitizen": "^2.9.6",
9090
"coveralls": "^2.13.1",
9191
"cz-conventional-changelog": "^2.0.0",
9292
"husky": "^0.14.0",
93-
"jest": "^22.0.0",
93+
"jest": "^25.1.0",
9494
"lint-staged": "^4.0.0",
9595
"mysql": "^2.15.0",
9696
"pg": "^7.4.0",
9797
"prettier": "^1.9.2",
9898
"rimraf": "^2.6.1",
9999
"semantic-release": "^8.0.0",
100-
"ts-jest": "^22.0.0",
101-
"ts-node": "^3.0.6",
100+
"ts-jest": "^25.1.0",
101+
"ts-node": "^8.9.1",
102102
"tslint": "^5.4.3",
103103
"tslint-config-prettier": "^1.1.0",
104104
"tslint-config-standard": "^6.0.0",
105-
"typedoc": "^0.8.0",
106-
"typescript": "^2.3.4",
105+
"typedoc": "0.16.11",
106+
"typescript": "^3.7.5",
107107
"validate-commit-msg": "^2.12.2"
108108
},
109109
"dependencies": {
110110
"@types/joi": "^10.4.3",
111111
"@types/jsonwebtoken": "^7.2.3",
112-
"@types/knex": "^0.0.61",
113-
"@types/lodash": "^4.14.76",
112+
"@types/lodash": "^4.14.165",
114113
"@types/mongodb": "^2.2.11",
115114
"@types/node-fetch": "^1.6.7",
116115
"@types/qrcode": "^0.8.0",
117116
"@types/speakeasy": "^2.0.1",
118117
"@types/uuid": "^3.4.2",
119118
"joi": "^11.1.1",
120119
"jsonwebtoken": "^8.0.1",
121-
"knex": "^0.13.0",
122-
"lodash": "^4.17.4",
120+
"knex": "^0.20.15",
121+
"lodash": "^4.17.20",
123122
"mongodb": "^2.2.31",
124123
"node-fetch": "^1.7.3",
125124
"pnp-email-service": "^0.1.8",

core/src/database/knex.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ export default class KnexAdapter implements IDatabaseAdapter {
4747
table
4848
.text('emailConfirmationToken')
4949
.nullable()
50-
.unique()
50+
// Mysql does not support unique on blobs
51+
//.unique()
5152
table.string('termsAndConditions').nullable()
5253
table.timestamps()
5354
})
@@ -186,7 +187,7 @@ export default class KnexAdapter implements IDatabaseAdapter {
186187
}
187188

188189
async insertUser(user: IUser): Promise<string> {
189-
user = omit(user, ['id', '_id'])
190+
user = omit(user, ['id', '_id']) as IUser
190191
const userId = uuid()
191192
user.id = userId
192193
return this.db('auth_users')

core/src/database/mongo.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import * as mongo from 'mongodb';
33
import { IProvider, IRecoveryCode, IUser, IUserUpdate } from '../types';
44
import { IDatabaseAdapter } from './adapter';
55

6+
const UNINITIALIZED_ADAPTER = 'Mongo adapter was not initialized';
7+
68
export default class MongoAdapter implements IDatabaseAdapter {
79
private databaseURL: string
8-
private db: mongo.Db
10+
private db: mongo.Db | undefined
911

1012
constructor(databaseURL: string) {
1113
this.databaseURL = databaseURL
@@ -22,16 +24,19 @@ export default class MongoAdapter implements IDatabaseAdapter {
2224
}
2325

2426
public async findUserByEmail(email: string): Promise<IUser | undefined> {
27+
if(!this.db) throw new Error(UNINITIALIZED_ADAPTER);
2528
return this.normalize(await this.db.collection('auth_users').findOne({ email }))
2629
}
2730

2831
public async findUserById(id: string): Promise<IUser | undefined> {
32+
if(!this.db) throw new Error(UNINITIALIZED_ADAPTER);
2933
return this.normalize(
3034
await this.db.collection('auth_users').findOne({ _id: new mongo.ObjectID(id) })
3135
)
3236
}
3337

3438
public async findUserByProviderLogin(login: string): Promise<IUser | undefined> {
39+
if(!this.db) throw new Error(UNINITIALIZED_ADAPTER);
3540
const provider = await this.db.collection('auth_providers').findOne({ login })
3641
if (!provider) {
3742
return undefined
@@ -42,43 +47,50 @@ export default class MongoAdapter implements IDatabaseAdapter {
4247
}
4348

4449
public findRecoveryCodesByUserId(userId: string): Promise<IRecoveryCode[]> {
50+
if(!this.db) throw new Error(UNINITIALIZED_ADAPTER);
4551
return this.db
4652
.collection('auth_recovery_codes')
4753
.find({ userId })
4854
.toArray()
4955
}
5056

5157
public async insertRecoveryCodes(userId: string, codes: string[]): Promise<IRecoveryCode[]> {
58+
if(!this.db) throw new Error(UNINITIALIZED_ADAPTER);
5259
await this.db.collection('auth_recovery_codes').deleteMany({ userId })
5360

5461
await Promise.all(
5562
codes.map(code => {
63+
if(!this.db) throw new Error(UNINITIALIZED_ADAPTER);
5664
return this.db.collection('auth_recovery_codes').insertOne({ userId, code, used: false })
5765
})
5866
)
5967
return codes.map(code => ({ code, used: false }))
6068
}
6169

6270
public async useRecoveryCode(userId: string, code: string): Promise<boolean> {
71+
if(!this.db) throw new Error(UNINITIALIZED_ADAPTER);
6372
const res = await this.db
6473
.collection('auth_recovery_codes')
6574
.updateOne({ userId, code: code.toLowerCase(), used: false }, { $set: { used: true } })
6675
return !!res.result.nModified
6776
}
6877

6978
public async insertUser(user: IUser): Promise<string> {
79+
if(!this.db) throw new Error(UNINITIALIZED_ADAPTER);
7080
const res = await this.db.collection('auth_users').insertOne(user)
7181
return res.insertedId.toHexString()
7282
}
7383

7484
public async updateUser(user: IUserUpdate): Promise<void> {
85+
if(!this.db) throw new Error(UNINITIALIZED_ADAPTER);
7586
const res = await this.db
7687
.collection('auth_users')
7788
.update({ _id: new mongo.ObjectID(user.id!) }, { $set: omit(user, 'id') })
7889
return res.result.nModified
7990
}
8091

8192
public async insertProvider(provider: IProvider): Promise<void> {
93+
if(!this.db) throw new Error(UNINITIALIZED_ADAPTER);
8294
await this.db.collection('auth_providers').insertOne(provider)
8395
// return res.insertedId.toHexString()
8496
}

core/src/utils/crypto.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ const encoding = 'hex'
66

77
export default class Crypto {
88
private key: string
9-
private algorithm: string
9+
private algorithm: crypto.CipherGCMTypes
1010

11-
constructor(key: string, algorithm: string = 'aes-256-gcm') {
11+
constructor(key: string, algorithm: crypto.CipherGCMTypes = 'aes-256-gcm') {
1212
this.key = key
1313
this.algorithm = algorithm
1414
}

core/test/database.test.ts

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,60 @@ const adapters: { [index: string]: IDatabaseAdapter } = {
3535

3636
const randomId = crypto.randomBytes(16).toString('hex')
3737

38+
const USER_UNDEFINED = 'User is not defined';
39+
3840
describe('Database adapter', () => {
41+
42+
describe('Mongo adapter specific', () => {
43+
const adapter = adapters.mongo
44+
const adapterName = 'mongo';
45+
46+
describe('Before init() calls', () => {
47+
it(`${adapterName} insertUser() should fail`, async () => {
48+
expect(
49+
adapter.insertUser({
50+
email: '',
51+
emailConfirmationToken: ''
52+
})
53+
).rejects.toThrow();
54+
});
55+
it(`${adapterName} insertProvider() should fail`, async () => {
56+
expect(
57+
adapter.insertProvider({
58+
userId: '',
59+
login: '',
60+
data: { }
61+
})
62+
).rejects.toThrow();
63+
})
64+
it(`${adapterName} updateUser() should fail`, async () => {
65+
expect(
66+
adapter.updateUser({ id: '', emailConfirmed: true })
67+
).rejects.toThrow();
68+
})
69+
it(`${adapterName} findUserByEmail() should fail`, async () => {
70+
expect(
71+
adapter.findUserByEmail('')
72+
).rejects.toThrow();
73+
})
74+
it(`${adapterName} findUserById() should fail`, async () => {
75+
expect(
76+
adapter.findUserById('')
77+
).rejects.toThrow();
78+
})
79+
it(`${adapterName} findUserByProviderLogin() should fail`, async () => {
80+
expect(
81+
adapter.findUserByProviderLogin('')
82+
).rejects.toThrow();
83+
})
84+
});
85+
});
86+
3987
Object.keys(adapters).forEach(adapterName => {
4088
const adapter = adapters[adapterName]
41-
let userId
42-
let emailConfirmationToken
89+
let userId: string
90+
let emailConfirmationToken: string
91+
4392
it(`${adapterName} init()`, async () => {
4493
await adapter.init()
4594
})
@@ -61,25 +110,31 @@ describe('Database adapter', () => {
61110
it(`${adapterName} updateUser()`, async () => {
62111
await adapter.updateUser({ id: userId, emailConfirmed: true })
63112
const user = await adapter.findUserById(userId)
113+
if(!user) throw Error(USER_UNDEFINED);
64114
expect(user.emailConfirmed).toEqual(true)
65115
})
66116

67117
it(`${adapterName} findUserByEmail()`, async () => {
68118
const user = await adapter.findUserByEmail(`test+${randomId}@example.com`)
119+
if(!user) throw Error(USER_UNDEFINED);
69120
expect(user.id).toEqual(userId)
70121
expect(user.email).toEqual(`test+${randomId}@example.com`)
71-
emailConfirmationToken = user.emailConfirmationToken
122+
if(user.emailConfirmationToken) {
123+
emailConfirmationToken = user.emailConfirmationToken
124+
}
72125
})
73126

74127
it(`${adapterName} findUserById()`, async () => {
75128
const user = await adapter.findUserById(userId)
129+
if(!user) throw Error(USER_UNDEFINED);
76130
expect(user.id).toEqual(userId)
77131
expect(user.email).toEqual(`test+${randomId}@example.com`)
78132
expect(user.emailConfirmationToken).toEqual(emailConfirmationToken)
79133
})
80134

81135
it(`${adapterName} findUserByProviderLogin()`, async () => {
82136
const user = await adapter.findUserByProviderLogin(`login${randomId}`)
137+
if(!user) throw Error(USER_UNDEFINED);
83138
expect(user.id).toEqual(userId)
84139
expect(user.email).toEqual(`test+${randomId}@example.com`)
85140
expect(user.emailConfirmationToken).toEqual(emailConfirmationToken)

core/test/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ services:
1010
ports:
1111
- '5432:5432'
1212
mysql:
13-
image: mysql
13+
image: mysql:5.7
1414
restart: always
1515
environment:
1616
MYSQL_ROOT_PASSWORD: cleverauth-test

core/test/utils/jwt.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ describe('JWT', () => {
1010
expect(original.hello).toEqual(payload.hello)
1111
})
1212
it('sign rejects on invalid params', async () => {
13-
expect(jwt1.sign(undefined)).rejects.toHaveProperty('message', 'payload is required')
13+
const value: unknown = undefined;
14+
expect(jwt1.sign(value as string)).rejects.toHaveProperty('message', 'payload is required')
1415
})
1516
it('verify rejects on invalid params', async () => {
16-
expect(jwt1.verify(undefined)).rejects.toHaveProperty('message', 'jwt must be provided')
17+
const value: unknown = undefined;
18+
expect(jwt1.verify(value as string)).rejects.toHaveProperty('message', 'jwt must be provided')
1719
})
1820
})

0 commit comments

Comments
 (0)