@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.
- package/index.js +163 -0
- 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
|
+
}
|