@solidxai/core 0.1.9-beta.7 → 0.1.9
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/LICENSE +89 -0
- package/README.md +3 -1
- package/dist/constants/chatter-message.constants.d.ts +6 -0
- package/dist/constants/chatter-message.constants.d.ts.map +1 -1
- package/dist/constants/chatter-message.constants.js +7 -1
- package/dist/constants/chatter-message.constants.js.map +1 -1
- package/dist/controllers/authentication.controller.d.ts +12 -0
- package/dist/controllers/authentication.controller.d.ts.map +1 -1
- package/dist/controllers/authentication.controller.js +13 -0
- package/dist/controllers/authentication.controller.js.map +1 -1
- package/dist/controllers/chatter-message.controller.d.ts +1 -0
- package/dist/controllers/chatter-message.controller.d.ts.map +1 -1
- package/dist/controllers/chatter-message.controller.js +12 -0
- package/dist/controllers/chatter-message.controller.js.map +1 -1
- package/dist/controllers/facebook-authentication.controller.d.ts +27 -0
- package/dist/controllers/facebook-authentication.controller.d.ts.map +1 -0
- package/dist/controllers/facebook-authentication.controller.js +117 -0
- package/dist/controllers/facebook-authentication.controller.js.map +1 -0
- package/dist/controllers/menu-item-metadata.controller.d.ts +1 -0
- package/dist/controllers/menu-item-metadata.controller.d.ts.map +1 -1
- package/dist/controllers/menu-item-metadata.controller.js +15 -0
- package/dist/controllers/menu-item-metadata.controller.js.map +1 -1
- package/dist/controllers/microsoft-authentication.controller.d.ts +27 -0
- package/dist/controllers/microsoft-authentication.controller.d.ts.map +1 -0
- package/dist/controllers/microsoft-authentication.controller.js +118 -0
- package/dist/controllers/microsoft-authentication.controller.js.map +1 -0
- package/dist/controllers/setting.controller.d.ts +2 -2
- package/dist/controllers/setting.controller.js +2 -2
- package/dist/decorators/auth.decorator.d.ts.map +1 -1
- package/dist/decorators/computed-field-provider.decorator.d.ts.map +1 -1
- package/dist/decorators/dashboard-question-data-provider.decorator.d.ts.map +1 -1
- package/dist/decorators/dashboard-selection-provider.decorator.d.ts.map +1 -1
- package/dist/decorators/disallow-in-production.decorator.d.ts.map +1 -1
- package/dist/decorators/error-codes-provider.decorator.d.ts.map +1 -1
- package/dist/decorators/extension-user-creation-provider.decorator.d.ts.map +1 -1
- package/dist/decorators/is-not-in-enum.decorator.d.ts.map +1 -1
- package/dist/decorators/mail-provider.decorator.d.ts.map +1 -1
- package/dist/decorators/roles.decorator.d.ts.map +1 -1
- package/dist/decorators/scheduled-job-provider.decorator.d.ts.map +1 -1
- package/dist/decorators/security-rule-config-provider.decorator.d.ts.map +1 -1
- package/dist/decorators/selection-provider.decorator.d.ts.map +1 -1
- package/dist/decorators/sms-provider.decorator.d.ts.map +1 -1
- package/dist/decorators/solid-database-module.decorator.d.ts.map +1 -1
- package/dist/decorators/whatsapp-provider.decorator.d.ts.map +1 -1
- package/dist/dtos/create-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/create-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/create-chatter-message.dto.js +7 -1
- package/dist/dtos/create-chatter-message.dto.js.map +1 -1
- package/dist/dtos/post-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/post-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/post-chatter-message.dto.js +6 -1
- package/dist/dtos/post-chatter-message.dto.js.map +1 -1
- package/dist/dtos/update-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/update-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/update-chatter-message.dto.js +7 -1
- package/dist/dtos/update-chatter-message.dto.js.map +1 -1
- package/dist/entities/chatter-message.entity.d.ts +1 -0
- package/dist/entities/chatter-message.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message.entity.js +5 -1
- package/dist/entities/chatter-message.entity.js.map +1 -1
- package/dist/entities/user.entity.d.ts +8 -0
- package/dist/entities/user.entity.d.ts.map +1 -1
- package/dist/entities/user.entity.js +33 -1
- package/dist/entities/user.entity.js.map +1 -1
- package/dist/helpers/cors.helper.js +1 -1
- package/dist/helpers/cors.helper.js.map +1 -1
- package/dist/helpers/facebook-oauth.helper.d.ts +8 -0
- package/dist/helpers/facebook-oauth.helper.d.ts.map +1 -0
- package/dist/helpers/facebook-oauth.helper.js +11 -0
- package/dist/helpers/facebook-oauth.helper.js.map +1 -0
- package/dist/helpers/microsoft-oauth.helper.d.ts +9 -0
- package/dist/helpers/microsoft-oauth.helper.d.ts.map +1 -0
- package/dist/helpers/microsoft-oauth.helper.js +12 -0
- package/dist/helpers/microsoft-oauth.helper.js.map +1 -0
- package/dist/helpers/security.helper.d.ts.map +1 -1
- package/dist/helpers/string.helper.d.ts.map +1 -1
- package/dist/helpers/user-helper.d.ts.map +1 -1
- package/dist/helpers/user-helper.js +4 -0
- package/dist/helpers/user-helper.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +19 -0
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/passport-strategies/facebook-oauth.strategy.d.ts +16 -0
- package/dist/passport-strategies/facebook-oauth.strategy.d.ts.map +1 -0
- package/dist/passport-strategies/facebook-oauth.strategy.js +96 -0
- package/dist/passport-strategies/facebook-oauth.strategy.js.map +1 -0
- package/dist/passport-strategies/microsoft-oauth.strategy.d.ts +14 -0
- package/dist/passport-strategies/microsoft-oauth.strategy.d.ts.map +1 -0
- package/dist/passport-strategies/microsoft-oauth.strategy.js +77 -0
- package/dist/passport-strategies/microsoft-oauth.strategy.js.map +1 -0
- package/dist/seeders/seed-data/solid-core-metadata.json +27 -58
- package/dist/services/api-key.service.d.ts +17 -1
- package/dist/services/api-key.service.d.ts.map +1 -1
- package/dist/services/api-key.service.js +38 -2
- package/dist/services/api-key.service.js.map +1 -1
- package/dist/services/authentication.service.d.ts +61 -27
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +356 -164
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/chatter-message.service.d.ts +1 -0
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +24 -7
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/model-metadata.service.js +1 -1
- package/dist/services/model-metadata.service.js.map +1 -1
- package/dist/services/setting.service.d.ts +5 -2
- package/dist/services/setting.service.d.ts.map +1 -1
- package/dist/services/setting.service.js +51 -6
- package/dist/services/setting.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +846 -0
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +1096 -117
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/services/user.service.d.ts +12 -8
- package/dist/services/user.service.d.ts.map +1 -1
- package/dist/services/user.service.js +143 -32
- package/dist/services/user.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +11 -3
- package/dist/solid-core.module.js.map +1 -1
- package/dist/transformers/array-transformer.d.ts.map +1 -1
- package/dist/transformers/boolean-transformer.d.ts.map +1 -1
- package/dist/transformers/datetime-transformer.d.ts.map +1 -1
- package/dist/transformers/integer-transformer.d.ts.map +1 -1
- package/dist/validators/is-parsable-int.d.ts.map +1 -1
- package/nest +0 -0
- package/package.json +8 -2
- package/src/constants/chatter-message.constants.ts +7 -0
- package/src/controllers/authentication.controller.ts +8 -1
- package/src/controllers/chatter-message.controller.ts +6 -0
- package/src/controllers/facebook-authentication.controller.ts +113 -0
- package/src/controllers/menu-item-metadata.controller.ts +21 -15
- package/src/controllers/microsoft-authentication.controller.ts +116 -0
- package/src/dtos/create-chatter-message.dto.ts +11 -0
- package/src/dtos/post-chatter-message.dto.ts +4 -0
- package/src/dtos/update-chatter-message.dto.ts +13 -1
- package/src/entities/chatter-message.entity.ts +4 -1
- package/src/entities/user.entity.ts +32 -0
- package/src/helpers/cors.helper.ts +1 -1
- package/src/helpers/facebook-oauth.helper.ts +17 -0
- package/src/helpers/microsoft-oauth.helper.ts +19 -0
- package/src/helpers/user-helper.ts +4 -0
- package/src/index.ts +2 -0
- package/src/interfaces.ts +32 -1
- package/src/passport-strategies/facebook-oauth.strategy.ts +115 -0
- package/src/passport-strategies/microsoft-oauth.strategy.ts +70 -0
- package/src/seeders/seed-data/solid-core-metadata.json +27 -58
- package/src/services/api-key.service.ts +77 -35
- package/src/services/authentication.service.ts +1947 -1432
- package/src/services/chatter-message.service.ts +23 -3
- package/src/services/model-metadata.service.ts +1 -1
- package/src/services/setting.service.ts +64 -8
- package/src/services/settings/default-settings-provider.service.ts +1168 -156
- package/src/services/user.service.ts +220 -61
- package/src/solid-core.module.ts +25 -8
- package/dev-grooming-docs/ozzy-prompts.txt +0 -70
- package/docs/grouping-enhancements.md +0 -89
- package/docs/seed-changes.md +0 -65
- package/docs/test-data-workflow.md +0 -200
- package/docs/type-declaration-import-issue.md +0 -24
|
@@ -1,37 +1,68 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
BadRequestException,
|
|
3
|
+
forwardRef,
|
|
4
|
+
Inject,
|
|
5
|
+
Injectable,
|
|
6
|
+
} from "@nestjs/common";
|
|
2
7
|
import { ModuleRef } from "@nestjs/core";
|
|
3
|
-
import { InjectEntityManager, InjectRepository } from
|
|
4
|
-
import { CRUDService } from
|
|
5
|
-
import { EntityManager, Repository } from
|
|
8
|
+
import { InjectEntityManager, InjectRepository } from "@nestjs/typeorm";
|
|
9
|
+
import { CRUDService } from "src/services/crud.service";
|
|
10
|
+
import { EntityManager, Repository } from "typeorm";
|
|
6
11
|
import type { SolidCoreSetting } from "src/services/settings/default-settings-provider.service";
|
|
7
12
|
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { HashingService } from './hashing.service';
|
|
13
|
+
import { OauthUserDto } from "../dtos/oauth-user-dto";
|
|
14
|
+
import { RoleMetadata } from "../entities/role-metadata.entity";
|
|
15
|
+
import { User } from "../entities/user.entity";
|
|
16
|
+
import { ActiveUserData } from "../interfaces/active-user-data.interface";
|
|
17
|
+
import { ERROR_MESSAGES } from "src/constants/error-messages";
|
|
18
|
+
import { UserRepository } from "src/repository/user.repository";
|
|
19
|
+
import { RoleMetadataRepository } from "src/repository/role-metadata.repository";
|
|
20
|
+
import { HashingService } from "./hashing.service";
|
|
17
21
|
|
|
18
22
|
@Injectable()
|
|
19
23
|
export class UserService extends CRUDService<User> {
|
|
24
|
+
private buildFacebookUsernameBase(name?: string): string {
|
|
25
|
+
const normalized = (name || "")
|
|
26
|
+
.trim()
|
|
27
|
+
.toLowerCase()
|
|
28
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
29
|
+
.replace(/^_+|_+$/g, "");
|
|
30
|
+
return normalized || "facebook_user";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private async resolveUniqueUsername(
|
|
34
|
+
preferredUsername: string,
|
|
35
|
+
// fallbackUsername: string,
|
|
36
|
+
): Promise<string> {
|
|
37
|
+
let candidate = preferredUsername;
|
|
38
|
+
let suffix = 0;
|
|
39
|
+
|
|
40
|
+
while (await this.repo.findOne({ where: { username: candidate } })) {
|
|
41
|
+
suffix += 1;
|
|
42
|
+
candidate = `${preferredUsername}_${suffix}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (candidate) {
|
|
46
|
+
return candidate;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// return fallbackUsername;
|
|
50
|
+
}
|
|
51
|
+
|
|
20
52
|
constructor(
|
|
21
53
|
readonly hashingService: HashingService,
|
|
22
54
|
@InjectEntityManager()
|
|
23
55
|
readonly entityManager: EntityManager,
|
|
24
56
|
// @InjectRepository(User, 'default')
|
|
25
57
|
readonly repo: UserRepository,
|
|
26
|
-
@InjectRepository(User,
|
|
58
|
+
@InjectRepository(User, "default")
|
|
27
59
|
readonly nonSecurityRuleAwareRepo: Repository<User>,
|
|
28
60
|
// @InjectRepository(RoleMetadata)
|
|
29
61
|
// private readonly roleRepository: Repository<RoleMetadata>,
|
|
30
62
|
private readonly roleRepository: RoleMetadataRepository,
|
|
31
63
|
readonly moduleRef: ModuleRef,
|
|
32
|
-
|
|
33
64
|
) {
|
|
34
|
-
super(entityManager, repo,
|
|
65
|
+
super(entityManager, repo, "user", "solid-core", moduleRef);
|
|
35
66
|
}
|
|
36
67
|
|
|
37
68
|
override async delete(id: number, solidRequestContext: any = {}) {
|
|
@@ -44,13 +75,19 @@ export class UserService extends CRUDService<User> {
|
|
|
44
75
|
return super.delete(id, solidRequestContext);
|
|
45
76
|
}
|
|
46
77
|
|
|
47
|
-
override async deleteMany(
|
|
78
|
+
override async deleteMany(
|
|
79
|
+
ids: number[],
|
|
80
|
+
solidRequestContext: any = {},
|
|
81
|
+
): Promise<any> {
|
|
48
82
|
if (!ids || ids.length === 0) {
|
|
49
83
|
throw new Error(ERROR_MESSAGES.DELETE_IDS_REQUIRED);
|
|
50
84
|
}
|
|
51
85
|
|
|
52
86
|
// ❌ If the active user is trying to delete themselves
|
|
53
|
-
if (
|
|
87
|
+
if (
|
|
88
|
+
solidRequestContext?.activeUser?.sub &&
|
|
89
|
+
ids.includes(solidRequestContext.activeUser.id)
|
|
90
|
+
) {
|
|
54
91
|
throw new BadRequestException(ERROR_MESSAGES.DELETE_SELF_NOT_ALLOWED);
|
|
55
92
|
}
|
|
56
93
|
|
|
@@ -60,9 +97,9 @@ export class UserService extends CRUDService<User> {
|
|
|
60
97
|
async findOneByEmail(email: string): Promise<User> {
|
|
61
98
|
return await this.repo.findOne({
|
|
62
99
|
where: {
|
|
63
|
-
email: email
|
|
100
|
+
email: email,
|
|
64
101
|
},
|
|
65
|
-
relations: {}
|
|
102
|
+
relations: {},
|
|
66
103
|
});
|
|
67
104
|
// if (!entity) {
|
|
68
105
|
// throw new NotFoundException(`user with email #${email} not found`);
|
|
@@ -73,18 +110,18 @@ export class UserService extends CRUDService<User> {
|
|
|
73
110
|
async findOneByAccessCode(accessCode: string): Promise<User> {
|
|
74
111
|
return await this.repo.findOne({
|
|
75
112
|
where: {
|
|
76
|
-
accessCode: accessCode
|
|
113
|
+
accessCode: accessCode,
|
|
77
114
|
},
|
|
78
|
-
relations: {}
|
|
115
|
+
relations: {},
|
|
79
116
|
});
|
|
80
117
|
}
|
|
81
118
|
|
|
82
119
|
async findOneByUsername(username: string): Promise<User> {
|
|
83
120
|
return await this.repo.findOne({
|
|
84
121
|
where: {
|
|
85
|
-
username: username
|
|
122
|
+
username: username,
|
|
86
123
|
},
|
|
87
|
-
relations: {}
|
|
124
|
+
relations: {},
|
|
88
125
|
});
|
|
89
126
|
// if (!entity) {
|
|
90
127
|
// throw new NotFoundException(`user with username ${username} not found`);
|
|
@@ -96,8 +133,8 @@ export class UserService extends CRUDService<User> {
|
|
|
96
133
|
const user = await this.repo.findOne({
|
|
97
134
|
where: { id: id },
|
|
98
135
|
relations: {
|
|
99
|
-
roles: true
|
|
100
|
-
}
|
|
136
|
+
roles: true,
|
|
137
|
+
},
|
|
101
138
|
});
|
|
102
139
|
if (!user) {
|
|
103
140
|
throw new Error(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
@@ -113,21 +150,22 @@ export class UserService extends CRUDService<User> {
|
|
|
113
150
|
const user = await this.repo.findOne({
|
|
114
151
|
where: { username: username },
|
|
115
152
|
relations: {
|
|
116
|
-
roles: true
|
|
117
|
-
}
|
|
153
|
+
roles: true,
|
|
154
|
+
},
|
|
118
155
|
});
|
|
119
156
|
if (!user) {
|
|
120
157
|
throw new Error(ERROR_MESSAGES.USER_NOT_FOUND_BY_USERNAME(username));
|
|
121
158
|
}
|
|
122
|
-
const role = await this.roleRepository.findOne({
|
|
159
|
+
const role = await this.roleRepository.findOne({
|
|
160
|
+
where: { name: roleName },
|
|
161
|
+
});
|
|
123
162
|
if (!role) {
|
|
124
163
|
throw new Error(ERROR_MESSAGES.ROLE_NOT_FOUND(roleName));
|
|
125
164
|
}
|
|
126
165
|
|
|
127
166
|
if (user.roles && user.roles.length > 0) {
|
|
128
167
|
user.roles.push(role);
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
168
|
+
} else {
|
|
131
169
|
user.roles = [role];
|
|
132
170
|
}
|
|
133
171
|
|
|
@@ -137,7 +175,7 @@ export class UserService extends CRUDService<User> {
|
|
|
137
175
|
async addRolesToUser(username: string, roleNames: string[]): Promise<User> {
|
|
138
176
|
const user = await this.nonSecurityRuleAwareRepo.findOne({
|
|
139
177
|
where: { username: username },
|
|
140
|
-
relations: { roles: true }
|
|
178
|
+
relations: { roles: true },
|
|
141
179
|
});
|
|
142
180
|
|
|
143
181
|
if (!user) {
|
|
@@ -145,43 +183,47 @@ export class UserService extends CRUDService<User> {
|
|
|
145
183
|
}
|
|
146
184
|
|
|
147
185
|
const roles = await this.roleRepository.find({
|
|
148
|
-
where: roleNames.map(roleName => ({ name: roleName }))
|
|
186
|
+
where: roleNames.map((roleName) => ({ name: roleName })),
|
|
149
187
|
});
|
|
150
188
|
|
|
151
189
|
if (roles.length !== roleNames.length) {
|
|
152
|
-
const foundRoleNames = roles.map(role => role.name);
|
|
153
|
-
const missingRoles = roleNames.filter(
|
|
190
|
+
const foundRoleNames = roles.map((role) => role.name);
|
|
191
|
+
const missingRoles = roleNames.filter(
|
|
192
|
+
(roleName) => !foundRoleNames.includes(roleName),
|
|
193
|
+
);
|
|
154
194
|
throw new Error(ERROR_MESSAGES.ROLES_NOT_FOUND(missingRoles));
|
|
155
195
|
}
|
|
156
196
|
|
|
157
|
-
const currentRoles = user.roles.map(role => role.name);
|
|
197
|
+
const currentRoles = user.roles.map((role) => role.name);
|
|
158
198
|
|
|
159
|
-
const rolesToAdd = roles.filter(
|
|
199
|
+
const rolesToAdd = roles.filter(
|
|
200
|
+
(role) => !currentRoles.includes(role.name),
|
|
201
|
+
);
|
|
160
202
|
|
|
161
|
-
const rolesToRemove = user.roles.filter(
|
|
203
|
+
const rolesToRemove = user.roles.filter(
|
|
204
|
+
(role) => !roleNames.includes(role.name),
|
|
205
|
+
);
|
|
162
206
|
|
|
163
207
|
if (rolesToAdd.length > 0) {
|
|
164
208
|
user.roles.push(...rolesToAdd);
|
|
165
209
|
}
|
|
166
210
|
|
|
167
211
|
if (rolesToRemove.length > 0) {
|
|
168
|
-
user.roles = user.roles.filter(role => !rolesToRemove.includes(role));
|
|
212
|
+
user.roles = user.roles.filter((role) => !rolesToRemove.includes(role));
|
|
169
213
|
}
|
|
170
214
|
|
|
171
215
|
return await this.nonSecurityRuleAwareRepo.save(user);
|
|
172
216
|
}
|
|
173
217
|
|
|
174
|
-
|
|
175
218
|
async removeRoleFromUser(username: string, roleName: string): Promise<User> {
|
|
176
|
-
|
|
177
219
|
// load the role with the respective permissions.
|
|
178
220
|
const user = await this.repo.findOne({
|
|
179
221
|
where: {
|
|
180
|
-
username: username
|
|
222
|
+
username: username,
|
|
181
223
|
},
|
|
182
224
|
relations: {
|
|
183
|
-
roles: true
|
|
184
|
-
}
|
|
225
|
+
roles: true,
|
|
226
|
+
},
|
|
185
227
|
});
|
|
186
228
|
|
|
187
229
|
if (!user) {
|
|
@@ -189,7 +231,7 @@ export class UserService extends CRUDService<User> {
|
|
|
189
231
|
}
|
|
190
232
|
|
|
191
233
|
// modify the permissions array.
|
|
192
|
-
user.roles = user.roles.filter(role => role.name !== roleName);
|
|
234
|
+
user.roles = user.roles.filter((role) => role.name !== roleName);
|
|
193
235
|
|
|
194
236
|
return await this.repo.save(user);
|
|
195
237
|
}
|
|
@@ -201,11 +243,11 @@ export class UserService extends CRUDService<User> {
|
|
|
201
243
|
email: oauthUserDto.email,
|
|
202
244
|
},
|
|
203
245
|
relations: {
|
|
204
|
-
roles: true
|
|
205
|
-
}
|
|
246
|
+
roles: true,
|
|
247
|
+
},
|
|
206
248
|
});
|
|
207
249
|
|
|
208
|
-
// if we are unable to find a user then we need to create one.
|
|
250
|
+
// if we are unable to find a user then we need to create one.
|
|
209
251
|
if (!user) {
|
|
210
252
|
const user = new User();
|
|
211
253
|
user.username = oauthUserDto.email;
|
|
@@ -220,9 +262,12 @@ export class UserService extends CRUDService<User> {
|
|
|
220
262
|
const savedUser = await this.repo.save(user);
|
|
221
263
|
|
|
222
264
|
// Initialize the user roles
|
|
223
|
-
await this.initializeRolesForNewUser(
|
|
265
|
+
await this.initializeRolesForNewUser(
|
|
266
|
+
[this.settingService.getConfigValue<SolidCoreSetting>("defaultRole")],
|
|
267
|
+
savedUser,
|
|
268
|
+
);
|
|
224
269
|
}
|
|
225
|
-
// else we update the user and store the generated code & access token.
|
|
270
|
+
// else we update the user and store the generated code & access token.
|
|
226
271
|
else {
|
|
227
272
|
const entity = await this.repo.preload({
|
|
228
273
|
id: user.id,
|
|
@@ -239,21 +284,138 @@ export class UserService extends CRUDService<User> {
|
|
|
239
284
|
return user;
|
|
240
285
|
}
|
|
241
286
|
|
|
242
|
-
async
|
|
287
|
+
async resolveUserOnOauthFacebook(oauthUserDto: OauthUserDto): Promise<User> {
|
|
288
|
+
const normalizedEmail = oauthUserDto.email?.trim().toLowerCase() || null;
|
|
289
|
+
let user: User | null = null;
|
|
290
|
+
|
|
291
|
+
if (oauthUserDto.providerId) {
|
|
292
|
+
user = await this.repo.findOne({
|
|
293
|
+
where: {
|
|
294
|
+
facebookId: oauthUserDto.providerId,
|
|
295
|
+
},
|
|
296
|
+
relations: {
|
|
297
|
+
roles: true,
|
|
298
|
+
},
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (!user) {
|
|
303
|
+
const facebookProviderFallback = `facebook_${oauthUserDto.providerId}`;
|
|
304
|
+
const facebookNameUsername = this.buildFacebookUsernameBase(
|
|
305
|
+
oauthUserDto.name,
|
|
306
|
+
);
|
|
307
|
+
// let username = normalizedEmail || facebookNameUsername;
|
|
308
|
+
let username = facebookNameUsername;
|
|
309
|
+
|
|
310
|
+
let email = normalizedEmail;
|
|
311
|
+
|
|
312
|
+
// Avoid clashing with local users that already own the same email/username.
|
|
313
|
+
if (normalizedEmail) {
|
|
314
|
+
const existingByEmail = await this.repo.findOne({
|
|
315
|
+
where: { email: normalizedEmail },
|
|
316
|
+
});
|
|
317
|
+
if (existingByEmail) {
|
|
318
|
+
username = facebookNameUsername;
|
|
319
|
+
email = null;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
username = await this.resolveUniqueUsername(
|
|
323
|
+
username,
|
|
324
|
+
// facebookProviderFallback,
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
const newUser = new User();
|
|
328
|
+
newUser.username = username;
|
|
329
|
+
newUser.email = email;
|
|
330
|
+
newUser.fullName = oauthUserDto.name;
|
|
331
|
+
newUser.lastLoginProvider = oauthUserDto.provider;
|
|
332
|
+
newUser.accessCode = oauthUserDto.accessCode;
|
|
333
|
+
newUser.facebookAccessToken = oauthUserDto.accessToken;
|
|
334
|
+
newUser.facebookId = oauthUserDto.providerId;
|
|
335
|
+
newUser.facebookProfilePicture = oauthUserDto.picture;
|
|
336
|
+
|
|
337
|
+
const savedUser = await this.repo.save(newUser);
|
|
338
|
+
|
|
339
|
+
await this.initializeRolesForNewUser(
|
|
340
|
+
[this.settingService.getConfigValue<SolidCoreSetting>("defaultRole")],
|
|
341
|
+
savedUser,
|
|
342
|
+
);
|
|
343
|
+
return savedUser;
|
|
344
|
+
} else {
|
|
345
|
+
const entity = await this.repo.preload({
|
|
346
|
+
id: user.id,
|
|
347
|
+
lastLoginProvider: oauthUserDto.provider,
|
|
348
|
+
accessCode: oauthUserDto.accessCode,
|
|
349
|
+
facebookAccessToken: oauthUserDto.accessToken,
|
|
350
|
+
facebookId: oauthUserDto.providerId,
|
|
351
|
+
facebookProfilePicture: oauthUserDto.picture,
|
|
352
|
+
});
|
|
353
|
+
await this.repo.save(entity);
|
|
354
|
+
return entity;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
async resolveUserOnOauthMicrosoft(oauthUserDto: OauthUserDto): Promise<User> {
|
|
359
|
+
const user = await this.repo.findOne({
|
|
360
|
+
where: {
|
|
361
|
+
email: oauthUserDto.email,
|
|
362
|
+
},
|
|
363
|
+
relations: {
|
|
364
|
+
roles: true,
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
if (!user) {
|
|
369
|
+
const newUser = new User();
|
|
370
|
+
newUser.username = oauthUserDto.email;
|
|
371
|
+
newUser.email = oauthUserDto.email;
|
|
372
|
+
newUser.fullName = oauthUserDto.name;
|
|
373
|
+
newUser.lastLoginProvider = oauthUserDto.provider;
|
|
374
|
+
newUser.accessCode = oauthUserDto.accessCode;
|
|
375
|
+
newUser.microsoftAccessToken = oauthUserDto.accessToken;
|
|
376
|
+
newUser.microsoftId = oauthUserDto.providerId;
|
|
377
|
+
newUser.microsoftProfilePicture = oauthUserDto.picture;
|
|
378
|
+
|
|
379
|
+
const savedUser = await this.repo.save(newUser);
|
|
380
|
+
|
|
381
|
+
await this.initializeRolesForNewUser(
|
|
382
|
+
[this.settingService.getConfigValue<SolidCoreSetting>("defaultRole")],
|
|
383
|
+
savedUser,
|
|
384
|
+
);
|
|
385
|
+
} else {
|
|
386
|
+
const entity = await this.repo.preload({
|
|
387
|
+
id: user.id,
|
|
388
|
+
lastLoginProvider: oauthUserDto.provider,
|
|
389
|
+
accessCode: oauthUserDto.accessCode,
|
|
390
|
+
microsoftAccessToken: oauthUserDto.accessToken,
|
|
391
|
+
microsoftId: oauthUserDto.providerId,
|
|
392
|
+
microsoftProfilePicture: oauthUserDto.picture,
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
await this.repo.save(entity);
|
|
396
|
+
}
|
|
397
|
+
return user;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
async findUsersByRole(
|
|
401
|
+
roleName: string,
|
|
402
|
+
relations: any = {},
|
|
403
|
+
): Promise<User[]> {
|
|
243
404
|
return await this.repo.find({
|
|
244
405
|
where: {
|
|
245
406
|
roles: {
|
|
246
|
-
name: roleName
|
|
247
|
-
}
|
|
407
|
+
name: roleName,
|
|
408
|
+
},
|
|
248
409
|
},
|
|
249
|
-
relations: relations
|
|
410
|
+
relations: relations,
|
|
250
411
|
});
|
|
251
412
|
}
|
|
252
413
|
|
|
253
414
|
async checkIfPermissionExists(query: any, activeUser: ActiveUserData) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
415
|
+
const matchingPermssions = activeUser.permissions.filter((p) =>
|
|
416
|
+
query.permissionNames.includes(p),
|
|
417
|
+
);
|
|
418
|
+
return matchingPermssions;
|
|
257
419
|
}
|
|
258
420
|
|
|
259
421
|
async initializeRolesForNewUser(roles: string[], user: User) {
|
|
@@ -261,7 +423,7 @@ export class UserService extends CRUDService<User> {
|
|
|
261
423
|
throw new BadRequestException(ERROR_MESSAGES.USER_MISSING_ID);
|
|
262
424
|
}
|
|
263
425
|
let userRoles = [];
|
|
264
|
-
// Default Internal user role assigned
|
|
426
|
+
// Default Internal user role assigned
|
|
265
427
|
userRoles.push("Internal User");
|
|
266
428
|
if (roles) {
|
|
267
429
|
userRoles = [...userRoles, ...roles];
|
|
@@ -285,7 +447,4 @@ export class UserService extends CRUDService<User> {
|
|
|
285
447
|
passwordSchemeVersion: this.hashingService.currentVersion(),
|
|
286
448
|
};
|
|
287
449
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
450
|
}
|
|
291
|
-
|
package/src/solid-core.module.ts
CHANGED
|
@@ -26,7 +26,7 @@ import { ModuleMetadata } from './entities/module-metadata.entity';
|
|
|
26
26
|
import { CommandService } from './helpers/command.service';
|
|
27
27
|
import { SchematicService } from './helpers/schematic.service';
|
|
28
28
|
import { ListOfValuesSelectionProvider } from './services/selection-providers/list-of-values-selection-providers.service';
|
|
29
|
-
import { PseudoForeignKeySelectionProvider } from './services/selection-providers/pseudo-foreign-key-selection-provider.service'
|
|
29
|
+
import { PseudoForeignKeySelectionProvider } from './services/selection-providers/pseudo-foreign-key-selection-provider.service';
|
|
30
30
|
import { ModuleMetadataSeederService } from './seeders/module-metadata-seeder.service';
|
|
31
31
|
import { ModuleTestDataService } from './seeders/module-test-data.service';
|
|
32
32
|
import { CrudHelperService } from './services/crud-helper.service';
|
|
@@ -55,6 +55,11 @@ import { ActionMetadataController } from './controllers/action-metadata.controll
|
|
|
55
55
|
import { ActionMetadata } from './entities/action-metadata.entity';
|
|
56
56
|
import { ActionMetadataService } from './services/action-metadata.service';
|
|
57
57
|
|
|
58
|
+
import { FacebookAuthenticationController } from './controllers/facebook-authentication.controller';
|
|
59
|
+
import { MicrosoftAuthenticationController } from './controllers/microsoft-authentication.controller';
|
|
60
|
+
import { FacebookOAuthStrategy } from './passport-strategies/facebook-oauth.strategy';
|
|
61
|
+
import { MicrosoftOAuthStrategy } from './passport-strategies/microsoft-oauth.strategy';
|
|
62
|
+
|
|
58
63
|
import { HttpModule } from '@nestjs/axios';
|
|
59
64
|
import { JwtModule } from '@nestjs/jwt';
|
|
60
65
|
import { SeedCommand } from './commands/seed.command';
|
|
@@ -133,7 +138,14 @@ import { BcryptService } from './services/bcrypt.service';
|
|
|
133
138
|
import { UuidExternalIdEntityComputedFieldProvider } from './services/computed-fields/entity/uuid-externalid-entity-computed-field-provider.service';
|
|
134
139
|
import { UuidExternalIdComputedFieldProvider } from './services/computed-fields/uuid-external-id-computed-field-provider.service';
|
|
135
140
|
import { EmailTemplateService } from './services/email-template.service';
|
|
136
|
-
import {
|
|
141
|
+
import {
|
|
142
|
+
DiskFileService,
|
|
143
|
+
S3FileService,
|
|
144
|
+
FileServiceFactory,
|
|
145
|
+
DiskStoragePathBuilder,
|
|
146
|
+
S3StoragePathBuilder,
|
|
147
|
+
StoragePathBuilderFactory,
|
|
148
|
+
} from './services/file';
|
|
137
149
|
import { HashingService } from './services/hashing.service';
|
|
138
150
|
import { ElasticEmailService } from './services/mail/elastic-email.service';
|
|
139
151
|
import { SMTPEMailService } from './services/mail/smtp-email.service';
|
|
@@ -229,7 +241,6 @@ import { SmtpEmailQueueSubscriberDatabase } from './jobs/database/smtp-email-sub
|
|
|
229
241
|
import { TwilioSmsQueuePublisherDatabase } from './jobs/database/twilio-sms-publisher-database.service';
|
|
230
242
|
import { TwilioSmsQueueSubscriberDatabase } from './jobs/database/twilio-sms-subscriber-database.service';
|
|
231
243
|
|
|
232
|
-
|
|
233
244
|
// import { ThrottlerModule } from '@nestjs/throttler';
|
|
234
245
|
import { IngestCommand } from './commands/ingest.command';
|
|
235
246
|
import { MailFactory } from './factories/mail.factory';
|
|
@@ -380,7 +391,6 @@ import { InfoCommand } from './commands/info.command';
|
|
|
380
391
|
import { ListOfRolesSelectionProvider } from './services/selection-providers/list-of-roles-selectionproviders.service';
|
|
381
392
|
import { Entity } from 'typeorm';
|
|
382
393
|
|
|
383
|
-
|
|
384
394
|
@Global()
|
|
385
395
|
@Module({
|
|
386
396
|
imports: [
|
|
@@ -442,12 +452,12 @@ import { Entity } from 'typeorm';
|
|
|
442
452
|
// you can also expose CORS here (not needed for simple <img>):
|
|
443
453
|
// res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
|
|
444
454
|
},
|
|
445
|
-
}
|
|
455
|
+
},
|
|
446
456
|
}),
|
|
447
457
|
MulterModule.registerAsync({
|
|
448
458
|
imports: [ConfigModule],
|
|
449
459
|
useFactory: async (configService: ConfigService) => ({
|
|
450
|
-
dest: process.env.AB_MEDIA_UPLOAD_DIR ??
|
|
460
|
+
dest: process.env.AB_MEDIA_UPLOAD_DIR ?? 'media-uploads',
|
|
451
461
|
}),
|
|
452
462
|
inject: [ConfigService],
|
|
453
463
|
}),
|
|
@@ -474,6 +484,8 @@ import { Entity } from 'typeorm';
|
|
|
474
484
|
ExportTransactionController,
|
|
475
485
|
FieldMetadataController,
|
|
476
486
|
GoogleAuthenticationController,
|
|
487
|
+
FacebookAuthenticationController,
|
|
488
|
+
MicrosoftAuthenticationController,
|
|
477
489
|
ImportTransactionController,
|
|
478
490
|
ImportTransactionErrorLogController,
|
|
479
491
|
ListOfValuesController,
|
|
@@ -524,7 +536,7 @@ import { Entity } from 'typeorm';
|
|
|
524
536
|
},
|
|
525
537
|
{
|
|
526
538
|
provide: APP_FILTER,
|
|
527
|
-
useClass: HttpExceptionFilter
|
|
539
|
+
useClass: HttpExceptionFilter,
|
|
528
540
|
},
|
|
529
541
|
ModuleMetadataService,
|
|
530
542
|
ModuleMetadataHelperService,
|
|
@@ -640,6 +652,8 @@ import { Entity } from 'typeorm';
|
|
|
640
652
|
RefreshTokenIdsStorageService,
|
|
641
653
|
SsoCodeStorageService,
|
|
642
654
|
GoogleOauthStrategy,
|
|
655
|
+
FacebookOAuthStrategy,
|
|
656
|
+
MicrosoftOAuthStrategy,
|
|
643
657
|
UserRegistrationListener,
|
|
644
658
|
TestQueuePublisher,
|
|
645
659
|
TestQueueSubscriber,
|
|
@@ -873,7 +887,10 @@ import { Entity } from 'typeorm';
|
|
|
873
887
|
export class SolidCoreModule implements NestModule {
|
|
874
888
|
configure(consumer: MiddlewareConsumer) {
|
|
875
889
|
consumer
|
|
876
|
-
.apply(
|
|
890
|
+
.apply(
|
|
891
|
+
express.json({ limit: '10mb' }),
|
|
892
|
+
express.urlencoded({ limit: '10mb', extended: true }),
|
|
893
|
+
)
|
|
877
894
|
.forRoutes('*');
|
|
878
895
|
}
|
|
879
896
|
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
Hi Ozzy,
|
|
2
|
-
Can you give me instructions to create a new model in the fees portal module, you can call it address-master.
|
|
3
|
-
This model needs to have the following fields.
|
|
4
|
-
1. address1 - shortText
|
|
5
|
-
2. address2 - shortText
|
|
6
|
-
3. addressType - selectionStatic with values - home, office & other.
|
|
7
|
-
4. city - many2one with the city model
|
|
8
|
-
5. state - many2one with the state model
|
|
9
|
-
6. pincode - many2one with the state model.
|
|
10
|
-
|
|
11
|
-
After I add this model I want to start storing student address.
|
|
12
|
-
|
|
13
|
-
To do this if you can also give me instructions on how to add a relation field to the student model, you can call this field studentAddress.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Can you now create a new computed field provider.
|
|
21
|
-
- You can call this provider: StateTotalCitiesComputedFieldProvider
|
|
22
|
-
- This will be a post computation provider and will depend on the city model being inserted, deleted, updated.
|
|
23
|
-
- The implementation simply needs to take a count of cities that belong to the same state as the city being mutated and update the state totalCities field.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Can you now create a new computed field provider.
|
|
27
|
-
- You can call this provider: StateTotalPopulationComputedFieldProvider
|
|
28
|
-
- This will be a post computation provider and will depend on the city model being inserted, deleted, updated.
|
|
29
|
-
- The implementation simply needs to take a sum of population of each city that belong to the same state as the city being mutated and update the state totalPopulation field.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
Can you now create a new computed field provider.
|
|
33
|
-
- You can call this provider: StateTotalGdpComputedFieldProvider
|
|
34
|
-
- This will be a post computation provider and will depend on the city model being inserted, deleted, updated.
|
|
35
|
-
- The implementation simply needs to take a sum of gdp of each city that belong to the same state as the city being mutated and update the state totalGdp field.
|
|
36
|
-
- I will add the totalGdp field to the state model after I have the computed provider TS code.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# Testing prompt sequence
|
|
40
|
-
|
|
41
|
-
## Create Module
|
|
42
|
-
Can you create a new module called address-master. This will be used to store address master data.
|
|
43
|
-
|
|
44
|
-
## Add Model - Country
|
|
45
|
-
Can you add a new model to the address-master module called country.
|
|
46
|
-
This will have name, description (richText), countryCode. You can assume name & countryCode to be unique. But only name will be used as a userkey.
|
|
47
|
-
Also enable audit tracking on the model and all its fields.
|
|
48
|
-
Make sure the table name is properly prefixed with the module name snake case.
|
|
49
|
-
|
|
50
|
-
## Add Model - Language
|
|
51
|
-
Can you add a new model to the address-master module called language.
|
|
52
|
-
This will have language, languageIsoCode. You can assume language to be unique.
|
|
53
|
-
Also for the languageIsoCode, can you create a field with type staticSelection add a bunch (20 odd, include at-least 7-8 indian languages also) of commonly spoken languages with their respective language codes as values.
|
|
54
|
-
Also enable audit tracking on the model and all its fields.
|
|
55
|
-
Make sure the table name is properly prefixed with the module name snake case.
|
|
56
|
-
|
|
57
|
-
## Add Model - Country Language
|
|
58
|
-
|
|
59
|
-
Can you now add a new model called CountrySpokenLanguages, this model will have 2 many-to-one fields.
|
|
60
|
-
1. country - many-to-one with the country model.
|
|
61
|
-
2. spokenLanguage - many-to-one with the language model.
|
|
62
|
-
3. spokenBy - int field storing data representing how many people speak that language.
|
|
63
|
-
Also enable audit tracking on the model and all its fields.
|
|
64
|
-
Make sure the table name is properly prefixed with the module name snake case.
|
|
65
|
-
|
|
66
|
-
## Add Model - Country Population Trend
|
|
67
|
-
Can you add a model called CountryPopulationTrend, this model has the following fields.
|
|
68
|
-
1. country - many-to-one with the country model.
|
|
69
|
-
2. entryDate - date field.
|
|
70
|
-
3. populationAsOnDate - int field storing the population of that country as on that date.
|