From 328b17092debfb899ea808f2bcff5af4d7f334f7 Mon Sep 17 00:00:00 2001 From: ozsay Date: Wed, 21 Aug 2019 14:29:15 +0300 Subject: [PATCH 01/10] code authentication service --- packages/code-provider-sms/README.md | 35 +++++++ packages/code-provider-sms/package.json | 28 ++++++ .../src/code-provider-sms.ts | 50 ++++++++++ packages/code-provider-sms/src/index.ts | 4 + packages/code-provider-sms/tsconfig.json | 9 ++ packages/code/README.md | 30 ++++++ packages/code/package.json | 32 +++++++ packages/code/src/accounts-code.ts | 94 +++++++++++++++++++ packages/code/src/errors.ts | 9 ++ packages/code/src/index.ts | 5 + packages/code/src/types/code-generator.ts | 3 + packages/code/src/types/code-hash.ts | 5 + packages/code/src/types/code-login-type.ts | 4 + packages/code/src/types/code-provider.ts | 3 + packages/code/src/types/error-messages.ts | 7 ++ packages/code/src/types/index.ts | 5 + .../src/utils/randomstring-code-generator.ts | 17 ++++ packages/code/src/utils/simple-code-hash.ts | 22 +++++ packages/code/tsconfig.json | 9 ++ yarn.lock | 85 ++++++++++++++++- 20 files changed, 454 insertions(+), 2 deletions(-) create mode 100644 packages/code-provider-sms/README.md create mode 100644 packages/code-provider-sms/package.json create mode 100644 packages/code-provider-sms/src/code-provider-sms.ts create mode 100644 packages/code-provider-sms/src/index.ts create mode 100644 packages/code-provider-sms/tsconfig.json create mode 100644 packages/code/README.md create mode 100644 packages/code/package.json create mode 100644 packages/code/src/accounts-code.ts create mode 100644 packages/code/src/errors.ts create mode 100644 packages/code/src/index.ts create mode 100644 packages/code/src/types/code-generator.ts create mode 100644 packages/code/src/types/code-hash.ts create mode 100644 packages/code/src/types/code-login-type.ts create mode 100644 packages/code/src/types/code-provider.ts create mode 100644 packages/code/src/types/error-messages.ts create mode 100644 packages/code/src/types/index.ts create mode 100644 packages/code/src/utils/randomstring-code-generator.ts create mode 100644 packages/code/src/utils/simple-code-hash.ts create mode 100644 packages/code/tsconfig.json diff --git a/packages/code-provider-sms/README.md b/packages/code-provider-sms/README.md new file mode 100644 index 000000000..215545f37 --- /dev/null +++ b/packages/code-provider-sms/README.md @@ -0,0 +1,35 @@ +# @accounts/code-provider-sms + +## Install + +``` +yarn add @accounts/code-provider-sms +``` + +## Usage + +```js +import { AccountsServer } from '@accounts/server'; +import { AccountsCode } from '@accounts/code'; +import { CodeProviderSMS } from '@accounts/code-provider-sms'; + +const codeProvider = new CodeProviderSMS({ + sid: 'TWILIO_SID', + secret: 'TWILIO_SECRET', + phoneNumber: 'TWILIO_FROM_PHONE_NUMBER', +}); + +export const accountsCode = new AccountsCode({ + codeProvider, + // options +}); + +const accountsServer = new AccountsServer( + { + // options + }, + { + code: accountsCode, + } +); +``` diff --git a/packages/code-provider-sms/package.json b/packages/code-provider-sms/package.json new file mode 100644 index 000000000..aec44204f --- /dev/null +++ b/packages/code-provider-sms/package.json @@ -0,0 +1,28 @@ +{ + "name": "@accounts/code-provider-sms", + "version": "0.18.0", + "license": "MIT", + "main": "lib/index.js", + "typings": "lib/index.d.ts", + "scripts": { + "clean": "rimraf lib", + "start": "tsc --watch", + "precompile": "yarn clean", + "compile": "tsc", + "prepublishOnly": "yarn compile", + "testonly": "jest --coverage", + "coverage": "jest --coverage" + }, + "jest": { + "testEnvironment": "node", + "preset": "ts-jest" + }, + "dependencies": { + "twilio": "^3.33.3" + }, + "devDependencies": { + }, + "peerDependencies": { + "@accounts/code": "^0.18.0" + } +} diff --git a/packages/code-provider-sms/src/code-provider-sms.ts b/packages/code-provider-sms/src/code-provider-sms.ts new file mode 100644 index 000000000..c39ad7b1b --- /dev/null +++ b/packages/code-provider-sms/src/code-provider-sms.ts @@ -0,0 +1,50 @@ +import { Twilio } from 'twilio'; + +import { CodeProvider } from '@accounts/code'; + +export type MessageCreator = (code: string) => string; + +export interface TwilioSmsCodeProviderOptions { + sid: string; + secret: string; + phoneNumber?: string; + messagingServiceSid?: string; + messageCreator?: MessageCreator; +} + +export default class TwilioSmsCodeProvider implements CodeProvider { + private messageCreator: MessageCreator; + private phoneNumber?: string; + private messagingServiceSid?: string; + private twilio: Twilio; + + constructor({ + sid, + secret, + phoneNumber, + messagingServiceSid, + messageCreator = code => `This is your authentication code: ${code}`, + }: TwilioSmsCodeProviderOptions) { + this.twilio = new Twilio(sid, secret); + this.phoneNumber = phoneNumber; + this.messagingServiceSid = messagingServiceSid; + this.messageCreator = messageCreator; + } + + public async sendToClient(serviceId: string, code: string): Promise { + const options: any = { + body: this.messageCreator(code), + to: serviceId, + }; + + if (this.phoneNumber) { + options.from = this.phoneNumber; + } else if (this.messagingServiceSid) { + options.messagingServiceSid = this.messagingServiceSid; + } else { + throw new Error('Not enough twilio credentials'); + } + + await this.twilio.messages.create(options); + } +} diff --git a/packages/code-provider-sms/src/index.ts b/packages/code-provider-sms/src/index.ts new file mode 100644 index 000000000..f5fe1a68e --- /dev/null +++ b/packages/code-provider-sms/src/index.ts @@ -0,0 +1,4 @@ +import CodeProviderSMS from './code-provider-sms'; + +export default CodeProviderSMS; +export { CodeProviderSMS }; diff --git a/packages/code-provider-sms/tsconfig.json b/packages/code-provider-sms/tsconfig.json new file mode 100644 index 000000000..4ec56d0f8 --- /dev/null +++ b/packages/code-provider-sms/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./lib", + "importHelpers": true + }, + "exclude": ["node_modules", "__tests__", "lib"] +} diff --git a/packages/code/README.md b/packages/code/README.md new file mode 100644 index 000000000..4a7bb4e63 --- /dev/null +++ b/packages/code/README.md @@ -0,0 +1,30 @@ +# @accounts/code + +## Install + +``` +yarn add @accounts/code +``` + +## Usage + +```js +import { AccountsServer } from '@accounts/server'; +import { AccountsCode } from '@accounts/code'; + +const codeProvider = '...'; + +export const accountsCode = new AccountsCode({ + codeProvider, + // options +}); + +const accountsServer = new AccountsServer( + { + // options + }, + { + code: accountsCode, + } +); +``` diff --git a/packages/code/package.json b/packages/code/package.json new file mode 100644 index 000000000..7a5b923e2 --- /dev/null +++ b/packages/code/package.json @@ -0,0 +1,32 @@ +{ + "name": "@accounts/code", + "version": "0.18.0", + "license": "MIT", + "main": "lib/index.js", + "typings": "lib/index.d.ts", + "scripts": { + "clean": "rimraf lib", + "start": "tsc --watch", + "precompile": "yarn clean", + "compile": "tsc", + "prepublishOnly": "yarn compile", + "testonly": "jest --coverage", + "coverage": "jest --coverage" + }, + "jest": { + "testEnvironment": "node", + "preset": "ts-jest" + }, + "dependencies": { + "@accounts/types": "^0.18.0", + "lodash": "^4.17.15", + "randomstring": "^1.1.5", + "tslib": "1.10.0" + }, + "devDependencies": { + "@types/randomstring": "^1.1.6" + }, + "peerDependencies": { + "@accounts/server": "^0.18.0" + } +} diff --git a/packages/code/src/accounts-code.ts b/packages/code/src/accounts-code.ts new file mode 100644 index 000000000..44f310a03 --- /dev/null +++ b/packages/code/src/accounts-code.ts @@ -0,0 +1,94 @@ +import { AuthenticationService, DatabaseInterface, User } from '@accounts/types'; +import { AccountsServer } from '@accounts/server'; + +import { CodeGenerator, CodeProvider, CodeHash, ErrorMessages, CodeLoginType } from './types'; +import SimpleCodeHash from './utils/simple-code-hash'; +import RandomstringCodeGenerator from './utils/randomstring-code-generator'; +import { errors } from './errors'; + +const DEFAULT_EXPIRY = 20 * 60 * 1000; // 20 minutes in milliseconds + +export interface AccountsCodeOptions { + codeGenerator?: CodeGenerator; + codeProvider: CodeProvider; + codeHash?: CodeHash; + expiry?: number; + errors?: ErrorMessages; +} + +interface DBService { + id: string; + code: string; + expiry: number; +} + +const defaultOptions = { + codeGenerator: new RandomstringCodeGenerator({ length: 4, charset: 'numeric' }), + codeHash: new SimpleCodeHash() as CodeHash, + expiry: DEFAULT_EXPIRY, + errors, +}; + +export default class CodeService implements AuthenticationService { + public serviceName = 'code'; + public server!: AccountsServer; + private db!: DatabaseInterface; + private options: AccountsCodeOptions & typeof defaultOptions; + + constructor(options: AccountsCodeOptions) { + this.options = { ...defaultOptions, ...options }; + } + + public setStore(store: DatabaseInterface) { + this.db = store; + } + + public async prepareAuthentication(serviceId: string) { + const user = await this.db.findUserByServiceId(this.serviceName, serviceId); + + if (!user) { + throw new Error(this.options.errors.userNotFound); + } + + const newCode = await this.options.codeGenerator.generate(); + const hashedCode = this.options.codeHash.hash(newCode); + + const dbService: DBService = { + id: serviceId, + code: hashedCode, + expiry: Date.now() + this.options.expiry, + }; + + await this.db.setService(user.id, this.serviceName, dbService); + + try { + await this.options.codeProvider.sendToClient(serviceId, newCode); + } catch (e) { + throw new Error(this.options.errors.failedToProvideCode); + } + } + + public async authenticate({ serviceId, code }: CodeLoginType): Promise { + const user = await this.db.findUserByServiceId(this.serviceName, serviceId); + + if (!user) { + throw new Error(this.options.errors.userNotFound); + } + + if (!user.services || !(user.services as any)[this.serviceName]) { + throw new Error(this.options.errors.codeWasNotFound); + } + + const { code: serviceCode, expiry }: DBService = (user.services as any)[this.serviceName]; + + if (serviceCode !== code) { + throw new Error(this.options.errors.wrongCode); + } + + if (expiry < Date.now()) { + throw new Error(this.options.errors.codeExpired); + } + + return user; + } +} diff --git a/packages/code/src/errors.ts b/packages/code/src/errors.ts new file mode 100644 index 000000000..6d615253a --- /dev/null +++ b/packages/code/src/errors.ts @@ -0,0 +1,9 @@ +import { ErrorMessages } from './types'; + +export const errors: ErrorMessages = { + userNotFound: 'User not found', + codeExpired: 'Code is expired', + codeWasNotFound: 'Code not found', + wrongCode: 'Wrong code', + failedToProvideCode: 'Failed to deliver code to the client', +}; diff --git a/packages/code/src/index.ts b/packages/code/src/index.ts new file mode 100644 index 000000000..dc09c99ad --- /dev/null +++ b/packages/code/src/index.ts @@ -0,0 +1,5 @@ +import AccountsCode from './accounts-code'; +export * from './types'; + +export default AccountsCode; +export { AccountsCode }; diff --git a/packages/code/src/types/code-generator.ts b/packages/code/src/types/code-generator.ts new file mode 100644 index 000000000..05f807b61 --- /dev/null +++ b/packages/code/src/types/code-generator.ts @@ -0,0 +1,3 @@ +export interface CodeGenerator { + generate(): Promise; +} diff --git a/packages/code/src/types/code-hash.ts b/packages/code/src/types/code-hash.ts new file mode 100644 index 000000000..ebd264d2d --- /dev/null +++ b/packages/code/src/types/code-hash.ts @@ -0,0 +1,5 @@ +export interface CodeHash { + hash(code: string): string; + + verify(code: string, hash: string): boolean; +} diff --git a/packages/code/src/types/code-login-type.ts b/packages/code/src/types/code-login-type.ts new file mode 100644 index 000000000..4b194c893 --- /dev/null +++ b/packages/code/src/types/code-login-type.ts @@ -0,0 +1,4 @@ +export interface CodeLoginType { + serviceId: string; + code: string; +} diff --git a/packages/code/src/types/code-provider.ts b/packages/code/src/types/code-provider.ts new file mode 100644 index 000000000..6bec16b3d --- /dev/null +++ b/packages/code/src/types/code-provider.ts @@ -0,0 +1,3 @@ +export interface CodeProvider { + sendToClient(serviceId: string, code: string): Promise; +} diff --git a/packages/code/src/types/error-messages.ts b/packages/code/src/types/error-messages.ts new file mode 100644 index 000000000..4bcb6b892 --- /dev/null +++ b/packages/code/src/types/error-messages.ts @@ -0,0 +1,7 @@ +export interface ErrorMessages { + userNotFound: string; + codeWasNotFound: string; + wrongCode: string; + codeExpired: string; + failedToProvideCode: string; +} diff --git a/packages/code/src/types/index.ts b/packages/code/src/types/index.ts new file mode 100644 index 000000000..6de31d741 --- /dev/null +++ b/packages/code/src/types/index.ts @@ -0,0 +1,5 @@ +export { ErrorMessages } from './error-messages'; +export { CodeGenerator } from './code-generator'; +export { CodeProvider } from './code-provider'; +export { CodeHash } from './code-hash'; +export { CodeLoginType } from './code-login-type'; diff --git a/packages/code/src/utils/randomstring-code-generator.ts b/packages/code/src/utils/randomstring-code-generator.ts new file mode 100644 index 000000000..accd771e6 --- /dev/null +++ b/packages/code/src/utils/randomstring-code-generator.ts @@ -0,0 +1,17 @@ +import randomstring from 'randomstring'; + +import { CodeGenerator } from '../types'; + +export type RandomstringOptions = randomstring.GenerateOptions; + +export default class RandomstringCodeGenerator implements CodeGenerator { + private options?: RandomstringOptions; + + constructor(options?: RandomstringOptions) { + this.options = options; + } + + public async generate(): Promise { + return randomstring.generate(this.options); + } +} diff --git a/packages/code/src/utils/simple-code-hash.ts b/packages/code/src/utils/simple-code-hash.ts new file mode 100644 index 000000000..6736ee99e --- /dev/null +++ b/packages/code/src/utils/simple-code-hash.ts @@ -0,0 +1,22 @@ +import crypto from 'crypto'; + +import { CodeHash } from '../types'; + +export default class SimpleCodeHash implements CodeHash { + public hash(code: string): string { + return this._hash(code); + } + + public verify(code: string, hash: string): boolean { + const hashedCode = this._hash(code); + + return hashedCode === hash; + } + + private _hash(code: string): string { + const hash = crypto.createHash('sha256'); + hash.update(code); + + return hash.digest('base64'); + } +} diff --git a/packages/code/tsconfig.json b/packages/code/tsconfig.json new file mode 100644 index 000000000..4ec56d0f8 --- /dev/null +++ b/packages/code/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./lib", + "importHelpers": true + }, + "exclude": ["node_modules", "__tests__", "lib"] +} diff --git a/yarn.lock b/yarn.lock index 069667504..ab1564e6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1628,6 +1628,15 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" +"@types/express@^4.16.1": + version "4.17.1" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.1.tgz#4cf7849ae3b47125a567dfee18bfca4254b88c5c" + integrity sha512-VfH/XCP0QbQk5B5puLqTLEeFgR8lfCJHZJKkInZ9mkYd+u8byX0kztXEQxEk4wZXJs8HI+7km2ALXjn4YKcX9w== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/serve-static" "*" + "@types/glob@7.1.1", "@types/glob@^7.1.1": version "7.1.1" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" @@ -1785,6 +1794,11 @@ dependencies: "@types/react" "*" +"@types/randomstring@^1.1.6": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@types/randomstring/-/randomstring-1.1.6.tgz#45cdc060a6f043d610bcd46503a6887db2a209c3" + integrity sha512-XRIZIMTxjcUukqQcYBdpFWGbcRDyNBXrvTEtTYgFMIbBNUVt+9mCKsU+jUUDLeFO/RXopUgR5OLiBqbY18vSHQ== + "@types/range-parser@*": version "1.2.3" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" @@ -2763,6 +2777,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array-uniq@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.2.tgz#5fcc373920775723cfd64d65c64bef53bf9eba6d" + integrity sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0= + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -2778,7 +2797,7 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -asap@~2.0.6: +asap@^2.0.0, asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= @@ -4933,6 +4952,11 @@ depd@~2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +deprecate@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/deprecate/-/deprecate-1.0.0.tgz#661490ed2428916a6c8883d8834e5646f4e4a4a8" + integrity sha1-ZhSQ7SQokWpsiIPYg05WRvTkpKg= + deprecated-decorator@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz#00966317b7a12fe92f3cc831f7583af329b86c37" @@ -9485,7 +9509,7 @@ modify-values@^1.0.0: resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== -moment@^2.6.0: +moment@^2.24.0, moment@^2.6.0: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== @@ -10643,6 +10667,11 @@ pnp-webpack-plugin@1.2.1: dependencies: ts-pnp "^1.0.0" +pop-iterate@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pop-iterate/-/pop-iterate-1.0.1.tgz#ceacfdab4abf353d7a0f2aaa2c1fc7b3f9413ba3" + integrity sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M= + popper.js@^1.14.1: version "1.15.0" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.15.0.tgz#5560b99bbad7647e9faa475c6b8056621f5a4ff2" @@ -11531,6 +11560,15 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +q@2.0.x: + version "2.0.3" + resolved "https://registry.yarnpkg.com/q/-/q-2.0.3.tgz#75b8db0255a1a5af82f58c3f3aaa1efec7d0d134" + integrity sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ= + dependencies: + asap "^2.0.0" + pop-iterate "^1.0.1" + weak-map "^1.0.5" + q@^1.1.2, q@^1.4.1, q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -11606,6 +11644,13 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" +randomstring@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/randomstring/-/randomstring-1.1.5.tgz#6df0628f75cbd5932930d9fe3ab4e956a18518c3" + integrity sha1-bfBij3XL1ZMpMNn+OrTpVqGFGMM= + dependencies: + array-uniq "1.0.2" + range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -12324,6 +12369,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +rootpath@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/rootpath/-/rootpath-0.1.2.tgz#5b379a87dca906e9b91d690a599439bef267ea6b" + integrity sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms= + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -12462,6 +12512,11 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" +scmp@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/scmp/-/scmp-2.0.0.tgz#247110ef22ccf897b13a3f0abddb52782393cd6a" + integrity sha1-JHEQ7yLM+JexOj8KvdtSeCOTzWo= + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -13720,6 +13775,22 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +twilio@^3.33.3: + version "3.33.3" + resolved "https://registry.yarnpkg.com/twilio/-/twilio-3.33.3.tgz#ad610c19914ba8f9950b672c62eddd69b6349b54" + integrity sha512-xw/NjPXJ7JoeDSC1Eq6rkxlRdgJhiLeE8BM2KeI14g9ir5Hb1ui9YKYacqnnv/Hf9ZgLvtz4O/HWXzRItg7kqA== + dependencies: + "@types/express" "^4.16.1" + deprecate "1.0.0" + jsonwebtoken "^8.5.1" + lodash "^4.17.11" + moment "^2.24.0" + q "2.0.x" + request "^2.88.0" + rootpath "0.1.2" + scmp "2.0.0" + xmlbuilder "9.0.1" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -14126,6 +14197,11 @@ wcwidth@^1.0.0: dependencies: defaults "^1.0.3" +weak-map@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/weak-map/-/weak-map-1.0.5.tgz#79691584d98607f5070bd3b70a40e6bb22e401eb" + integrity sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes= + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -14601,6 +14677,11 @@ xml2js@^0.4.17: sax ">=0.6.0" xmlbuilder "~9.0.1" +xmlbuilder@9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.1.tgz#91cd70897755363eba57c12ddeeab4a341a61f65" + integrity sha1-kc1wiXdVNj66V8Et3uq0o0GmH2U= + xmlbuilder@~9.0.1: version "9.0.7" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" From 520f525b311b7daa06ca577f4f056ee04c1c8bc6 Mon Sep 17 00:00:00 2001 From: ozsay Date: Wed, 21 Aug 2019 14:56:00 +0300 Subject: [PATCH 02/10] fix compilation --- packages/code-provider-sms/package.json | 1 + packages/code/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/code-provider-sms/package.json b/packages/code-provider-sms/package.json index aec44204f..c0f3f3dfa 100644 --- a/packages/code-provider-sms/package.json +++ b/packages/code-provider-sms/package.json @@ -21,6 +21,7 @@ "twilio": "^3.33.3" }, "devDependencies": { + "@accounts/code": "^0.18.0" }, "peerDependencies": { "@accounts/code": "^0.18.0" diff --git a/packages/code/package.json b/packages/code/package.json index 7a5b923e2..55e104a57 100644 --- a/packages/code/package.json +++ b/packages/code/package.json @@ -24,6 +24,7 @@ "tslib": "1.10.0" }, "devDependencies": { + "@accounts/server": "^0.18.0", "@types/randomstring": "^1.1.6" }, "peerDependencies": { From ef901abb344d0fb853a3fee3da3714b6bd2e3fc0 Mon Sep 17 00:00:00 2001 From: ozsay Date: Wed, 21 Aug 2019 15:02:42 +0300 Subject: [PATCH 03/10] clear code when authentication is successful --- packages/code/src/accounts-code.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/code/src/accounts-code.ts b/packages/code/src/accounts-code.ts index 44f310a03..87d799309 100644 --- a/packages/code/src/accounts-code.ts +++ b/packages/code/src/accounts-code.ts @@ -18,8 +18,8 @@ export interface AccountsCodeOptions { interface DBService { id: string; - code: string; - expiry: number; + code?: string; + expiry?: number; } const defaultOptions = { @@ -85,10 +85,12 @@ export default class CodeService implements AuthenticationService { throw new Error(this.options.errors.wrongCode); } - if (expiry < Date.now()) { + if (expiry && expiry < Date.now()) { throw new Error(this.options.errors.codeExpired); } + await this.db.setService(user.id, this.serviceName, { id: serviceId }); + return user; } } From 4e55972d10ffc296612a0f430f1a48883ef0fd4d Mon Sep 17 00:00:00 2001 From: ozsay Date: Wed, 21 Aug 2019 18:49:50 +0300 Subject: [PATCH 04/10] add tests --- packages/code-provider-sms/package.json | 4 +- packages/code/__tests__/accounts-code.ts | 195 ++++++++++++++++++ packages/code/package.json | 5 +- packages/code/src/accounts-code.ts | 6 +- .../src/utils/randomstring-code-generator.ts | 2 +- packages/code/src/utils/simple-code-hash.ts | 4 +- 6 files changed, 209 insertions(+), 7 deletions(-) create mode 100644 packages/code/__tests__/accounts-code.ts diff --git a/packages/code-provider-sms/package.json b/packages/code-provider-sms/package.json index c0f3f3dfa..d6df919e0 100644 --- a/packages/code-provider-sms/package.json +++ b/packages/code-provider-sms/package.json @@ -9,9 +9,7 @@ "start": "tsc --watch", "precompile": "yarn clean", "compile": "tsc", - "prepublishOnly": "yarn compile", - "testonly": "jest --coverage", - "coverage": "jest --coverage" + "prepublishOnly": "yarn compile" }, "jest": { "testEnvironment": "node", diff --git a/packages/code/__tests__/accounts-code.ts b/packages/code/__tests__/accounts-code.ts new file mode 100644 index 000000000..1916d10e0 --- /dev/null +++ b/packages/code/__tests__/accounts-code.ts @@ -0,0 +1,195 @@ +import { AccountsCode, CodeProvider, ErrorMessages } from '../src'; + +function createCodeProvider(success: boolean): CodeProvider { + return { + sendToClient: jest.fn(() => (success ? Promise.resolve() : Promise.reject())), + }; +} + +const errors: ErrorMessages = { + userNotFound: '0', + codeExpired: '1', + codeWasNotFound: '2', + wrongCode: '3', + failedToProvideCode: '4', +}; + +describe('AccountsCode', () => { + describe('preparation', () => { + it('throws error when no user is found', async () => { + const code = new AccountsCode({ codeProvider: createCodeProvider(true), errors }); + const findUserByServiceId = jest.fn(() => Promise.resolve()); + code.setStore({ findUserByServiceId } as any); + + try { + await code.prepareAuthentication('1234'); + } catch (e) { + expect(e.message).toEqual(errors.userNotFound); + } + + expect.assertions(1); + }); + + it('throws error when failed to send code to the client', async () => { + const code = new AccountsCode({ codeProvider: createCodeProvider(false), errors }); + + const user = { + id: '123', + }; + + const findUserByServiceId = jest.fn(() => Promise.resolve(user)); + const setService = jest.fn(() => Promise.resolve()); + code.setStore({ findUserByServiceId, setService } as any); + + try { + await code.prepareAuthentication('1234'); + } catch (e) { + expect(e.message).toEqual(errors.failedToProvideCode); + } + + expect.assertions(1); + }); + + it('completes successfully', async () => { + const code = new AccountsCode({ codeProvider: createCodeProvider(true), errors }); + + const user = { + id: '123', + }; + + const findUserByServiceId = jest.fn(() => Promise.resolve(user)); + const setService = jest.fn(() => Promise.resolve()); + code.setStore({ findUserByServiceId, setService } as any); + + const res = await code.prepareAuthentication('1234'); + + expect(res).toBeUndefined(); + expect(setService).toHaveBeenCalledTimes(1); + expect(setService).toHaveBeenCalledWith('123', code.serviceName, { + id: '1234', + code: expect.any(String), + expiry: expect.any(Number), + }); + }); + }); + + describe('Authentication', () => { + const code = new AccountsCode({ codeProvider: createCodeProvider(true), errors }); + + it('throws error when no user is found', async () => { + const findUserByServiceId = jest.fn(() => Promise.resolve(null)); + code.setStore({ findUserByServiceId } as any); + + try { + await code.authenticate({ serviceId: '1234', code: '2233' }); + } catch (e) { + expect(e.message).toEqual(errors.userNotFound); + } + + expect.assertions(1); + }); + + it('throws error when no code is found', async () => { + const findUserByServiceId = jest.fn(() => + Promise.resolve({ + id: '123', + }) + ); + code.setStore({ findUserByServiceId } as any); + + try { + await code.authenticate({ serviceId: '1234', code: '2233' }); + } catch (e) { + expect(e.message).toEqual(errors.codeWasNotFound); + } + + expect.assertions(1); + }); + + it('throws error when no code is found 2', async () => { + const findUserByServiceId = jest.fn(() => + Promise.resolve({ + id: '123', + services: { + [code.serviceName]: {}, + }, + }) + ); + code.setStore({ findUserByServiceId } as any); + + try { + await code.authenticate({ serviceId: '1234', code: '2233' }); + } catch (e) { + expect(e.message).toEqual(errors.codeWasNotFound); + } + + expect.assertions(1); + }); + + it('throws error when code is wrong', async () => { + const findUserByServiceId = jest.fn(() => + Promise.resolve({ + id: '123', + services: { + [code.serviceName]: { + code: '1111', + }, + }, + }) + ); + code.setStore({ findUserByServiceId } as any); + + try { + await code.authenticate({ serviceId: '1234', code: '2233' }); + } catch (e) { + expect(e.message).toEqual(errors.wrongCode); + } + + expect.assertions(1); + }); + + it('throws error when code is expired', async () => { + const findUserByServiceId = jest.fn(() => + Promise.resolve({ + id: '123', + services: { + [code.serviceName]: { + code: 'vKw3G1T1mUWhSqSeLkCOXW5NvFk4f12M/GsBXUDVuwI=', + expiry: Date.now() - 10000, + }, + }, + }) + ); + code.setStore({ findUserByServiceId } as any); + + try { + await code.authenticate({ serviceId: '1234', code: '2233' }); + } catch (e) { + expect(e.message).toEqual(errors.codeExpired); + } + + expect.assertions(1); + }); + + it('authenticates successfully and returns user', async () => { + const user = { + id: '123', + services: { + [code.serviceName]: { + code: 'vKw3G1T1mUWhSqSeLkCOXW5NvFk4f12M/GsBXUDVuwI=', + expiry: Date.now() + 10000, + }, + }, + }; + const findUserByServiceId = jest.fn(() => Promise.resolve(user)); + const setService = jest.fn(() => Promise.resolve()); + code.setStore({ findUserByServiceId, setService } as any); + + const res = await code.authenticate({ serviceId: '1234', code: '2233' }); + + expect(res).toEqual(user); + expect(setService).toHaveBeenCalledTimes(1); + expect(setService).toHaveBeenCalledWith('123', code.serviceName, { id: '1234' }); + }); + }); +}); diff --git a/packages/code/package.json b/packages/code/package.json index 55e104a57..f91465e01 100644 --- a/packages/code/package.json +++ b/packages/code/package.json @@ -25,7 +25,10 @@ }, "devDependencies": { "@accounts/server": "^0.18.0", - "@types/randomstring": "^1.1.6" + "@types/randomstring": "^1.1.6", + "@types/jest": "24.0.16", + "jest": "24.8.0", + "rimraf": "2.6.3" }, "peerDependencies": { "@accounts/server": "^0.18.0" diff --git a/packages/code/src/accounts-code.ts b/packages/code/src/accounts-code.ts index 87d799309..4e22bc873 100644 --- a/packages/code/src/accounts-code.ts +++ b/packages/code/src/accounts-code.ts @@ -81,7 +81,11 @@ export default class CodeService implements AuthenticationService { const { code: serviceCode, expiry }: DBService = (user.services as any)[this.serviceName]; - if (serviceCode !== code) { + if (!serviceCode) { + throw new Error(this.options.errors.codeWasNotFound); + } + + if (!this.options.codeHash.verify(code, serviceCode)) { throw new Error(this.options.errors.wrongCode); } diff --git a/packages/code/src/utils/randomstring-code-generator.ts b/packages/code/src/utils/randomstring-code-generator.ts index accd771e6..b9e97a27a 100644 --- a/packages/code/src/utils/randomstring-code-generator.ts +++ b/packages/code/src/utils/randomstring-code-generator.ts @@ -1,4 +1,4 @@ -import randomstring from 'randomstring'; +import * as randomstring from 'randomstring'; import { CodeGenerator } from '../types'; diff --git a/packages/code/src/utils/simple-code-hash.ts b/packages/code/src/utils/simple-code-hash.ts index 6736ee99e..cd9b9a6ce 100644 --- a/packages/code/src/utils/simple-code-hash.ts +++ b/packages/code/src/utils/simple-code-hash.ts @@ -1,4 +1,4 @@ -import crypto from 'crypto'; +import * as crypto from 'crypto'; import { CodeHash } from '../types'; @@ -10,6 +10,8 @@ export default class SimpleCodeHash implements CodeHash { public verify(code: string, hash: string): boolean { const hashedCode = this._hash(code); + console.log(code, hashedCode); + return hashedCode === hash; } From 566792b97d31bf643235da162487e3c474110d3e Mon Sep 17 00:00:00 2001 From: ozsay Date: Wed, 21 Aug 2019 18:52:40 +0300 Subject: [PATCH 05/10] fix --- packages/code/src/utils/simple-code-hash.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/code/src/utils/simple-code-hash.ts b/packages/code/src/utils/simple-code-hash.ts index cd9b9a6ce..e9a83750b 100644 --- a/packages/code/src/utils/simple-code-hash.ts +++ b/packages/code/src/utils/simple-code-hash.ts @@ -10,8 +10,6 @@ export default class SimpleCodeHash implements CodeHash { public verify(code: string, hash: string): boolean { const hashedCode = this._hash(code); - console.log(code, hashedCode); - return hashedCode === hash; } From a60f702de578b2458922095deebc54981658ec11 Mon Sep 17 00:00:00 2001 From: ozsay Date: Mon, 26 Aug 2019 11:32:43 +0300 Subject: [PATCH 06/10] renaming package to twilio --- packages/code-provider-sms/src/index.ts | 4 ---- .../{code-provider-sms => code-provider-twilio}/README.md | 8 ++++---- .../package.json | 2 +- .../src/code-provider-twilio.ts} | 0 packages/code-provider-twilio/src/index.ts | 4 ++++ .../tsconfig.json | 0 6 files changed, 9 insertions(+), 9 deletions(-) delete mode 100644 packages/code-provider-sms/src/index.ts rename packages/{code-provider-sms => code-provider-twilio}/README.md (69%) rename packages/{code-provider-sms => code-provider-twilio}/package.json (92%) rename packages/{code-provider-sms/src/code-provider-sms.ts => code-provider-twilio/src/code-provider-twilio.ts} (100%) create mode 100644 packages/code-provider-twilio/src/index.ts rename packages/{code-provider-sms => code-provider-twilio}/tsconfig.json (100%) diff --git a/packages/code-provider-sms/src/index.ts b/packages/code-provider-sms/src/index.ts deleted file mode 100644 index f5fe1a68e..000000000 --- a/packages/code-provider-sms/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import CodeProviderSMS from './code-provider-sms'; - -export default CodeProviderSMS; -export { CodeProviderSMS }; diff --git a/packages/code-provider-sms/README.md b/packages/code-provider-twilio/README.md similarity index 69% rename from packages/code-provider-sms/README.md rename to packages/code-provider-twilio/README.md index 215545f37..ad02388fd 100644 --- a/packages/code-provider-sms/README.md +++ b/packages/code-provider-twilio/README.md @@ -1,9 +1,9 @@ -# @accounts/code-provider-sms +# @accounts/code-provider-twilio ## Install ``` -yarn add @accounts/code-provider-sms +yarn add @accounts/code-provider-twilio ``` ## Usage @@ -11,9 +11,9 @@ yarn add @accounts/code-provider-sms ```js import { AccountsServer } from '@accounts/server'; import { AccountsCode } from '@accounts/code'; -import { CodeProviderSMS } from '@accounts/code-provider-sms'; +import { CodeProviderTwilio } from '@accounts/code-provider-twilio'; -const codeProvider = new CodeProviderSMS({ +const codeProvider = new CodeProviderTwilio({ sid: 'TWILIO_SID', secret: 'TWILIO_SECRET', phoneNumber: 'TWILIO_FROM_PHONE_NUMBER', diff --git a/packages/code-provider-sms/package.json b/packages/code-provider-twilio/package.json similarity index 92% rename from packages/code-provider-sms/package.json rename to packages/code-provider-twilio/package.json index d6df919e0..c3361a832 100644 --- a/packages/code-provider-sms/package.json +++ b/packages/code-provider-twilio/package.json @@ -1,5 +1,5 @@ { - "name": "@accounts/code-provider-sms", + "name": "@accounts/code-provider-twilio", "version": "0.18.0", "license": "MIT", "main": "lib/index.js", diff --git a/packages/code-provider-sms/src/code-provider-sms.ts b/packages/code-provider-twilio/src/code-provider-twilio.ts similarity index 100% rename from packages/code-provider-sms/src/code-provider-sms.ts rename to packages/code-provider-twilio/src/code-provider-twilio.ts diff --git a/packages/code-provider-twilio/src/index.ts b/packages/code-provider-twilio/src/index.ts new file mode 100644 index 000000000..c5e82924f --- /dev/null +++ b/packages/code-provider-twilio/src/index.ts @@ -0,0 +1,4 @@ +import CodeProviderTwilio from './code-provider-twilio'; + +export default CodeProviderTwilio; +export { CodeProviderTwilio }; diff --git a/packages/code-provider-sms/tsconfig.json b/packages/code-provider-twilio/tsconfig.json similarity index 100% rename from packages/code-provider-sms/tsconfig.json rename to packages/code-provider-twilio/tsconfig.json From 92616b50a201ad63bceec7eae4cf04f87743607d Mon Sep 17 00:00:00 2001 From: ozsay Date: Mon, 2 Sep 2019 15:18:48 +0300 Subject: [PATCH 07/10] api docs --- website/docs/strategies/code.md | 81 +++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 website/docs/strategies/code.md diff --git a/website/docs/strategies/code.md b/website/docs/strategies/code.md new file mode 100644 index 000000000..ecc69c79a --- /dev/null +++ b/website/docs/strategies/code.md @@ -0,0 +1,81 @@ +--- +title: Code +--- + +[Github](https://github.com/accounts-js/accounts/tree/master/packages/code) | +[npm](https://www.npmjs.com/package/@accounts/code) + +The `@accounts/code` package provide a secure system for a code based login strategy. The code is being created prior to the login request and sent to the client via a provider (SMS provider for example) + +## Install + +``` +# With yarn +yarn add @accounts/code + +# Or if you use npm +npm install @accounts/code --save +``` + +A provider is also needed. You can use `accounts` providers or create your own. + +## Usage + +```javascript +import AccountsServer from '@accounts/server'; +import AccountsCode from '@accounts/code'; + +// We create a new code instance with a code provider and extra configuration +const accountsCode = new AccountsCode(provider, ...config); + +// We pass the code instance the AccountsServer service list +const accountsServer = new AccountsServer(...config, { + code: accountsCode, +}); +``` + +## Providers + +### twilio + +#### Install + +``` +# With yarn +yarn add @accounts/code-provider-twilio + +# Or if you use npm +npm install @accounts/code-provider-twilio --save +``` + +#### Usage + +```js +import { AccountsServer } from '@accounts/server'; +import { AccountsCode } from '@accounts/code'; +import { CodeProviderTwilio } from '@accounts/code-provider-twilio'; + +const codeProvider = new CodeProviderTwilio({ + sid: 'TWILIO_SID', + secret: 'TWILIO_SECRET', + phoneNumber: 'TWILIO_FROM_PHONE_NUMBER', +}); + +export const accountsCode = new AccountsCode({ + codeProvider, + // options +}); + +const accountsServer = new AccountsServer( + { + // options + }, + { + code: accountsCode, + } +); +``` + +## Create a custom provider + +In order to create a custom code provider you need to implement the `CodeProvider` interface from `@accounts/code`. From 8dba8444d6bca5b274558e554988b5b35ebb47ba Mon Sep 17 00:00:00 2001 From: ozsay Date: Mon, 2 Sep 2019 15:40:21 +0300 Subject: [PATCH 08/10] add updateUser function --- packages/code/src/accounts-code.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/code/src/accounts-code.ts b/packages/code/src/accounts-code.ts index 4e22bc873..db2bb4611 100644 --- a/packages/code/src/accounts-code.ts +++ b/packages/code/src/accounts-code.ts @@ -43,6 +43,14 @@ export default class CodeService implements AuthenticationService { this.db = store; } + public async updateUserServiceId(userId: string, serviceId: string): Promise { + const dbService: DBService = { + id: serviceId, + }; + + await this.db.setService(userId, this.serviceName, dbService); + } + public async prepareAuthentication(serviceId: string) { const user = await this.db.findUserByServiceId(this.serviceName, serviceId); From b10e18251d75ecbc0a85e840d704705d9e56b6dd Mon Sep 17 00:00:00 2001 From: ozsay Date: Mon, 2 Sep 2019 15:45:56 +0300 Subject: [PATCH 09/10] yarn.lock --- yarn.lock | 60 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index dad369f6d..a251c9bba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,19 @@ # yarn lockfile v1 +"@accounts/server@^0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@accounts/server/-/server-0.18.0.tgz#9bcccae7691f7ac392718bb9b6a171d66828737b" + integrity sha512-wO5/jlc6dVcHFmsqi/FmgKLyli7wkMGwq0gJaBgNev2HC6PJV9O3oUx546Rj8L/QrYqPGjWQ/qGFF+jvCogfCg== + dependencies: + "@accounts/types" "^0.18.0" + "@types/jsonwebtoken" "8.3.2" + emittery "0.4.1" + jsonwebtoken "8.5.1" + jwt-decode "2.2.0" + lodash "4.17.15" + tslib "1.10.0" + "@accounts/tslint-config-accounts@0.0.9": version "0.0.9" resolved "https://registry.yarnpkg.com/@accounts/tslint-config-accounts/-/tslint-config-accounts-0.0.9.tgz#a2073361c4127ba7c8662cd72e08a28a794a44df" @@ -10,6 +23,13 @@ tslint-config-prettier "^1.1.0" tslint-eslint-rules "^4.1.1" +"@accounts/types@^0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@accounts/types/-/types-0.18.0.tgz#5c44287415cf714a726ef54c210771c535635cc3" + integrity sha512-qWm4HKFlM5iv4dDMs5XtjCAJufRVDN+btD7coE2phnI/uVCQvm5slPL7veZMFKyuaiK+1C64qzIU5z1J8g18ww== + dependencies: + tslib "1.10.0" + "@apollographql/apollo-tools@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@apollographql/apollo-tools/-/apollo-tools-0.4.0.tgz#8a1a0ab7a0bb12ccc03b72e4a104cfa5d969fd5f" @@ -2285,7 +2305,7 @@ "@types/express" "*" "@types/node" "*" -"@types/express@*", "@types/express@4.17.1": +"@types/express@*", "@types/express@4.17.1", "@types/express@^4.16.1": version "4.17.1" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.1.tgz#4cf7849ae3b47125a567dfee18bfca4254b88c5c" integrity sha512-VfH/XCP0QbQk5B5puLqTLEeFgR8lfCJHZJKkInZ9mkYd+u8byX0kztXEQxEk4wZXJs8HI+7km2ALXjn4YKcX9w== @@ -2294,14 +2314,12 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" -"@types/express@^4.16.1": - version "4.17.1" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.1.tgz#4cf7849ae3b47125a567dfee18bfca4254b88c5c" - integrity sha512-VfH/XCP0QbQk5B5puLqTLEeFgR8lfCJHZJKkInZ9mkYd+u8byX0kztXEQxEk4wZXJs8HI+7km2ALXjn4YKcX9w== +"@types/fs-capacitor@*": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz#17113e25817f584f58100fb7a08eed288b81956e" + integrity sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ== dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "*" - "@types/serve-static" "*" + "@types/node" "*" "@types/glob@7.1.1", "@types/glob@^7.1.1": version "7.1.1" @@ -2369,6 +2387,13 @@ resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89" integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA== +"@types/jest@24.0.16": + version "24.0.16" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.16.tgz#8d3e406ec0f0dc1688d6711af3062ff9bd428066" + integrity sha512-JrAiyV+PPGKZzw6uxbI761cHZ0G7QMOHXPhtSpcl08rZH6CswXaaejckn3goFKmF7M3nzEoJ0lwYCbqLMmjziQ== + dependencies: + "@types/jest-diff" "*" + "@types/jest@24.0.18": version "24.0.18" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.18.tgz#9c7858d450c59e2164a8a9df0905fc5091944498" @@ -2381,6 +2406,13 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== +"@types/jsonwebtoken@8.3.2": + version "8.3.2" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.3.2.tgz#e3d5245197152346fae7ee87d5541aa5a92d0362" + integrity sha512-Mkjljd9DTpkPlrmGfTJvcP4aBU7yO2QmW7wNVhV4/6AEUxYoacqU7FJU/N0yFEHTsIrE4da3rUrjrR5ejicFmA== + dependencies: + "@types/node" "*" + "@types/jsonwebtoken@8.3.3": version "8.3.3" resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.3.3.tgz#eafeea8239c74b02263d204c0e1175d5cd0bb85f" @@ -10265,7 +10297,7 @@ modify-values@^1.0.0: resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== -moment@^2.24.0, moment@^2.6.0: +moment@^2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== @@ -12507,7 +12539,7 @@ q@2.0.x: pop-iterate "^1.0.1" weak-map "^1.0.5" -q@^1.1.2, q@^1.4.1, q@^1.5.1: +q@^1.1.2, q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= @@ -13516,6 +13548,14 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" +schema-utils@^2.0.0, schema-utils@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.2.0.tgz#48a065ce219e0cacf4631473159037b2c1ae82da" + integrity sha512-5EwsCNhfFTZvUreQhx/4vVQpJ/lnCAkgoIHLhSpp4ZirE+4hzFvdJi0FMub6hxbFVBJYSpeVVmon+2e7uEGRrA== + dependencies: + ajv "^6.10.2" + ajv-keywords "^3.4.1" + scmp@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/scmp/-/scmp-2.0.0.tgz#247110ef22ccf897b13a3f0abddb52782393cd6a" From 937f60aef010f39d05045c2f49a8bcdfc9379160 Mon Sep 17 00:00:00 2001 From: ozsay Date: Tue, 24 Sep 2019 11:14:46 +0300 Subject: [PATCH 10/10] update version --- packages/code-provider-twilio/package.json | 6 ++--- packages/code/package.json | 8 +++---- yarn.lock | 27 ---------------------- 3 files changed, 7 insertions(+), 34 deletions(-) diff --git a/packages/code-provider-twilio/package.json b/packages/code-provider-twilio/package.json index c3361a832..4cf2ca69c 100644 --- a/packages/code-provider-twilio/package.json +++ b/packages/code-provider-twilio/package.json @@ -1,6 +1,6 @@ { "name": "@accounts/code-provider-twilio", - "version": "0.18.0", + "version": "0.19.0", "license": "MIT", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -19,9 +19,9 @@ "twilio": "^3.33.3" }, "devDependencies": { - "@accounts/code": "^0.18.0" + "@accounts/code": "^0.19.0" }, "peerDependencies": { - "@accounts/code": "^0.18.0" + "@accounts/code": "^0.19.0" } } diff --git a/packages/code/package.json b/packages/code/package.json index f91465e01..ec779b6d7 100644 --- a/packages/code/package.json +++ b/packages/code/package.json @@ -1,6 +1,6 @@ { "name": "@accounts/code", - "version": "0.18.0", + "version": "0.19.0", "license": "MIT", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -18,19 +18,19 @@ "preset": "ts-jest" }, "dependencies": { - "@accounts/types": "^0.18.0", + "@accounts/types": "^0.19.0", "lodash": "^4.17.15", "randomstring": "^1.1.5", "tslib": "1.10.0" }, "devDependencies": { - "@accounts/server": "^0.18.0", + "@accounts/server": "^0.19.0", "@types/randomstring": "^1.1.6", "@types/jest": "24.0.16", "jest": "24.8.0", "rimraf": "2.6.3" }, "peerDependencies": { - "@accounts/server": "^0.18.0" + "@accounts/server": "^0.19.0" } } diff --git a/yarn.lock b/yarn.lock index 22ec30643..b54721c21 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,26 +2,6 @@ # yarn lockfile v1 -"@accounts/server@^0.18.0": - version "0.18.0" - resolved "https://registry.yarnpkg.com/@accounts/server/-/server-0.18.0.tgz#9bcccae7691f7ac392718bb9b6a171d66828737b" - integrity sha512-wO5/jlc6dVcHFmsqi/FmgKLyli7wkMGwq0gJaBgNev2HC6PJV9O3oUx546Rj8L/QrYqPGjWQ/qGFF+jvCogfCg== - dependencies: - "@accounts/types" "^0.18.0" - "@types/jsonwebtoken" "8.3.2" - emittery "0.4.1" - jsonwebtoken "8.5.1" - jwt-decode "2.2.0" - lodash "4.17.15" - tslib "1.10.0" - -"@accounts/types@^0.18.0": - version "0.18.0" - resolved "https://registry.yarnpkg.com/@accounts/types/-/types-0.18.0.tgz#5c44287415cf714a726ef54c210771c535635cc3" - integrity sha512-qWm4HKFlM5iv4dDMs5XtjCAJufRVDN+btD7coE2phnI/uVCQvm5slPL7veZMFKyuaiK+1C64qzIU5z1J8g18ww== - dependencies: - tslib "1.10.0" - "@apollographql/apollo-tools@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@apollographql/apollo-tools/-/apollo-tools-0.4.0.tgz#8a1a0ab7a0bb12ccc03b72e4a104cfa5d969fd5f" @@ -2395,13 +2375,6 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== -"@types/jsonwebtoken@8.3.2": - version "8.3.2" - resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.3.2.tgz#e3d5245197152346fae7ee87d5541aa5a92d0362" - integrity sha512-Mkjljd9DTpkPlrmGfTJvcP4aBU7yO2QmW7wNVhV4/6AEUxYoacqU7FJU/N0yFEHTsIrE4da3rUrjrR5ejicFmA== - dependencies: - "@types/node" "*" - "@types/jsonwebtoken@8.3.3": version "8.3.3" resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.3.3.tgz#eafeea8239c74b02263d204c0e1175d5cd0bb85f"