@live-change/secret-code-service 0.2.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +163 -0
  2. package/package.json +28 -0
package/index.js ADDED
@@ -0,0 +1,163 @@
1
+ const nodemailer = require('nodemailer')
2
+ const app = require("@live-change/framework").app()
3
+ const crypto = require('crypto')
4
+
5
+ const definition = app.createServiceDefinition({
6
+ name: "secretCode"
7
+ })
8
+ const config = definition.config
9
+
10
+ const MessageAuthentication = definition.foreignModel('messageAuthentication', 'Authentication')
11
+
12
+ const targetProperties = {
13
+ authentication: {
14
+ type: MessageAuthentication,
15
+ validation: ['nonEmpty']
16
+ }
17
+ }
18
+
19
+ const secretProperties = {
20
+ secretCode: {
21
+ type: String,
22
+ validation: ['nonEmpty']
23
+ }
24
+ }
25
+
26
+ const Code = definition.model({
27
+ name: "Code",
28
+ properties: {
29
+ ...targetProperties,
30
+ ...secretProperties,
31
+ expire: {
32
+ type: Date,
33
+ validation: ['nonEmpty']
34
+ }
35
+ },
36
+ indexes: {
37
+ byAuthenticationAndSecretCode: {
38
+ property: ['authentication', 'secretCode']
39
+ },
40
+ byAuthentication: {
41
+ property: 'authentication'
42
+ }
43
+ }
44
+ })
45
+
46
+ definition.event({
47
+ name: 'codeCreated',
48
+ execute({ code, authentication, secretCode, expire }) {
49
+ return Code.create({ id: code, authentication, secretCode, expire })
50
+ }
51
+ })
52
+
53
+ definition.event({
54
+ name: 'codeExpired',
55
+ execute({ code }) {
56
+ return Code.update(code, { date: new Date(Date.now() - 1000) })
57
+ }
58
+ })
59
+
60
+ definition.trigger({
61
+ name: "authenticationSecret",
62
+ properties: {
63
+ ...targetProperties
64
+ },
65
+ waitForEvents: true,
66
+ async execute({ authentication }, context, emit) {
67
+ const code = app.generateUid()
68
+ const digits = config.digits || 6
69
+ const secretCode = crypto.randomInt(0, Math.pow(10, digits)).toFixed().padStart(digits, '0')
70
+ const expire = new Date()
71
+ expire.setTime(Date.now() + (config.expireTime || 10*60*1000))
72
+ emit({
73
+ type: 'codeCreated',
74
+ code,
75
+ authentication,
76
+ secretCode, expire
77
+ })
78
+ return {
79
+ type: 'code',
80
+ code,
81
+ expire,
82
+ secret: {
83
+ secretCode
84
+ }
85
+ }
86
+ }
87
+ })
88
+
89
+ definition.trigger({
90
+ name: "refreshAuthenticationSecret",
91
+ properties: {
92
+ ...targetProperties
93
+ },
94
+ waitForEvents: true,
95
+ async execute({ authentication }, context, emit) {
96
+ const currentCode = await Code.indexObjectGet('byAuthentication', authentication)
97
+ if(currentCode) {
98
+ emit({ type: 'codeExpired', code: currentCode.id })
99
+ }
100
+ const code = app.generateUid()
101
+ const digits = config.digits || 6
102
+ const secretCode = crypto.randomInt(0, Math.pow(10, digits)).toFixed().padStart(digits, '0')
103
+ const expire = new Date()
104
+ expire.setTime(Date.now() + (config.expireTime || 24*60*60*1000))
105
+ emit({
106
+ type: 'codeCreated',
107
+ code,
108
+ authentication,
109
+ secretCode, expire
110
+ })
111
+ return {
112
+ type: 'code',
113
+ code,
114
+ expire,
115
+ secret: {
116
+ secretCode
117
+ }
118
+ }
119
+ }
120
+ })
121
+
122
+ definition.trigger({
123
+ name: "checkCodeSecret",
124
+ properties: {
125
+ secret: {
126
+ type: String,
127
+ validation: ['nonEmpty']
128
+ },
129
+ authentication: {
130
+ type: String,
131
+ validation: ['nonEmpty']
132
+ },
133
+ client: {
134
+ type: Object,
135
+ validation: ['nonEmpty']
136
+ }
137
+ },
138
+ secured: {},
139
+ async execute({ secret, authentication, client }, context, emit) {
140
+ const codeData = await Code.indexObjectGet('byAuthenticationAndSecretCode', [authentication, secret])
141
+ if(!codeData) {
142
+ if(client) {
143
+ await context.trigger({
144
+ type: 'securityEvent',
145
+ event: {
146
+ type: 'wrong-secret-code',
147
+ properties: {
148
+ authentication
149
+ }
150
+ },
151
+ client
152
+ })
153
+ }
154
+ throw { properties: { secret: 'codeNotFound' } }
155
+ }
156
+ if(new Date().toISOString() > codeData.expire) {
157
+ throw { properties: { secret: "codeExpired" } }
158
+ }
159
+ return codeData.authentication
160
+ }
161
+ })
162
+
163
+ module.exports = definition
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@live-change/secret-code-service",
3
+ "version": "0.2.20",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "NODE_ENV=test tape tests/*"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/live-change/live-change-services.git"
12
+ },
13
+ "license": "MIT",
14
+ "bugs": {
15
+ "url": "https://github.com/live-change/live-change-services/issues"
16
+ },
17
+ "homepage": "https://github.com/live-change/live-change-services",
18
+ "author": {
19
+ "email": "michal@laszczewski.pl",
20
+ "name": "Michał Łaszczewski",
21
+ "url": "https://www.viamage.com/"
22
+ },
23
+ "dependencies": {
24
+ "@live-change/framework": "^0.5.7",
25
+ "nodemailer": "^6.7.2"
26
+ },
27
+ "gitHead": "48b13d32478da797b31f73ed1d6f4271cd68b574"
28
+ }