@friggframework/core 2.0.0--canary.393.5a4db58.0 → 2.0.0--canary.395.d07514c.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.
Files changed (31) hide show
  1. package/handlers/app-handler-helpers.js +0 -3
  2. package/handlers/backend-utils.js +34 -16
  3. package/handlers/routers/auth.js +18 -9
  4. package/handlers/routers/integration-defined-routers.js +7 -2
  5. package/handlers/routers/user.js +25 -5
  6. package/handlers/workers/integration-defined-workers.js +5 -1
  7. package/index.js +0 -2
  8. package/integrations/index.js +0 -2
  9. package/integrations/integration-factory.js +5 -6
  10. package/integrations/integration-router.js +133 -43
  11. package/module-plugin/auther.js +3 -2
  12. package/module-plugin/test/mock-api/api.js +8 -3
  13. package/module-plugin/test/mock-api/definition.js +12 -8
  14. package/package.json +5 -5
  15. package/user/tests/doubles/test-user-repository.js +115 -0
  16. package/user/tests/use-cases/create-individual-user.test.js +24 -0
  17. package/user/tests/use-cases/create-organization-user.test.js +28 -0
  18. package/user/tests/use-cases/create-token-for-user-id.test.js +19 -0
  19. package/user/tests/use-cases/get-user-from-bearer-token.test.js +64 -0
  20. package/user/tests/use-cases/login-user.test.js +148 -0
  21. package/user/use-cases/create-individual-user.js +52 -0
  22. package/user/use-cases/create-organization-user.js +39 -0
  23. package/user/use-cases/create-token-for-user-id.js +30 -0
  24. package/user/use-cases/get-user-from-bearer-token.js +50 -0
  25. package/user/use-cases/login-user.js +88 -0
  26. package/user/user-repository.js +97 -0
  27. package/user/user.js +77 -0
  28. package/handlers/routers/middleware/loadUser.js +0 -15
  29. package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
  30. package/integrations/create-frigg-backend.js +0 -31
  31. package/integrations/integration-user.js +0 -144
package/user/user.js ADDED
@@ -0,0 +1,77 @@
1
+ const bcrypt = require('bcryptjs');
2
+
3
+ /**
4
+ * Represents a user in the system. The User class is a domain entity,
5
+ * @class User
6
+ */
7
+ class User {
8
+ /**
9
+ * Creates a new User instance.
10
+ * @param {import('../database/models/IndividualUser').IndividualUser} [individualUser=null] - The individual user for the user.
11
+ * @param {import('../database/models/OrganizationUser').OrganizationUser} [organizationUser=null] - The organization user for the user.
12
+ * @param {boolean} [usePassword=false] - Whether the user has a password.
13
+ * @param {string} [primary='individual'] - The primary user type.
14
+ * @param {boolean} [individualUserRequired=true] - Whether the user is required to have an individual user.
15
+ * @param {boolean} [organizationUserRequired=false] - Whether the user is required to have an organization user.
16
+ */
17
+ constructor(individualUser = null, organizationUser = null, usePassword = false, primary = 'individual', individualUserRequired = true, organizationUserRequired = false) {
18
+ this.individualUser = individualUser;
19
+ this.organizationUser = organizationUser;
20
+ this.usePassword = usePassword;
21
+
22
+ this.config = {
23
+ primary,
24
+ individualUserRequired,
25
+ organizationUserRequired,
26
+ };
27
+ }
28
+
29
+ getPrimaryUser() {
30
+ if (this.config.primary === 'organization') {
31
+ return this.organizationUser;
32
+ }
33
+ return this.individualUser;
34
+ }
35
+
36
+ getId() {
37
+ return this.getPrimaryUser()?.id;
38
+ }
39
+
40
+ isPasswordRequired() {
41
+ return this.usePassword;
42
+ }
43
+
44
+ isPasswordValid(password) {
45
+ if (!this.isPasswordRequired()) {
46
+ return true;
47
+ }
48
+
49
+ return bcrypt.compareSync(password, this.getPrimaryUser().hashword);
50
+ }
51
+
52
+ setIndividualUser(individualUser) {
53
+ this.individualUser = individualUser;
54
+ }
55
+
56
+ setOrganizationUser(organizationUser) {
57
+ this.organizationUser = organizationUser;
58
+ }
59
+
60
+ isOrganizationUserRequired() {
61
+ return this.config.organizationUserRequired;
62
+ }
63
+
64
+ isIndividualUserRequired() {
65
+ return this.config.individualUserRequired;
66
+ }
67
+
68
+ getIndividualUser() {
69
+ return this.individualUser;
70
+ }
71
+
72
+ getOrganizationUser() {
73
+ return this.organizationUser;
74
+ }
75
+ }
76
+
77
+ module.exports = { User };
@@ -1,15 +0,0 @@
1
- const catchAsyncError = require('express-async-handler');
2
- const { User } = require('../../backend-utils');
3
-
4
- module.exports = catchAsyncError(async (req, res, next) => {
5
- const authorizationHeader = req.headers.authorization;
6
-
7
- if (authorizationHeader) {
8
- // Removes "Bearer " and trims
9
- const token = authorizationHeader.split(' ')[1].trim();
10
- // Load user for later middleware/routes to use
11
- req.user = await User.newUser({ token });
12
- }
13
-
14
- return next();
15
- });
@@ -1,12 +0,0 @@
1
- const Boom = require('@hapi/boom');
2
-
3
- // CheckLoggedIn Middleware
4
- const requireLoggedInUser = (req, res, next) => {
5
- if (!req.user || !req.user.isLoggedIn()) {
6
- throw Boom.unauthorized('Invalid Token');
7
- }
8
-
9
- next();
10
- };
11
-
12
- module.exports = { requireLoggedInUser };
@@ -1,31 +0,0 @@
1
- const {IntegrationFactory, IntegrationHelper} = require('./integration-factory');
2
- const User = require('./integration-user');
3
-
4
- function createFriggBackend(appDefinition) {
5
- const {integrations = [], user=null} = appDefinition
6
- const integrationFactory = new IntegrationFactory(integrations);
7
- if (user) {
8
- if (user.usePassword) {
9
- User.usePassword = true;
10
- }
11
- if (user.primary === 'organization') {
12
- User.primary = User.OrganizationUser
13
- }
14
- if (user.individualUserRequired !== undefined) {
15
- User.individualUserRequired = user.individualUserRequired
16
- }
17
- if (user.organizationUserRequired !== undefined) {
18
- User.organizationUserRequired = user.organizationUserRequired
19
- }
20
-
21
- }
22
- const backend = {
23
- integrationFactory,
24
- moduleFactory: integrationFactory.moduleFactory,
25
- IntegrationHelper,
26
- User: User
27
- }
28
- return backend
29
- }
30
-
31
- module.exports = { createFriggBackend }
@@ -1,144 +0,0 @@
1
- const bcrypt = require('bcryptjs');
2
- const crypto = require('crypto');
3
- const { get } = require('../assertions');
4
- const { Token } = require('../database/models/Token');
5
- const { IndividualUser } = require('../database/models/IndividualUser');
6
- const { OrganizationUser } = require('../database/models/OrganizationUser');
7
- const Boom = require('@hapi/boom');
8
-
9
- class User {
10
- static IndividualUser = IndividualUser;
11
- static OrganizationUser = OrganizationUser;
12
- static Token = Token;
13
- static usePassword = false
14
- static primary = User.IndividualUser;
15
- static individualUserRequired = true;
16
- static organizationUserRequired = false;
17
-
18
- constructor() {
19
- this.user = null;
20
- this.individualUser = null;
21
- this.organizationUser = null;
22
- }
23
-
24
- getPrimaryUser() {
25
- if (User.primary === User.OrganizationUser) {
26
- return this.organizationUser;
27
- }
28
- return this.individualUser;
29
- }
30
-
31
- getUserId() {
32
- return this.getPrimaryUser()?.id;
33
- }
34
-
35
- isLoggedIn() {
36
- return Boolean(this.getUserId());
37
- }
38
-
39
- async createUserToken(minutes) {
40
- const rawToken = crypto.randomBytes(20).toString('hex');
41
- const createdToken = await User.Token.createTokenWithExpire(this.getUserId(), rawToken, 120);
42
- const tokenBuf = User.Token.createBase64BufferToken(createdToken, rawToken);
43
- return tokenBuf;
44
- }
45
-
46
- static async newUser(params={}) {
47
- const user = new User();
48
- const token = get(params, 'token', null);
49
- if (token) {
50
- const jsonToken = this.Token.getJSONTokenFromBase64BufferToken(token);
51
- const sessionToken = await this.Token.validateAndGetTokenFromJSONToken(jsonToken);
52
- if (this.primary === User.OrganizationUser) {
53
- user.organizationUser = await this.OrganizationUser.findById(sessionToken.user);
54
- } else {
55
- user.individualUser = await this.IndividualUser.findById(sessionToken.user);
56
- }
57
- }
58
- return user;
59
- }
60
-
61
- static async createIndividualUser(params) {
62
- const user = await this.newUser(params);
63
- let hashword;
64
- if (this.usePassword) {
65
- hashword = get(params, 'password');
66
- }
67
-
68
- const email = get(params, 'email', null);
69
- const username = get(params, 'username', null);
70
- if (!email && !username) {
71
- throw Boom.badRequest('email or username is required');
72
- }
73
-
74
- const appUserId = get(params, 'appUserId', null);
75
- const organizationUserId = get(params, 'organizationUserId', null);
76
-
77
- user.individualUser = await this.IndividualUser.create({
78
- email,
79
- username,
80
- hashword,
81
- appUserId,
82
- organizationUser: organizationUserId,
83
- });
84
- return user;
85
- }
86
-
87
- static async createOrganizationUser(params) {
88
- const user = await this.newUser(params);
89
- const name = get(params, 'name');
90
- const appOrgId = get(params, 'appOrgId');
91
- user.organizationUser = await this.OrganizationUser.create({
92
- name,
93
- appOrgId,
94
- });
95
- return user;
96
- }
97
-
98
- static async loginUser(params) {
99
- const user = await this.newUser(params);
100
-
101
- if (this.usePassword){
102
- const username = get(params, 'username');
103
- const password = get(params, 'password');
104
-
105
- const individualUser = await this.IndividualUser.findOne({username});
106
-
107
- if (!individualUser) {
108
- throw Boom.unauthorized('incorrect username or password');
109
- }
110
-
111
- const isValid = await bcrypt.compareSync(password, individualUser.hashword);
112
- if (!isValid) {
113
- throw Boom.unauthorized('incorrect username or password');
114
- }
115
- user.individualUser = individualUser;
116
- }
117
- else {
118
- const appUserId = get(params, 'appUserId', null);
119
- user.individualUser = await this.IndividualUser.getUserByAppUserId(
120
- appUserId
121
- );
122
- }
123
-
124
- const appOrgId = get(params, 'appOrgId', null);
125
- user.organizationUser = await this.OrganizationUser.getUserByAppOrgId(
126
- appOrgId
127
- );
128
-
129
- if (this.individualUserRequired) {
130
- if (!user.individualUser) {
131
- throw Boom.unauthorized('user not found');
132
- }
133
- }
134
-
135
- if (this.organizationUserRequired) {
136
- if (!user.organizationUser) {
137
- throw Boom.unauthorized(`org user ${appOrgId} not found`);
138
- }
139
- }
140
- return user;
141
- }
142
- }
143
-
144
- module.exports = User;