@webda/core 2.0.0-beta.3 → 2.0.0
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/lib/application.d.ts +5 -5
- package/lib/application.js +71 -84
- package/lib/application.js.map +1 -1
- package/lib/application.spec.js +121 -140
- package/lib/application.spec.js.map +1 -1
- package/lib/core.d.ts +20 -24
- package/lib/core.js +222 -315
- package/lib/core.js.map +1 -1
- package/lib/core.spec.js +332 -406
- package/lib/core.spec.js.map +1 -1
- package/lib/index.d.ts +49 -48
- package/lib/index.js +53 -70
- package/lib/index.js.map +1 -1
- package/lib/models/aclmodel.d.ts +2 -2
- package/lib/models/aclmodel.js +63 -90
- package/lib/models/aclmodel.js.map +1 -1
- package/lib/models/aclmodel.spec.js +127 -152
- package/lib/models/aclmodel.spec.js.map +1 -1
- package/lib/models/coremodel.d.ts +7 -6
- package/lib/models/coremodel.js +65 -113
- package/lib/models/coremodel.js.map +1 -1
- package/lib/models/coremodel.spec.js +88 -107
- package/lib/models/coremodel.spec.js.map +1 -1
- package/lib/models/deployment.js +1 -2
- package/lib/models/ident.d.ts +3 -3
- package/lib/models/ident.js +4 -9
- package/lib/models/ident.js.map +1 -1
- package/lib/models/ident.spec.js +9 -11
- package/lib/models/ident.spec.js.map +1 -1
- package/lib/models/ownermodel.d.ts +2 -2
- package/lib/models/ownermodel.js +39 -62
- package/lib/models/ownermodel.js.map +1 -1
- package/lib/models/ownermodel.spec.js +126 -168
- package/lib/models/ownermodel.spec.js.map +1 -1
- package/lib/models/rolemodel.d.ts +1 -1
- package/lib/models/rolemodel.js +24 -40
- package/lib/models/rolemodel.js.map +1 -1
- package/lib/models/rolemodel.spec.js +44 -63
- package/lib/models/rolemodel.spec.js.map +1 -1
- package/lib/models/user.d.ts +3 -3
- package/lib/models/user.js +3 -8
- package/lib/models/user.js.map +1 -1
- package/lib/models/user.spec.js +14 -16
- package/lib/models/user.spec.js.map +1 -1
- package/lib/queues/filequeue.d.ts +2 -2
- package/lib/queues/filequeue.js +72 -93
- package/lib/queues/filequeue.js.map +1 -1
- package/lib/queues/filequeue.spec.js +53 -70
- package/lib/queues/filequeue.spec.js.map +1 -1
- package/lib/queues/memoryqueue.d.ts +2 -2
- package/lib/queues/memoryqueue.js +37 -61
- package/lib/queues/memoryqueue.js.map +1 -1
- package/lib/queues/memoryqueue.spec.js +142 -165
- package/lib/queues/memoryqueue.spec.js.map +1 -1
- package/lib/queues/pubsubservice.d.ts +2 -2
- package/lib/queues/pubsubservice.js +3 -7
- package/lib/queues/pubsubservice.js.map +1 -1
- package/lib/queues/queue.spec.d.ts +1 -1
- package/lib/queues/queue.spec.js +42 -56
- package/lib/queues/queue.spec.js.map +1 -1
- package/lib/queues/queueservice.d.ts +3 -3
- package/lib/queues/queueservice.js +51 -67
- package/lib/queues/queueservice.js.map +1 -1
- package/lib/router.d.ts +3 -3
- package/lib/router.js +46 -47
- package/lib/router.js.map +1 -1
- package/lib/router.spec.js +64 -61
- package/lib/router.spec.js.map +1 -1
- package/lib/services/asyncevents.d.ts +2 -2
- package/lib/services/asyncevents.js +44 -64
- package/lib/services/asyncevents.js.map +1 -1
- package/lib/services/asyncevents.spec.js +81 -98
- package/lib/services/asyncevents.spec.js.map +1 -1
- package/lib/services/authentication.d.ts +23 -13
- package/lib/services/authentication.js +537 -563
- package/lib/services/authentication.js.map +1 -1
- package/lib/services/authentication.spec.js +411 -447
- package/lib/services/authentication.spec.js.map +1 -1
- package/lib/services/binary.d.ts +7 -5
- package/lib/services/binary.js +211 -244
- package/lib/services/binary.js.map +1 -1
- package/lib/services/binary.spec.d.ts +3 -3
- package/lib/services/binary.spec.js +390 -443
- package/lib/services/binary.spec.js.map +1 -1
- package/lib/services/cloudbinary.d.ts +3 -3
- package/lib/services/cloudbinary.js +45 -70
- package/lib/services/cloudbinary.js.map +1 -1
- package/lib/services/cloudbinary.spec.d.ts +3 -3
- package/lib/services/cloudbinary.spec.js +133 -162
- package/lib/services/cloudbinary.spec.js.map +1 -1
- package/lib/services/configuration.d.ts +1 -1
- package/lib/services/configuration.js +78 -105
- package/lib/services/configuration.js.map +1 -1
- package/lib/services/configuration.spec.js +63 -83
- package/lib/services/configuration.spec.js.map +1 -1
- package/lib/services/cron.d.ts +3 -2
- package/lib/services/cron.js +9 -13
- package/lib/services/cron.js.map +1 -1
- package/lib/services/cron.spec.js +18 -21
- package/lib/services/cron.spec.js.map +1 -1
- package/lib/services/cryptoservice.d.ts +9 -4
- package/lib/services/cryptoservice.js +187 -221
- package/lib/services/cryptoservice.js.map +1 -1
- package/lib/services/cryptoservice.spec.js +88 -115
- package/lib/services/cryptoservice.spec.js.map +1 -1
- package/lib/services/debugmailer.d.ts +1 -1
- package/lib/services/debugmailer.js +13 -34
- package/lib/services/debugmailer.js.map +1 -1
- package/lib/services/debugmailer.spec.js +16 -29
- package/lib/services/debugmailer.spec.js.map +1 -1
- package/lib/services/echo.d.ts +2 -2
- package/lib/services/echo.js +15 -31
- package/lib/services/echo.js.map +1 -1
- package/lib/services/echo.spec.js +27 -40
- package/lib/services/echo.spec.js.map +1 -1
- package/lib/services/filebinary.d.ts +5 -5
- package/lib/services/filebinary.js +165 -210
- package/lib/services/filebinary.js.map +1 -1
- package/lib/services/filebinary.spec.d.ts +2 -1
- package/lib/services/filebinary.spec.js +106 -116
- package/lib/services/filebinary.spec.js.map +1 -1
- package/lib/services/fileconfiguration.d.ts +1 -1
- package/lib/services/fileconfiguration.js +25 -44
- package/lib/services/fileconfiguration.js.map +1 -1
- package/lib/services/fileconfiguration.spec.js +79 -109
- package/lib/services/fileconfiguration.spec.js.map +1 -1
- package/lib/services/invitationservice.d.ts +7 -7
- package/lib/services/invitationservice.js +274 -314
- package/lib/services/invitationservice.js.map +1 -1
- package/lib/services/invitationservice.spec.js +442 -448
- package/lib/services/invitationservice.spec.js.map +1 -1
- package/lib/services/kubernetesconfiguration.d.ts +1 -1
- package/lib/services/kubernetesconfiguration.js +41 -60
- package/lib/services/kubernetesconfiguration.js.map +1 -1
- package/lib/services/kubernetesconfiguration.spec.js +80 -98
- package/lib/services/kubernetesconfiguration.spec.js.map +1 -1
- package/lib/services/mailer.d.ts +4 -4
- package/lib/services/mailer.js +62 -86
- package/lib/services/mailer.js.map +1 -1
- package/lib/services/mailer.spec.js +86 -127
- package/lib/services/mailer.spec.js.map +1 -1
- package/lib/services/notificationservice.d.ts +3 -3
- package/lib/services/notificationservice.js +21 -42
- package/lib/services/notificationservice.js.map +1 -1
- package/lib/services/notificationservice.spec.js +47 -73
- package/lib/services/notificationservice.spec.js.map +1 -1
- package/lib/services/oauth.d.ts +4 -4
- package/lib/services/oauth.js +68 -83
- package/lib/services/oauth.js.map +1 -1
- package/lib/services/oauth.spec.js +130 -156
- package/lib/services/oauth.spec.js.map +1 -1
- package/lib/services/proxy.d.ts +2 -6
- package/lib/services/proxy.js +45 -58
- package/lib/services/proxy.js.map +1 -1
- package/lib/services/proxy.spec.js +34 -53
- package/lib/services/proxy.spec.js.map +1 -1
- package/lib/services/resource.d.ts +2 -2
- package/lib/services/resource.js +12 -18
- package/lib/services/resource.js.map +1 -1
- package/lib/services/resource.spec.js +67 -99
- package/lib/services/resource.spec.js.map +1 -1
- package/lib/services/service.d.ts +26 -3
- package/lib/services/service.js +68 -40
- package/lib/services/service.js.map +1 -1
- package/lib/services/service.spec.js +62 -67
- package/lib/services/service.spec.js.map +1 -1
- package/lib/services/version.d.ts +1 -1
- package/lib/services/version.js +3 -8
- package/lib/services/version.js.map +1 -1
- package/lib/services/version.spec.js +11 -24
- package/lib/services/version.spec.js.map +1 -1
- package/lib/stores/aggregator.d.ts +2 -2
- package/lib/stores/aggregator.js +37 -58
- package/lib/stores/aggregator.js.map +1 -1
- package/lib/stores/file.d.ts +3 -3
- package/lib/stores/file.js +93 -131
- package/lib/stores/file.js.map +1 -1
- package/lib/stores/file.spec.d.ts +2 -2
- package/lib/stores/file.spec.js +261 -289
- package/lib/stores/file.spec.js.map +1 -1
- package/lib/stores/mapper.d.ts +3 -3
- package/lib/stores/mapper.js +110 -137
- package/lib/stores/mapper.js.map +1 -1
- package/lib/stores/mapper.spec.js +131 -150
- package/lib/stores/mapper.spec.js.map +1 -1
- package/lib/stores/memory.d.ts +3 -3
- package/lib/stores/memory.js +98 -144
- package/lib/stores/memory.js.map +1 -1
- package/lib/stores/memory.spec.d.ts +2 -2
- package/lib/stores/memory.spec.js +124 -145
- package/lib/stores/memory.spec.js.map +1 -1
- package/lib/stores/store.d.ts +17 -13
- package/lib/stores/store.js +819 -847
- package/lib/stores/store.js.map +1 -1
- package/lib/stores/store.spec.d.ts +5 -4
- package/lib/stores/store.spec.js +624 -669
- package/lib/stores/store.spec.js.map +1 -1
- package/lib/stores/webdaql/WebdaQLLexer.d.ts +4 -4
- package/lib/stores/webdaql/WebdaQLLexer.js +9 -13
- package/lib/stores/webdaql/WebdaQLLexer.js.map +1 -1
- package/lib/stores/webdaql/WebdaQLParserLexer.d.ts +4 -4
- package/lib/stores/webdaql/WebdaQLParserLexer.js +9 -13
- package/lib/stores/webdaql/WebdaQLParserLexer.js.map +1 -1
- package/lib/stores/webdaql/WebdaQLParserListener.d.ts +2 -2
- package/lib/stores/webdaql/WebdaQLParserListener.js +1 -2
- package/lib/stores/webdaql/WebdaQLParserListener.js.map +1 -1
- package/lib/stores/webdaql/WebdaQLParserParser.d.ts +10 -10
- package/lib/stores/webdaql/WebdaQLParserParser.js +62 -91
- package/lib/stores/webdaql/WebdaQLParserParser.js.map +1 -1
- package/lib/stores/webdaql/WebdaQLParserVisitor.d.ts +2 -2
- package/lib/stores/webdaql/WebdaQLParserVisitor.js +1 -2
- package/lib/stores/webdaql/WebdaQLParserVisitor.js.map +1 -1
- package/lib/stores/webdaql/query.d.ts +4 -5
- package/lib/stores/webdaql/query.js +16 -19
- package/lib/stores/webdaql/query.js.map +1 -1
- package/lib/stores/webdaql/query.spec.js +30 -32
- package/lib/stores/webdaql/query.spec.js.map +1 -1
- package/lib/test.d.ts +3 -3
- package/lib/test.js +73 -100
- package/lib/test.js.map +1 -1
- package/lib/unpackedapplication.d.ts +1 -1
- package/lib/unpackedapplication.js +25 -31
- package/lib/unpackedapplication.js.map +1 -1
- package/lib/utils/abstractdeployer.js +1 -5
- package/lib/utils/abstractdeployer.js.map +1 -1
- package/lib/utils/abstractdeployer.spec.js +6 -8
- package/lib/utils/abstractdeployer.spec.js.map +1 -1
- package/lib/utils/context.d.ts +7 -5
- package/lib/utils/context.js +95 -103
- package/lib/utils/context.js.map +1 -1
- package/lib/utils/context.spec.js +139 -163
- package/lib/utils/context.spec.js.map +1 -1
- package/lib/utils/cookie.d.ts +3 -3
- package/lib/utils/cookie.js +42 -61
- package/lib/utils/cookie.js.map +1 -1
- package/lib/utils/cookie.spec.js +42 -64
- package/lib/utils/cookie.spec.js.map +1 -1
- package/lib/utils/esm.d.ts +4 -0
- package/lib/utils/esm.js +10 -0
- package/lib/utils/esm.js.map +1 -0
- package/lib/utils/httpcontext.d.ts +3 -0
- package/lib/utils/httpcontext.js +48 -65
- package/lib/utils/httpcontext.js.map +1 -1
- package/lib/utils/httpcontext.spec.js +37 -56
- package/lib/utils/httpcontext.spec.js.map +1 -1
- package/lib/utils/logger.d.ts +2 -2
- package/lib/utils/logger.js +15 -28
- package/lib/utils/logger.js.map +1 -1
- package/lib/utils/logger.spec.js +9 -11
- package/lib/utils/logger.spec.js.map +1 -1
- package/lib/utils/serializers.js +17 -20
- package/lib/utils/serializers.js.map +1 -1
- package/lib/utils/serializers.spec.js +43 -44
- package/lib/utils/serializers.spec.js.map +1 -1
- package/lib/utils/session.d.ts +6 -6
- package/lib/utils/session.js +37 -59
- package/lib/utils/session.js.map +1 -1
- package/lib/utils/session.spec.js +38 -51
- package/lib/utils/session.spec.js.map +1 -1
- package/lib/utils/waiter.d.ts +1 -1
- package/lib/utils/waiter.js +32 -52
- package/lib/utils/waiter.js.map +1 -1
- package/lib/utils/waiter.spec.js +75 -92
- package/lib/utils/waiter.spec.js.map +1 -1
- package/package.json +17 -12
- package/test/config-invitation.json +1 -3
- package/test/config.json +1 -2
- package/test/config.old.json +1 -2
- package/test/moddas/annotatedservice.js +5 -5
- package/test/moddas/debugmailer.js +2 -3
- package/test/moddas/fakeservice.js +2 -3
- package/test/moddas/voidstore.js +6 -4
- package/test/models/ident.js +2 -6
- package/test/models/task.js +3 -7
- package/test/package.json +2 -1
- package/webda.module.json +956 -189
|
@@ -1,42 +1,28 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
2
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
3
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
6
|
};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
13
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
14
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
15
|
-
});
|
|
16
|
-
};
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.Authentication = exports.AuthenticationParameters = void 0;
|
|
19
|
-
const bcrypt = require("bcryptjs");
|
|
20
|
-
const service_1 = require("../services/service");
|
|
21
|
-
const httpcontext_1 = require("../utils/httpcontext");
|
|
22
|
-
class AuthenticationParameters extends service_1.ServiceParameters {
|
|
7
|
+
import bcrypt from "bcryptjs";
|
|
8
|
+
import { Inject, Route, Service, ServiceParameters } from "../services/service.js";
|
|
9
|
+
import { HttpContext } from "../utils/httpcontext.js";
|
|
10
|
+
export class AuthenticationParameters extends ServiceParameters {
|
|
23
11
|
constructor(params) {
|
|
24
|
-
var _a, _b
|
|
25
|
-
var _g, _h;
|
|
12
|
+
var _a, _b;
|
|
26
13
|
super(params);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
this.identStore ?? (this.identStore = "idents");
|
|
15
|
+
this.userStore ?? (this.userStore = "users");
|
|
16
|
+
this.url ?? (this.url = "/auth");
|
|
17
|
+
this.password ?? (this.password = {
|
|
31
18
|
regexp: ".{8,}"
|
|
32
19
|
});
|
|
33
20
|
if (this.email) {
|
|
34
|
-
(
|
|
35
|
-
(
|
|
21
|
+
(_a = this.email).delay ?? (_a.delay = 3600000 * 4);
|
|
22
|
+
(_b = this.email).failedLoginBeforeDelay ?? (_b.failedLoginBeforeDelay = 3);
|
|
36
23
|
}
|
|
37
24
|
}
|
|
38
25
|
}
|
|
39
|
-
exports.AuthenticationParameters = AuthenticationParameters;
|
|
40
26
|
/**
|
|
41
27
|
* This class is known as the Authentication module
|
|
42
28
|
* It handles OAuth for several providers for now (Facebook, Google, Amazon, GitHub and Twitter)
|
|
@@ -60,7 +46,7 @@ exports.AuthenticationParameters = AuthenticationParameters;
|
|
|
60
46
|
* @category CoreServices
|
|
61
47
|
* @WebdaModda
|
|
62
48
|
*/
|
|
63
|
-
class Authentication extends
|
|
49
|
+
class Authentication extends Service {
|
|
64
50
|
constructor() {
|
|
65
51
|
super(...arguments);
|
|
66
52
|
this.providers = new Set();
|
|
@@ -85,132 +71,6 @@ class Authentication extends service_1.Service {
|
|
|
85
71
|
getIdentStore() {
|
|
86
72
|
return this._identsStore;
|
|
87
73
|
}
|
|
88
|
-
/**
|
|
89
|
-
* @override
|
|
90
|
-
*/
|
|
91
|
-
initRoutes() {
|
|
92
|
-
// ROUTES
|
|
93
|
-
let url = this.parameters.url;
|
|
94
|
-
// List authentication configured
|
|
95
|
-
this.addRoute(url, ["GET", "DELETE"], this._listAuthentications, {
|
|
96
|
-
get: {
|
|
97
|
-
description: "Retrieve the list of available authentication",
|
|
98
|
-
summary: "Get available auths",
|
|
99
|
-
operationId: `getAuthenticationMethods`,
|
|
100
|
-
responses: {
|
|
101
|
-
"200": {
|
|
102
|
-
description: "List of authentication"
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
delete: {
|
|
107
|
-
description: "Logout current user",
|
|
108
|
-
summary: "Logout",
|
|
109
|
-
operationId: `logout`,
|
|
110
|
-
responses: {
|
|
111
|
-
"200": {}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
// Get the current user
|
|
116
|
-
this.addRoute(url + "/me", ["GET"], this._getMe, {
|
|
117
|
-
get: {
|
|
118
|
-
description: "Retrieve the current user from the session",
|
|
119
|
-
summary: "Get current user",
|
|
120
|
-
operationId: "getCurrentUser"
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
if (this.parameters.email) {
|
|
124
|
-
this.addProvider("email");
|
|
125
|
-
// Add static for email for now, if set before it should have priority
|
|
126
|
-
this.addRoute(url + "/email", ["POST"], this._handleEmail, {
|
|
127
|
-
post: {
|
|
128
|
-
description: "Authenticate with an email and password",
|
|
129
|
-
summary: "Authenticate with email",
|
|
130
|
-
operationId: `authWithEmail`
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
this.addRoute(url + "/email/callback{?email,token,user}", ["GET"], this._handleEmailCallback, {
|
|
134
|
-
hidden: true
|
|
135
|
-
});
|
|
136
|
-
this.addRoute(url + "/email/passwordRecovery", ["POST"], this._passwordRecovery, {
|
|
137
|
-
post: {
|
|
138
|
-
schemas: {
|
|
139
|
-
input: {
|
|
140
|
-
type: "object",
|
|
141
|
-
properties: {
|
|
142
|
-
token: {
|
|
143
|
-
type: "string"
|
|
144
|
-
},
|
|
145
|
-
expire: {
|
|
146
|
-
type: "number"
|
|
147
|
-
},
|
|
148
|
-
password: {
|
|
149
|
-
type: "string"
|
|
150
|
-
},
|
|
151
|
-
login: {
|
|
152
|
-
type: "string"
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
},
|
|
157
|
-
description: "Reinit the password if we have the right token, expire",
|
|
158
|
-
summary: "Reinit password",
|
|
159
|
-
operationId: "reinitPassword",
|
|
160
|
-
responses: {
|
|
161
|
-
"204": {
|
|
162
|
-
description: ""
|
|
163
|
-
},
|
|
164
|
-
"403": {
|
|
165
|
-
description: "Wrong Token"
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
this.addRoute(url + "/email/{email}/recover", ["GET"], this._passwordRecoveryEmail, {
|
|
171
|
-
get: {
|
|
172
|
-
description: "The password reset process will be start",
|
|
173
|
-
summary: "Start password recovery",
|
|
174
|
-
operationId: "startEmailRecovery",
|
|
175
|
-
responses: {
|
|
176
|
-
"204": {
|
|
177
|
-
description: ""
|
|
178
|
-
},
|
|
179
|
-
"404": {
|
|
180
|
-
description: "Email does not exist"
|
|
181
|
-
},
|
|
182
|
-
"429": {
|
|
183
|
-
description: "Recovery has been initiated in the last 4 hours"
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
this.addRoute(url + "/email/{email}/validate", ["GET"], this._sendEmailValidation, {
|
|
189
|
-
get: {
|
|
190
|
-
description: "The email validation process will be start",
|
|
191
|
-
summary: "Restart email validation",
|
|
192
|
-
operationId: "startEmailRecovery",
|
|
193
|
-
responses: {
|
|
194
|
-
"204": {
|
|
195
|
-
description: ""
|
|
196
|
-
},
|
|
197
|
-
"409": {
|
|
198
|
-
description: "Email already verified for another user"
|
|
199
|
-
},
|
|
200
|
-
"412": {
|
|
201
|
-
description: "Email already verified for current user"
|
|
202
|
-
},
|
|
203
|
-
"429": {
|
|
204
|
-
description: "Validation has been initiated in the last 4 hours"
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
getUrl() {
|
|
212
|
-
return this.parameters.url;
|
|
213
|
-
}
|
|
214
74
|
setIdents(identStore) {
|
|
215
75
|
this._identsStore = identStore;
|
|
216
76
|
}
|
|
@@ -229,6 +89,10 @@ class Authentication extends service_1.Service {
|
|
|
229
89
|
if (this.parameters.email && this.getMailMan() === undefined) {
|
|
230
90
|
throw Error("email authentication requires a Mailer service");
|
|
231
91
|
}
|
|
92
|
+
// Add email provider
|
|
93
|
+
if (this.parameters.email) {
|
|
94
|
+
this.addProvider("email");
|
|
95
|
+
}
|
|
232
96
|
}
|
|
233
97
|
/**
|
|
234
98
|
* Add a provider to the oauth scheme
|
|
@@ -237,6 +101,16 @@ class Authentication extends service_1.Service {
|
|
|
237
101
|
addProvider(name) {
|
|
238
102
|
this.providers.add(name);
|
|
239
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Ensure email is enabled for all emails routes
|
|
106
|
+
* @override
|
|
107
|
+
*/
|
|
108
|
+
getUrl(url, methods) {
|
|
109
|
+
if (url.startsWith("./emails") && !this.parameters.email) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
return super.getUrl(url, methods);
|
|
113
|
+
}
|
|
240
114
|
/**
|
|
241
115
|
* Send or resend an email to validate the email address
|
|
242
116
|
*
|
|
@@ -245,54 +119,50 @@ class Authentication extends service_1.Service {
|
|
|
245
119
|
* @throws 412 if the email is already validated
|
|
246
120
|
* @throws 429 if a validation email has been sent recently
|
|
247
121
|
*/
|
|
248
|
-
_sendEmailValidation(ctx) {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
122
|
+
async _sendEmailValidation(ctx) {
|
|
123
|
+
let identKey = ctx.parameters.email + "_email";
|
|
124
|
+
let ident = await this._identsStore.get(identKey);
|
|
125
|
+
if (!ident) {
|
|
126
|
+
await this._identsStore.save({
|
|
127
|
+
uuid: `${ctx.parameters.email}_email`,
|
|
128
|
+
_lastValidationEmail: Date.now(),
|
|
129
|
+
_type: "email"
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// If the ident is linked to someone else - might want to remove it
|
|
134
|
+
if (ident.getUser() !== ctx.getCurrentUserId()) {
|
|
135
|
+
throw 409;
|
|
258
136
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
throw 409;
|
|
263
|
-
}
|
|
264
|
-
// If the email is already validated
|
|
265
|
-
if (ident._validation) {
|
|
266
|
-
throw 412;
|
|
267
|
-
}
|
|
268
|
-
//
|
|
269
|
-
if (ident._lastValidationEmail >= Date.now() - this.parameters.email.delay) {
|
|
270
|
-
throw 429;
|
|
271
|
-
}
|
|
272
|
-
yield this._identsStore.patch({
|
|
273
|
-
_lastValidationEmail: Date.now(),
|
|
274
|
-
uuid: identKey
|
|
275
|
-
});
|
|
137
|
+
// If the email is already validated
|
|
138
|
+
if (ident._validation) {
|
|
139
|
+
throw 412;
|
|
276
140
|
}
|
|
277
|
-
|
|
278
|
-
|
|
141
|
+
//
|
|
142
|
+
if (ident._lastValidationEmail >= Date.now() - this.parameters.email.delay) {
|
|
143
|
+
throw 429;
|
|
144
|
+
}
|
|
145
|
+
await this._identsStore.patch({
|
|
146
|
+
_lastValidationEmail: Date.now(),
|
|
147
|
+
uuid: identKey
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
await this.sendValidationEmail(ctx, ctx.parameters.email);
|
|
279
151
|
}
|
|
280
152
|
/**
|
|
281
153
|
* Return current user
|
|
282
154
|
* @param ctx
|
|
283
155
|
*/
|
|
284
|
-
_getMe(ctx) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
user
|
|
293
|
-
});
|
|
294
|
-
ctx.write(user);
|
|
156
|
+
async _getMe(ctx) {
|
|
157
|
+
let user = await ctx.getCurrentUser();
|
|
158
|
+
if (user === undefined) {
|
|
159
|
+
throw 404;
|
|
160
|
+
}
|
|
161
|
+
await this.emitSync("Authentication.GetMe", {
|
|
162
|
+
context: ctx,
|
|
163
|
+
user
|
|
295
164
|
});
|
|
165
|
+
ctx.write(user);
|
|
296
166
|
}
|
|
297
167
|
/**
|
|
298
168
|
* Handle both list of available authentication
|
|
@@ -301,232 +171,223 @@ class Authentication extends service_1.Service {
|
|
|
301
171
|
* @param ctx
|
|
302
172
|
* @returns
|
|
303
173
|
*/
|
|
304
|
-
_listAuthentications(ctx) {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
ctx.write(Array.from(this.providers));
|
|
312
|
-
});
|
|
174
|
+
async _listAuthentications(ctx) {
|
|
175
|
+
if (ctx.getHttpContext().getMethod() === "DELETE") {
|
|
176
|
+
await this.logout(ctx);
|
|
177
|
+
ctx.write("GoodBye");
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
ctx.write(Array.from(this.providers));
|
|
313
181
|
}
|
|
314
|
-
onIdentLogin(ctx, provider, identId, profile, tokens = undefined) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
182
|
+
async onIdentLogin(ctx, provider, identId, profile, tokens = undefined) {
|
|
183
|
+
// Auto postifx with provider name
|
|
184
|
+
const postfix = `_${provider}`;
|
|
185
|
+
if (!identId.endsWith(postfix)) {
|
|
186
|
+
identId += postfix;
|
|
187
|
+
}
|
|
188
|
+
let ident = await this._identsStore.get(identId);
|
|
189
|
+
// Ident is known
|
|
190
|
+
if (ident) {
|
|
191
|
+
await this.login(ctx, ident.getUser(), ident);
|
|
192
|
+
await this._identsStore.patch({
|
|
193
|
+
_lastUsed: new Date(),
|
|
194
|
+
__tokens: tokens,
|
|
195
|
+
uuid: ident.uuid
|
|
196
|
+
});
|
|
197
|
+
// Redirect to?
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
let user;
|
|
201
|
+
if (profile.email) {
|
|
202
|
+
ident = await this._identsStore.get(`${profile.email}_email`);
|
|
203
|
+
}
|
|
204
|
+
// If already login
|
|
205
|
+
if (ctx.getCurrentUserId()) {
|
|
206
|
+
user = await ctx.getCurrentUser();
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
// If an email in profile try to find the ident
|
|
323
210
|
if (ident) {
|
|
324
|
-
|
|
325
|
-
yield this._identsStore.patch({
|
|
326
|
-
_lastUsed: new Date(),
|
|
327
|
-
__tokens: tokens,
|
|
328
|
-
uuid: ident.uuid
|
|
329
|
-
});
|
|
330
|
-
// Redirect to?
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
let user;
|
|
334
|
-
if (profile.email) {
|
|
335
|
-
ident = yield this._identsStore.get(`${profile.email}_email`);
|
|
336
|
-
}
|
|
337
|
-
// If already login
|
|
338
|
-
if (ctx.getCurrentUserId()) {
|
|
339
|
-
user = yield ctx.getCurrentUser();
|
|
340
|
-
}
|
|
341
|
-
else {
|
|
342
|
-
// If an email in profile try to find the ident
|
|
343
|
-
if (ident) {
|
|
344
|
-
user = yield this._usersStore.get(ident.getUser());
|
|
345
|
-
}
|
|
346
|
-
if (!user) {
|
|
347
|
-
// If no user, register a new user automatically
|
|
348
|
-
user = yield this.registerUser(ctx, profile, identId);
|
|
349
|
-
yield this._usersStore.save(user);
|
|
350
|
-
}
|
|
211
|
+
user = await this._usersStore.get(ident.getUser());
|
|
351
212
|
}
|
|
352
|
-
if (
|
|
353
|
-
//
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
provider: "email"
|
|
357
|
-
});
|
|
358
|
-
ident.setUser(user.getUuid());
|
|
359
|
-
yield ident.save();
|
|
213
|
+
if (!user) {
|
|
214
|
+
// If no user, register a new user automatically
|
|
215
|
+
user = await this.registerUser(ctx, profile, identId);
|
|
216
|
+
await this._usersStore.save(user);
|
|
360
217
|
}
|
|
361
|
-
|
|
218
|
+
}
|
|
219
|
+
if (profile.email && !ident) {
|
|
220
|
+
// Save additional email
|
|
362
221
|
ident = this._identsStore.initModel({
|
|
363
|
-
uuid:
|
|
364
|
-
|
|
365
|
-
__tokens: tokens,
|
|
366
|
-
provider
|
|
222
|
+
uuid: `${profile.email}_email`,
|
|
223
|
+
provider: "email"
|
|
367
224
|
});
|
|
368
|
-
ident.setUser(user.
|
|
369
|
-
ident.
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
225
|
+
ident.setUser(user.getUuid());
|
|
226
|
+
await ident.save();
|
|
227
|
+
}
|
|
228
|
+
// Work directly on ident argument
|
|
229
|
+
ident = this._identsStore.initModel({
|
|
230
|
+
uuid: identId,
|
|
231
|
+
profile,
|
|
232
|
+
__tokens: tokens,
|
|
233
|
+
provider
|
|
374
234
|
});
|
|
235
|
+
ident.setUser(user.uuid);
|
|
236
|
+
ident._lastUsed = new Date();
|
|
237
|
+
ident.setType(provider);
|
|
238
|
+
await ident.save();
|
|
239
|
+
ident.__new = true;
|
|
240
|
+
await this.login(ctx, user, ident);
|
|
375
241
|
}
|
|
376
242
|
/**
|
|
377
243
|
* Create a new User with the link ident
|
|
378
244
|
* @param ident
|
|
379
245
|
*/
|
|
380
|
-
createUserWithIdent(provider, identId, profile = {}) {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
user
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
data: data,
|
|
397
|
-
context: ctx,
|
|
398
|
-
identId
|
|
399
|
-
});
|
|
400
|
-
return user;
|
|
246
|
+
async createUserWithIdent(provider, identId, profile = {}) {
|
|
247
|
+
if (await this._identsStore.exists(`${identId}_${provider}`)) {
|
|
248
|
+
throw new Error("Ident is already known");
|
|
249
|
+
}
|
|
250
|
+
let ctx = await this._webda.newContext(new HttpContext("fake", "GET", "/"));
|
|
251
|
+
// Pretend we logged in with the ident
|
|
252
|
+
await this.onIdentLogin(ctx, provider, identId, profile);
|
|
253
|
+
}
|
|
254
|
+
async registerUser(ctx, data, identId, user = this._usersStore.initModel()) {
|
|
255
|
+
user.email = data.email;
|
|
256
|
+
user.locale = ctx.getLocale();
|
|
257
|
+
await this.emitSync("Authentication.Register", {
|
|
258
|
+
user: user,
|
|
259
|
+
data: data,
|
|
260
|
+
context: ctx,
|
|
261
|
+
identId
|
|
401
262
|
});
|
|
263
|
+
return user;
|
|
402
264
|
}
|
|
403
|
-
getPasswordRecoveryInfos(uuid, interval = this.parameters.email.delay) {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
};
|
|
422
|
-
});
|
|
265
|
+
async getPasswordRecoveryInfos(uuid, interval = this.parameters.email.delay) {
|
|
266
|
+
const expire = Date.now() + interval;
|
|
267
|
+
let user;
|
|
268
|
+
if (typeof uuid === "string") {
|
|
269
|
+
user = await this._usersStore.get(uuid);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
user = uuid;
|
|
273
|
+
}
|
|
274
|
+
if (!user) {
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
expire: expire,
|
|
279
|
+
// Might want to add more alea not coming from the db to avoid exploitation of stolen db
|
|
280
|
+
token: await this.cryptoService.hmac(user.uuid + expire + user.getPassword()),
|
|
281
|
+
login: user.uuid
|
|
282
|
+
};
|
|
423
283
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
284
|
+
/**
|
|
285
|
+
* Manage password recovery
|
|
286
|
+
* @param ctx
|
|
287
|
+
*/
|
|
288
|
+
async _passwordRecoveryEmail(ctx) {
|
|
289
|
+
let email = ctx.parameter("email");
|
|
290
|
+
let ident = await this._identsStore.get(email + "_email");
|
|
291
|
+
if (!ident) {
|
|
292
|
+
throw 404;
|
|
293
|
+
}
|
|
294
|
+
let user = await this._usersStore.get(ident.getUser());
|
|
295
|
+
// Dont allow to do too many request
|
|
296
|
+
if (!user.lastPasswordRecoveryBefore(Date.now() - this.parameters.email.delay)) {
|
|
297
|
+
throw 429;
|
|
298
|
+
}
|
|
299
|
+
await this._usersStore.patch({
|
|
300
|
+
_lastPasswordRecovery: Date.now(),
|
|
301
|
+
uuid: user.uuid
|
|
441
302
|
});
|
|
303
|
+
await this.sendRecoveryEmail(ctx, user, email);
|
|
442
304
|
}
|
|
443
|
-
_verifyPassword(password, user) {
|
|
444
|
-
|
|
445
|
-
if (this._passwordVerifier) {
|
|
446
|
-
if (!(yield this._passwordVerifier.validate(password, user))) {
|
|
447
|
-
throw 400;
|
|
448
|
-
}
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
451
|
-
let regexp = new RegExp(this.parameters.password.regexp);
|
|
452
|
-
if (regexp.exec(password) === null) {
|
|
305
|
+
async _verifyPassword(password, user) {
|
|
306
|
+
if (this._passwordVerifier) {
|
|
307
|
+
if (!(await this._passwordVerifier.validate(password, user))) {
|
|
453
308
|
throw 400;
|
|
454
309
|
}
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
let regexp = new RegExp(this.parameters.password.regexp);
|
|
313
|
+
if (regexp.exec(password) === null) {
|
|
314
|
+
throw 400;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
async _passwordRecovery(ctx) {
|
|
318
|
+
let body = await ctx.getRequestBody();
|
|
319
|
+
if (body.password === undefined ||
|
|
320
|
+
body.login === undefined ||
|
|
321
|
+
body.token === undefined ||
|
|
322
|
+
body.expire === undefined) {
|
|
323
|
+
throw 400;
|
|
324
|
+
}
|
|
325
|
+
let user = await this._usersStore.get(body.login.toLowerCase());
|
|
326
|
+
if (!user) {
|
|
327
|
+
throw 403;
|
|
328
|
+
}
|
|
329
|
+
if (!(await this.cryptoService.hmacVerify(body.login.toLowerCase() + body.expire + user.getPassword(), body.token))) {
|
|
330
|
+
throw 403;
|
|
331
|
+
}
|
|
332
|
+
if (body.expire < Date.now()) {
|
|
333
|
+
throw 410;
|
|
334
|
+
}
|
|
335
|
+
await this._verifyPassword(body.password, user);
|
|
336
|
+
let password = this.hashPassword(body.password);
|
|
337
|
+
await this._usersStore.patch({
|
|
338
|
+
__password: password,
|
|
339
|
+
uuid: body.login.toLowerCase()
|
|
340
|
+
});
|
|
341
|
+
await this.emitSync("Authentication.PasswordUpdate", {
|
|
342
|
+
user,
|
|
343
|
+
password,
|
|
344
|
+
context: ctx
|
|
455
345
|
});
|
|
456
346
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
}
|
|
470
|
-
if (!(yield this.cryptoService.hmacVerify(body.login.toLowerCase() + body.expire + user.getPassword(), body.token))) {
|
|
471
|
-
throw 403;
|
|
472
|
-
}
|
|
473
|
-
if (body.expire < Date.now()) {
|
|
474
|
-
throw 410;
|
|
475
|
-
}
|
|
476
|
-
yield this._verifyPassword(body.password, user);
|
|
477
|
-
let password = this.hashPassword(body.password);
|
|
478
|
-
yield this._usersStore.patch({
|
|
479
|
-
__password: password,
|
|
480
|
-
uuid: body.login.toLowerCase()
|
|
347
|
+
/**
|
|
348
|
+
* Callback to validate an email address
|
|
349
|
+
* @param ctx
|
|
350
|
+
* @returns
|
|
351
|
+
*/
|
|
352
|
+
async _handleEmailCallback(ctx) {
|
|
353
|
+
if (!ctx.parameter("token")) {
|
|
354
|
+
throw 400;
|
|
355
|
+
}
|
|
356
|
+
if (!(await this.cryptoService.hmacVerify(`${ctx.parameter("email")}_${ctx.parameter("user")}`, ctx.parameter("token")))) {
|
|
357
|
+
ctx.writeHead(302, {
|
|
358
|
+
Location: this.parameters.failureRedirect + "?reason=badToken"
|
|
481
359
|
});
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (ctx.parameter("user") !== ctx.getCurrentUserId() &&
|
|
363
|
+
ctx.getCurrentUserId() !== "" &&
|
|
364
|
+
ctx.getCurrentUserId() !== undefined) {
|
|
365
|
+
ctx.writeHead(302, {
|
|
366
|
+
Location: this.parameters.failureRedirect + "?reason=badUser"
|
|
486
367
|
});
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
491
|
-
if (!ctx.parameter("token")) {
|
|
492
|
-
throw 400;
|
|
493
|
-
}
|
|
494
|
-
if (!(yield this.cryptoService.hmacVerify(`${ctx.parameter("email")}_${ctx.parameter("user")}`, ctx.parameter("token")))) {
|
|
495
|
-
ctx.writeHead(302, {
|
|
496
|
-
Location: this.parameters.failureRedirect + "?reason=badToken"
|
|
497
|
-
});
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
if (ctx.parameter("user") !== ctx.getCurrentUserId() &&
|
|
501
|
-
ctx.getCurrentUserId() !== "" &&
|
|
502
|
-
ctx.getCurrentUserId() !== undefined) {
|
|
503
|
-
ctx.writeHead(302, {
|
|
504
|
-
Location: this.parameters.failureRedirect + "?reason=badUser"
|
|
505
|
-
});
|
|
506
|
-
return;
|
|
507
|
-
}
|
|
508
|
-
if (!ctx.parameter("user")) {
|
|
509
|
-
ctx.writeHead(302, {
|
|
510
|
-
Location: `${this.parameters.registerRedirect}?token=${ctx.parameter("token")}&email=${ctx.parameter("email")}`
|
|
511
|
-
});
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
var uuid = ctx.parameter("email") + "_email";
|
|
515
|
-
let ident = yield this._identsStore.get(uuid);
|
|
516
|
-
// Would mean the ident got delete in the mean time... hyper low likely hood
|
|
517
|
-
if (ident === undefined) {
|
|
518
|
-
ident = this._identsStore.initModel({
|
|
519
|
-
uuid
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
ident._type = "email";
|
|
523
|
-
ident._validation = new Date();
|
|
524
|
-
ident.setUser(ctx.parameter("user"));
|
|
525
|
-
yield ident.save();
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (!ctx.parameter("user")) {
|
|
526
371
|
ctx.writeHead(302, {
|
|
527
|
-
Location: this.parameters.
|
|
528
|
-
|
|
372
|
+
Location: `${this.parameters.registerRedirect}?token=${ctx.parameter("token")}&email=${ctx.parameter("email")}`
|
|
373
|
+
});
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const uuid = ctx.parameter("email") + "_email";
|
|
377
|
+
let ident = await this._identsStore.get(uuid);
|
|
378
|
+
// Would mean the ident got delete in the mean time... hyper low likely hood
|
|
379
|
+
if (ident === undefined) {
|
|
380
|
+
ident = this._identsStore.initModel({
|
|
381
|
+
uuid
|
|
529
382
|
});
|
|
383
|
+
}
|
|
384
|
+
ident._type = "email";
|
|
385
|
+
ident._validation = new Date();
|
|
386
|
+
ident.setUser(ctx.parameter("user"));
|
|
387
|
+
await ident.save();
|
|
388
|
+
ctx.writeHead(302, {
|
|
389
|
+
Location: this.parameters.successRedirect + "?validation=email",
|
|
390
|
+
"X-Webda-Authentication": "success"
|
|
530
391
|
});
|
|
531
392
|
}
|
|
532
393
|
/**
|
|
@@ -537,19 +398,17 @@ class Authentication extends service_1.Service {
|
|
|
537
398
|
* @param email
|
|
538
399
|
* @returns
|
|
539
400
|
*/
|
|
540
|
-
sendRecoveryEmail(ctx, user, email) {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
return mailer.send(mailOptions);
|
|
552
|
-
});
|
|
401
|
+
async sendRecoveryEmail(ctx, user, email) {
|
|
402
|
+
let infos = await this.getPasswordRecoveryInfos(user);
|
|
403
|
+
const mailer = this.getMailMan();
|
|
404
|
+
let locale = user.locale || ctx.getLocale();
|
|
405
|
+
let mailOptions = {
|
|
406
|
+
to: email,
|
|
407
|
+
locale: locale,
|
|
408
|
+
template: "EMAIL_RECOVERY",
|
|
409
|
+
replacements: { ...this.parameters.email, infos, to: email, context: ctx }
|
|
410
|
+
};
|
|
411
|
+
return mailer.send(mailOptions);
|
|
553
412
|
}
|
|
554
413
|
/**
|
|
555
414
|
* Send an email to validate the user email by sending a unique link to
|
|
@@ -559,24 +418,26 @@ class Authentication extends service_1.Service {
|
|
|
559
418
|
* @param email
|
|
560
419
|
* @returns
|
|
561
420
|
*/
|
|
562
|
-
sendValidationEmail(ctx, email) {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
421
|
+
async sendValidationEmail(ctx, email) {
|
|
422
|
+
const mailer = this.getMailMan();
|
|
423
|
+
let replacements = {
|
|
424
|
+
...this.parameters.email,
|
|
425
|
+
context: ctx,
|
|
426
|
+
url: ctx
|
|
427
|
+
.getHttpContext()
|
|
428
|
+
.getAbsoluteUrl(`${this.parameters.url}/email/callback?email=${email}&token=${await this.generateEmailValidationToken(ctx.getCurrentUserId(), email)}`)
|
|
429
|
+
};
|
|
430
|
+
let userId = ctx.getCurrentUserId();
|
|
431
|
+
if (userId && userId.length > 0) {
|
|
432
|
+
replacements.url += "&user=" + userId;
|
|
433
|
+
}
|
|
434
|
+
let mailOptions = {
|
|
435
|
+
to: email,
|
|
436
|
+
locale: ctx.getLocale(),
|
|
437
|
+
template: "EMAIL_REGISTER",
|
|
438
|
+
replacements: replacements
|
|
439
|
+
};
|
|
440
|
+
return mailer.send(mailOptions);
|
|
580
441
|
}
|
|
581
442
|
/**
|
|
582
443
|
* Check the password match the stored hash
|
|
@@ -597,13 +458,11 @@ class Authentication extends service_1.Service {
|
|
|
597
458
|
/**
|
|
598
459
|
* Logout user
|
|
599
460
|
*/
|
|
600
|
-
logout(ctx) {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
context: ctx
|
|
604
|
-
});
|
|
605
|
-
ctx.newSession();
|
|
461
|
+
async logout(ctx) {
|
|
462
|
+
await this.emitSync("Authentication.Logout", {
|
|
463
|
+
context: ctx
|
|
606
464
|
});
|
|
465
|
+
ctx.newSession();
|
|
607
466
|
}
|
|
608
467
|
/**
|
|
609
468
|
* Login a user
|
|
@@ -613,25 +472,23 @@ class Authentication extends service_1.Service {
|
|
|
613
472
|
* @param ident
|
|
614
473
|
* @returns
|
|
615
474
|
*/
|
|
616
|
-
login(ctx, user, ident) {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
return this.emitSync("Authentication.Login", event);
|
|
634
|
-
});
|
|
475
|
+
async login(ctx, user, ident) {
|
|
476
|
+
const event = {
|
|
477
|
+
context: ctx,
|
|
478
|
+
userId: "",
|
|
479
|
+
identId: ident.uuid,
|
|
480
|
+
ident
|
|
481
|
+
};
|
|
482
|
+
if (typeof user == "object") {
|
|
483
|
+
event.userId = user.uuid;
|
|
484
|
+
event.user = user;
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
event.userId = user;
|
|
488
|
+
}
|
|
489
|
+
event.context = ctx;
|
|
490
|
+
ctx.getSession().login(event.userId, event.identId);
|
|
491
|
+
return this.emitSync("Authentication.Login", event);
|
|
635
492
|
}
|
|
636
493
|
getMailMan() {
|
|
637
494
|
return this.getService(this.parameters.email.mailer ? this.parameters.email.mailer : "Mailer");
|
|
@@ -642,40 +499,37 @@ class Authentication extends service_1.Service {
|
|
|
642
499
|
* @param ctx
|
|
643
500
|
* @param ident
|
|
644
501
|
*/
|
|
645
|
-
handleLogin(ctx, ident) {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
if (!ctx.isEnded()) {
|
|
675
|
-
throw 403;
|
|
676
|
-
}
|
|
502
|
+
async handleLogin(ctx, ident) {
|
|
503
|
+
let updates = {};
|
|
504
|
+
let user = await this._usersStore.get(ident.getUser());
|
|
505
|
+
// Check password
|
|
506
|
+
if (this.checkPassword(user.getPassword(), (await ctx.getRequestBody()).password)) {
|
|
507
|
+
if (ident._failedLogin > 0) {
|
|
508
|
+
ident._failedLogin = 0;
|
|
509
|
+
}
|
|
510
|
+
updates._lastUsed = new Date();
|
|
511
|
+
updates._failedLogin = 0;
|
|
512
|
+
updates.uuid = ident.uuid;
|
|
513
|
+
await this._identsStore.patch(updates);
|
|
514
|
+
await this.login(ctx, ident.getUser(), ident);
|
|
515
|
+
ctx.write(user);
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
await this.emitSync("Authentication.LoginFailed", {
|
|
519
|
+
user,
|
|
520
|
+
context: ctx
|
|
521
|
+
});
|
|
522
|
+
ident._failedLogin ?? (ident._failedLogin = 0);
|
|
523
|
+
updates._failedLogin = ident._failedLogin + 1;
|
|
524
|
+
updates._lastFailedLogin = new Date();
|
|
525
|
+
updates.uuid = ident.uuid;
|
|
526
|
+
// Swalow exeception issue to double check !
|
|
527
|
+
await this._identsStore.patch(updates);
|
|
528
|
+
// Allows to auto redirect user to a oauth if needed
|
|
529
|
+
if (!ctx.isEnded()) {
|
|
530
|
+
throw 403;
|
|
677
531
|
}
|
|
678
|
-
}
|
|
532
|
+
}
|
|
679
533
|
}
|
|
680
534
|
/**
|
|
681
535
|
* Handle the POST /auth/email
|
|
@@ -683,100 +537,220 @@ class Authentication extends service_1.Service {
|
|
|
683
537
|
* @param ctx
|
|
684
538
|
* @returns
|
|
685
539
|
*/
|
|
686
|
-
_handleEmail(ctx) {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
540
|
+
async _handleEmail(ctx) {
|
|
541
|
+
// If called while logged in reject
|
|
542
|
+
if (ctx.getCurrentUserId() !== undefined) {
|
|
543
|
+
throw 410;
|
|
544
|
+
}
|
|
545
|
+
let body = await ctx.getRequestBody();
|
|
546
|
+
if (body.login === undefined) {
|
|
547
|
+
throw 400;
|
|
548
|
+
}
|
|
549
|
+
const mailConfig = this.parameters.email;
|
|
550
|
+
const uuid = body.login.toLowerCase() + "_email";
|
|
551
|
+
let ident = await this._identsStore.get(uuid);
|
|
552
|
+
if (ident !== undefined && ident.getUser() !== undefined) {
|
|
553
|
+
// Register on an known user
|
|
554
|
+
if (!body.register) {
|
|
555
|
+
await this.handleLogin(ctx, ident);
|
|
556
|
+
return;
|
|
691
557
|
}
|
|
692
|
-
|
|
693
|
-
if (
|
|
694
|
-
throw
|
|
558
|
+
// If register on a validate email
|
|
559
|
+
if (ident._validation !== undefined) {
|
|
560
|
+
throw 409;
|
|
695
561
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
562
|
+
}
|
|
563
|
+
// TODO Handle add of email on authenticated user
|
|
564
|
+
const email = body.login.toLowerCase();
|
|
565
|
+
// Read the form
|
|
566
|
+
if (body.register) {
|
|
567
|
+
let validation = undefined;
|
|
568
|
+
// Need to check email before creation
|
|
569
|
+
if (!mailConfig.postValidation) {
|
|
570
|
+
if (body.token && (await this.cryptoService.hmacVerify(`${email}_${ctx.getCurrentUserId()}`, body.token))) {
|
|
571
|
+
validation = new Date();
|
|
704
572
|
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
573
|
+
else {
|
|
574
|
+
ctx.write({});
|
|
575
|
+
// token is undefined send an email
|
|
576
|
+
return this.sendValidationEmail(ctx, email);
|
|
708
577
|
}
|
|
709
578
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
// Read the form
|
|
713
|
-
if (body.register) {
|
|
714
|
-
var validation = undefined;
|
|
715
|
-
// Need to check email before creation
|
|
716
|
-
if (!mailConfig.postValidation) {
|
|
717
|
-
if (body.token && (yield this.cryptoService.hmacVerify(`${email}_${ctx.getCurrentUserId()}`, body.token))) {
|
|
718
|
-
validation = new Date();
|
|
719
|
-
}
|
|
720
|
-
else {
|
|
721
|
-
ctx.write({});
|
|
722
|
-
// token is undefined send an email
|
|
723
|
-
return this.sendValidationEmail(ctx, email);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (!body.password) {
|
|
727
|
-
throw 400;
|
|
728
|
-
}
|
|
729
|
-
// Store with a _
|
|
730
|
-
let __password = this.hashPassword(body.password);
|
|
731
|
-
yield this._verifyPassword(body.password);
|
|
732
|
-
// Remove useless attributes
|
|
733
|
-
delete body.password;
|
|
734
|
-
delete body.register;
|
|
735
|
-
delete body.token;
|
|
736
|
-
let user = yield this.registerUser(ctx, {}, uuid, Object.assign(Object.assign({}, body), { __password }));
|
|
737
|
-
yield this.emitSync("Authentication.PasswordCreate", {
|
|
738
|
-
user,
|
|
739
|
-
password: __password,
|
|
740
|
-
context: ctx
|
|
741
|
-
});
|
|
742
|
-
user = yield this._usersStore.save(user);
|
|
743
|
-
var newIdent = this._identsStore.initModel({
|
|
744
|
-
uuid: uuid,
|
|
745
|
-
_type: "email",
|
|
746
|
-
email: email
|
|
747
|
-
});
|
|
748
|
-
newIdent.setUser(user.uuid);
|
|
749
|
-
if (validation) {
|
|
750
|
-
newIdent._validation = validation;
|
|
751
|
-
}
|
|
752
|
-
else if (!mailConfig.skipEmailValidation) {
|
|
753
|
-
newIdent._lastValidationEmail = Date.now();
|
|
754
|
-
}
|
|
755
|
-
ident = yield newIdent.save();
|
|
756
|
-
yield this.login(ctx, user, ident);
|
|
757
|
-
ctx.write(user);
|
|
758
|
-
if (!validation && !mailConfig.skipEmailValidation) {
|
|
759
|
-
yield this.sendValidationEmail(ctx, email);
|
|
760
|
-
}
|
|
761
|
-
return;
|
|
579
|
+
if (!body.password) {
|
|
580
|
+
throw 400;
|
|
762
581
|
}
|
|
763
|
-
|
|
764
|
-
|
|
582
|
+
// Store with a _
|
|
583
|
+
let __password = this.hashPassword(body.password);
|
|
584
|
+
await this._verifyPassword(body.password);
|
|
585
|
+
// Remove useless attributes
|
|
586
|
+
delete body.password;
|
|
587
|
+
delete body.register;
|
|
588
|
+
delete body.token;
|
|
589
|
+
let user = await this.registerUser(ctx, {}, uuid, { ...body, __password });
|
|
590
|
+
await this.emitSync("Authentication.PasswordCreate", {
|
|
591
|
+
user,
|
|
592
|
+
password: __password,
|
|
593
|
+
context: ctx
|
|
594
|
+
});
|
|
595
|
+
user = await this._usersStore.save(user);
|
|
596
|
+
const newIdent = this._identsStore.initModel({
|
|
597
|
+
uuid: uuid,
|
|
598
|
+
_type: "email",
|
|
599
|
+
email: email
|
|
600
|
+
});
|
|
601
|
+
newIdent.setUser(user.uuid);
|
|
602
|
+
if (validation) {
|
|
603
|
+
newIdent._validation = validation;
|
|
604
|
+
}
|
|
605
|
+
else if (!mailConfig.skipEmailValidation) {
|
|
606
|
+
newIdent._lastValidationEmail = Date.now();
|
|
607
|
+
}
|
|
608
|
+
ident = await newIdent.save();
|
|
609
|
+
await this.login(ctx, user, ident);
|
|
610
|
+
ctx.write(user);
|
|
611
|
+
if (!validation && !mailConfig.skipEmailValidation) {
|
|
612
|
+
await this.sendValidationEmail(ctx, email);
|
|
613
|
+
}
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
throw 404;
|
|
765
617
|
}
|
|
766
|
-
generateEmailValidationToken(user, email) {
|
|
767
|
-
return
|
|
768
|
-
return this.cryptoService.hmac(email + "_" + user);
|
|
769
|
-
});
|
|
618
|
+
async generateEmailValidationToken(user, email) {
|
|
619
|
+
return this.cryptoService.hmac(email + "_" + user);
|
|
770
620
|
}
|
|
771
621
|
}
|
|
772
622
|
__decorate([
|
|
773
|
-
|
|
623
|
+
Inject("identStore", "idents")
|
|
774
624
|
], Authentication.prototype, "_identsStore", void 0);
|
|
775
625
|
__decorate([
|
|
776
|
-
|
|
626
|
+
Inject("userStore", "users")
|
|
777
627
|
], Authentication.prototype, "_usersStore", void 0);
|
|
778
628
|
__decorate([
|
|
779
|
-
|
|
629
|
+
Inject("CryptoService")
|
|
780
630
|
], Authentication.prototype, "cryptoService", void 0);
|
|
781
|
-
|
|
631
|
+
__decorate([
|
|
632
|
+
Route("./email/{email}/validate", ["GET"], false, {
|
|
633
|
+
get: {
|
|
634
|
+
description: "The email validation process will be start",
|
|
635
|
+
summary: "Restart email validation",
|
|
636
|
+
operationId: "startEmailRecovery",
|
|
637
|
+
responses: {
|
|
638
|
+
"204": {
|
|
639
|
+
description: ""
|
|
640
|
+
},
|
|
641
|
+
"409": {
|
|
642
|
+
description: "Email already verified for another user"
|
|
643
|
+
},
|
|
644
|
+
"412": {
|
|
645
|
+
description: "Email already verified for current user"
|
|
646
|
+
},
|
|
647
|
+
"429": {
|
|
648
|
+
description: "Validation has been initiated in the last 4 hours"
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
})
|
|
653
|
+
], Authentication.prototype, "_sendEmailValidation", null);
|
|
654
|
+
__decorate([
|
|
655
|
+
Route("./me", ["GET"], false, {
|
|
656
|
+
get: {
|
|
657
|
+
description: "Retrieve the current user from the session",
|
|
658
|
+
summary: "Get current user",
|
|
659
|
+
operationId: "getCurrentUser"
|
|
660
|
+
}
|
|
661
|
+
})
|
|
662
|
+
], Authentication.prototype, "_getMe", null);
|
|
663
|
+
__decorate([
|
|
664
|
+
Route(".", ["GET", "DELETE"], false, {
|
|
665
|
+
get: {
|
|
666
|
+
description: "Retrieve the list of available authentication",
|
|
667
|
+
summary: "Get available auths",
|
|
668
|
+
operationId: `getAuthenticationMethods`,
|
|
669
|
+
responses: {
|
|
670
|
+
"200": {
|
|
671
|
+
description: "List of authentication"
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
},
|
|
675
|
+
delete: {
|
|
676
|
+
description: "Logout current user",
|
|
677
|
+
summary: "Logout",
|
|
678
|
+
operationId: `logout`,
|
|
679
|
+
responses: {
|
|
680
|
+
"200": {}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
})
|
|
684
|
+
], Authentication.prototype, "_listAuthentications", null);
|
|
685
|
+
__decorate([
|
|
686
|
+
Route("./email/{email}/recover", ["GET"], false, {
|
|
687
|
+
get: {
|
|
688
|
+
description: "The password reset process will be start",
|
|
689
|
+
summary: "Start password recovery",
|
|
690
|
+
operationId: "startEmailRecovery",
|
|
691
|
+
responses: {
|
|
692
|
+
"204": {
|
|
693
|
+
description: ""
|
|
694
|
+
},
|
|
695
|
+
"404": {
|
|
696
|
+
description: "Email does not exist"
|
|
697
|
+
},
|
|
698
|
+
"429": {
|
|
699
|
+
description: "Recovery has been initiated in the last 4 hours"
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
})
|
|
704
|
+
], Authentication.prototype, "_passwordRecoveryEmail", null);
|
|
705
|
+
__decorate([
|
|
706
|
+
Route("./email/passwordRecovery", ["POST"], false, {
|
|
707
|
+
post: {
|
|
708
|
+
schemas: {
|
|
709
|
+
input: {
|
|
710
|
+
type: "object",
|
|
711
|
+
properties: {
|
|
712
|
+
token: {
|
|
713
|
+
type: "string"
|
|
714
|
+
},
|
|
715
|
+
expire: {
|
|
716
|
+
type: "number"
|
|
717
|
+
},
|
|
718
|
+
password: {
|
|
719
|
+
type: "string"
|
|
720
|
+
},
|
|
721
|
+
login: {
|
|
722
|
+
type: "string"
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
},
|
|
727
|
+
description: "Reinit the password if we have the right token, expire",
|
|
728
|
+
summary: "Reinit password",
|
|
729
|
+
operationId: "reinitPassword",
|
|
730
|
+
responses: {
|
|
731
|
+
"204": {
|
|
732
|
+
description: ""
|
|
733
|
+
},
|
|
734
|
+
"403": {
|
|
735
|
+
description: "Wrong Token"
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
})
|
|
740
|
+
], Authentication.prototype, "_passwordRecovery", null);
|
|
741
|
+
__decorate([
|
|
742
|
+
Route("./email/callback{?email,token,user}", ["GET"], false, {
|
|
743
|
+
hidden: true
|
|
744
|
+
})
|
|
745
|
+
], Authentication.prototype, "_handleEmailCallback", null);
|
|
746
|
+
__decorate([
|
|
747
|
+
Route("./email", ["POST"], false, {
|
|
748
|
+
post: {
|
|
749
|
+
description: "Authenticate with an email and password",
|
|
750
|
+
summary: "Authenticate with email",
|
|
751
|
+
operationId: `authWithEmail`
|
|
752
|
+
}
|
|
753
|
+
})
|
|
754
|
+
], Authentication.prototype, "_handleEmail", null);
|
|
755
|
+
export { Authentication };
|
|
782
756
|
//# sourceMappingURL=authentication.js.map
|