@drax/identity-back 0.9.0 → 0.10.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/dist/config/IdentityConfig.js +1 -0
- package/dist/controllers/UserController.js +152 -5
- package/dist/factory/UserRegistryServiceFactory.js +24 -0
- package/dist/html/RegistrationCompleteHtml.js +51 -0
- package/dist/models/UserModel.js +6 -1
- package/dist/repository/mongo/UserApiKeyMongoRepository.js +2 -2
- package/dist/repository/mongo/UserMongoRepository.js +28 -0
- package/dist/repository/sqlite/UserSqliteRepository.js +44 -1
- package/dist/routes/UserRoutes.js +11 -6
- package/dist/services/UserEmailService.js +54 -0
- package/dist/services/UserService.js +97 -6
- package/package.json +7 -6
- package/src/config/IdentityConfig.ts +2 -0
- package/src/controllers/UserController.ts +190 -21
- package/src/html/RegistrationCompleteHtml.ts +52 -0
- package/src/interfaces/IUserRepository.ts +5 -0
- package/src/models/UserModel.ts +6 -1
- package/src/repository/mongo/UserApiKeyMongoRepository.ts +2 -2
- package/src/repository/mongo/UserMongoRepository.ts +32 -1
- package/src/repository/sqlite/UserSqliteRepository.ts +51 -1
- package/src/routes/UserRoutes.ts +16 -6
- package/src/services/UserEmailService.ts +78 -0
- package/src/services/UserService.ts +107 -12
- package/tsconfig.tsbuildinfo +1 -1
- package/types/config/IdentityConfig.d.ts +2 -1
- package/types/config/IdentityConfig.d.ts.map +1 -1
- package/types/controllers/UserController.d.ts +7 -2
- package/types/controllers/UserController.d.ts.map +1 -1
- package/types/factory/UserApiKeyServiceFactory.d.ts +1 -1
- package/types/factory/UserRegistryServiceFactory.d.ts +4 -0
- package/types/factory/UserRegistryServiceFactory.d.ts.map +1 -0
- package/types/html/RegistrationCompleteHtml.d.ts +3 -0
- package/types/html/RegistrationCompleteHtml.d.ts.map +1 -0
- package/types/interfaces/IUserRepository.d.ts +4 -0
- package/types/interfaces/IUserRepository.d.ts.map +1 -1
- package/types/models/UserModel.d.ts.map +1 -1
- package/types/repository/mongo/UserApiKeyMongoRepository.d.ts +2 -2
- package/types/repository/mongo/UserApiKeyMongoRepository.d.ts.map +1 -1
- package/types/repository/mongo/UserMongoRepository.d.ts +5 -0
- package/types/repository/mongo/UserMongoRepository.d.ts.map +1 -1
- package/types/repository/sqlite/UserApiKeySqliteRepository.d.ts +1 -1
- package/types/repository/sqlite/UserSqliteRepository.d.ts +5 -0
- package/types/repository/sqlite/UserSqliteRepository.d.ts.map +1 -1
- package/types/routes/UserRoutes.d.ts.map +1 -1
- package/types/services/UserEmailService.d.ts +7 -0
- package/types/services/UserEmailService.d.ts.map +1 -0
- package/types/services/UserService.d.ts +6 -0
- package/types/services/UserService.d.ts.map +1 -1
|
@@ -29,7 +29,11 @@ const tableFields: SqliteTableField[] = [
|
|
|
29
29
|
{name: "avatar", type: "TEXT", unique: false, primary: false},
|
|
30
30
|
{name: "origin", type: "TEXT", unique: false, primary: false},
|
|
31
31
|
{name: "createdAt", type: "TEXT", unique: false, primary: false},
|
|
32
|
-
{name: "updatedAt", type: "TEXT", unique: false, primary: false}
|
|
32
|
+
{name: "updatedAt", type: "TEXT", unique: false, primary: false},
|
|
33
|
+
{name: "emailVerified", type: "INTEGER", unique: false, primary: false},
|
|
34
|
+
{name: "phoneVerified", type: "INTEGER", unique: false, primary: false},
|
|
35
|
+
{name: "emailCode", type: "TEXT", unique: false, primary: false},
|
|
36
|
+
{name: "phoneCode", type: "TEXT", unique: false, primary: false},
|
|
33
37
|
]
|
|
34
38
|
|
|
35
39
|
class UserSqliteRepository implements IUserRepository {
|
|
@@ -95,6 +99,10 @@ class UserSqliteRepository implements IUserRepository {
|
|
|
95
99
|
|
|
96
100
|
}
|
|
97
101
|
|
|
102
|
+
async updatePartial(id: string, userData: IUserUpdate): Promise<IUser> {
|
|
103
|
+
return this.update(id, userData)
|
|
104
|
+
}
|
|
105
|
+
|
|
98
106
|
async update(id: string, userData: IUserUpdate): Promise<IUser> {
|
|
99
107
|
try {
|
|
100
108
|
if (!await this.findRoleById(userData.role)) {
|
|
@@ -108,7 +116,9 @@ class UserSqliteRepository implements IUserRepository {
|
|
|
108
116
|
const setClauses = Object.keys(userData)
|
|
109
117
|
.map(field => `${field} = @${field}`)
|
|
110
118
|
.join(', ');
|
|
119
|
+
|
|
111
120
|
userData.id = id
|
|
121
|
+
|
|
112
122
|
const stmt = this.db.prepare(`UPDATE users
|
|
113
123
|
SET ${setClauses}
|
|
114
124
|
WHERE id = @id `);
|
|
@@ -151,6 +161,16 @@ class UserSqliteRepository implements IUserRepository {
|
|
|
151
161
|
return user
|
|
152
162
|
}
|
|
153
163
|
|
|
164
|
+
async findByUsernameWithPassword(username: string): Promise<IUser> {
|
|
165
|
+
const user = this.db.prepare('SELECT * FROM users WHERE username = ?').get(username);
|
|
166
|
+
if (!user) {
|
|
167
|
+
return null
|
|
168
|
+
}
|
|
169
|
+
user.role = await this.findRoleById(user.role)
|
|
170
|
+
user.tenant = await this.findTenantById(user.tenant)
|
|
171
|
+
return user
|
|
172
|
+
}
|
|
173
|
+
|
|
154
174
|
async findByEmail(email: string): Promise<IUser> {
|
|
155
175
|
const user = this.db.prepare('SELECT * FROM users WHERE email = ?').get(email);
|
|
156
176
|
if (!user) {
|
|
@@ -161,6 +181,36 @@ class UserSqliteRepository implements IUserRepository {
|
|
|
161
181
|
return user
|
|
162
182
|
}
|
|
163
183
|
|
|
184
|
+
async findByEmailCode(code: string): Promise<IUser> {
|
|
185
|
+
const user = this.db.prepare('SELECT * FROM users WHERE emailVerifyCode = ? AND emailVerified = 0').get(code);
|
|
186
|
+
if (!user) {
|
|
187
|
+
return null
|
|
188
|
+
}
|
|
189
|
+
user.role = await this.findRoleById(user.role)
|
|
190
|
+
user.tenant = await this.findTenantById(user.tenant)
|
|
191
|
+
return user
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async findByRecoveryCode(code: string): Promise<IUser> {
|
|
195
|
+
const user = this.db.prepare('SELECT * FROM users WHERE recoveryCode = ? AND active = 1').get(code);
|
|
196
|
+
if (!user) {
|
|
197
|
+
return null
|
|
198
|
+
}
|
|
199
|
+
user.role = await this.findRoleById(user.role)
|
|
200
|
+
user.tenant = await this.findTenantById(user.tenant)
|
|
201
|
+
return user
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async findByPhoneCode(code: string): Promise<IUser> {
|
|
205
|
+
const user = this.db.prepare('SELECT * FROM users WHERE phoneCode = ? AND phoneVerified = 0').get(code);
|
|
206
|
+
if (!user) {
|
|
207
|
+
return null
|
|
208
|
+
}
|
|
209
|
+
user.role = await this.findRoleById(user.role)
|
|
210
|
+
user.tenant = await this.findTenantById(user.tenant)
|
|
211
|
+
return user
|
|
212
|
+
}
|
|
213
|
+
|
|
164
214
|
async paginate({
|
|
165
215
|
page= 1,
|
|
166
216
|
limit= 5,
|
package/src/routes/UserRoutes.ts
CHANGED
|
@@ -4,9 +4,9 @@ async function UserRoutes(fastify, options) {
|
|
|
4
4
|
|
|
5
5
|
const controller: UserController = new UserController()
|
|
6
6
|
|
|
7
|
-
fastify.post('/api/auth', (req,rep) => controller.auth(req,rep))
|
|
7
|
+
fastify.post('/api/auth/login', (req,rep) => controller.auth(req,rep))
|
|
8
8
|
|
|
9
|
-
fastify.get('/api/me', (req,rep) => controller.me(req,rep))
|
|
9
|
+
fastify.get('/api/auth/me', (req,rep) => controller.me(req,rep))
|
|
10
10
|
|
|
11
11
|
fastify.get('/api/users/search', (req,rep) => controller.search(req,rep) )
|
|
12
12
|
|
|
@@ -20,13 +20,23 @@ async function UserRoutes(fastify, options) {
|
|
|
20
20
|
|
|
21
21
|
fastify.delete('/api/users/:id', (req,rep) => controller.delete(req,rep))
|
|
22
22
|
|
|
23
|
-
fastify.post('/api/
|
|
23
|
+
fastify.post('/api/users/register', (req,rep) => controller.register(req,rep))
|
|
24
24
|
|
|
25
|
-
fastify.
|
|
25
|
+
fastify.get('/api/users/verify-email/:code', (req,rep) => controller.verifyEmail(req,rep))
|
|
26
26
|
|
|
27
|
-
fastify.
|
|
27
|
+
fastify.get('/api/users/verify-phone/:code', (req,rep) => controller.verifyPhone(req,rep))
|
|
28
28
|
|
|
29
|
-
fastify.
|
|
29
|
+
fastify.post('/api/users/password/change', (req,rep) => controller.changeMyPassword(req,rep))
|
|
30
|
+
|
|
31
|
+
fastify.post('/api/users/password/change/:id', (req,rep) => controller.changePassword(req,rep))
|
|
32
|
+
|
|
33
|
+
fastify.post('/api/users/password/recovery/request', (req,rep) => controller.passwordRecoveryRequest(req,rep))
|
|
34
|
+
|
|
35
|
+
fastify.post('/api/users/password/recovery/complete', (req,rep) => controller.recoveryPasswordComplete(req,rep))
|
|
36
|
+
|
|
37
|
+
fastify.post('/api/users/avatar', (req,rep) => controller.updateAvatar(req,rep))
|
|
38
|
+
|
|
39
|
+
fastify.get('/api/users/avatar/:filename', (req,rep) => controller.getAvatar(req,rep))
|
|
30
40
|
|
|
31
41
|
}
|
|
32
42
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {EmailTransportConfig, EmailLayoutServiceFactory, EmailTransportServiceFactory} from "@drax/email-back"
|
|
2
|
+
import {CommonConfig, DraxConfig} from "@drax/common-back";
|
|
3
|
+
import type {SendMailOptions} from "nodemailer";
|
|
4
|
+
|
|
5
|
+
class UserEmailService {
|
|
6
|
+
|
|
7
|
+
static async emailVerifyCode(emailCode: string, emailTo:string){
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
let emailLayout = EmailLayoutServiceFactory.instance
|
|
11
|
+
|
|
12
|
+
let baseurl = DraxConfig.getOrLoad(CommonConfig.BaseUrl)
|
|
13
|
+
|
|
14
|
+
let body = `
|
|
15
|
+
<h2 style="font-size: 22px; color: #333333; font-weight: 600; margin: 0 0 10px 0;">
|
|
16
|
+
Verificación de Email
|
|
17
|
+
</h2>
|
|
18
|
+
<p style="font-size: 16px; line-height: 1.6; color: #555555; margin: 0 0 15px 0;">
|
|
19
|
+
Para confirmar tu email, haz clic en el siguiente enlace:
|
|
20
|
+
</p>
|
|
21
|
+
<a href="${baseurl}/api/users/verify-email/${emailCode}" style="color: #333333; text-decoration: none; border: 1px solid #333333; padding: 10px 20px; text-align: center; text-decoration: none; display: inline-block;">Verificar Email</a>
|
|
22
|
+
`
|
|
23
|
+
|
|
24
|
+
const emailFrom = DraxConfig.getOrLoad(EmailTransportConfig.authUsername)
|
|
25
|
+
|
|
26
|
+
const emailOptions : SendMailOptions = {
|
|
27
|
+
subject: "Verificación de Email",
|
|
28
|
+
from: emailFrom,
|
|
29
|
+
to: emailTo,
|
|
30
|
+
html: emailLayout.html(body)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await EmailTransportServiceFactory.instance.sendEmail(emailOptions)
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
static async recoveryCode(recoveryCode: string, emailTo:string){
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
let emailLayout = EmailLayoutServiceFactory.instance
|
|
42
|
+
|
|
43
|
+
let baseurl = DraxConfig.getOrLoad(CommonConfig.BaseUrl)
|
|
44
|
+
|
|
45
|
+
let body = `
|
|
46
|
+
<h2 style="font-size: 22px; color: #333333; font-weight: 600; margin: 0 0 10px 0;">
|
|
47
|
+
Recuperación de Contraseña
|
|
48
|
+
</h2>
|
|
49
|
+
<p style="font-size: 16px; line-height: 1.6; color: #555555; margin: 0 0 15px 0;">
|
|
50
|
+
Accede al siguiente link para recuperar tu contraseña:
|
|
51
|
+
</p>
|
|
52
|
+
<p style="text-align: center; width: 100%;">
|
|
53
|
+
<a href="${baseurl}/password/recovery/complete/${recoveryCode}"
|
|
54
|
+
style="color: #333333; text-decoration: none; border: 1px solid #333333; padding: 10px 20px; text-align: center; text-decoration: none; display: inline-block;">
|
|
55
|
+
Recuperar Contraseña
|
|
56
|
+
</a>
|
|
57
|
+
</p>
|
|
58
|
+
|
|
59
|
+
`
|
|
60
|
+
|
|
61
|
+
const emailFrom = DraxConfig.getOrLoad(EmailTransportConfig.authUsername)
|
|
62
|
+
|
|
63
|
+
const emailOptions : SendMailOptions = {
|
|
64
|
+
subject: "Recuperación de Contraseña",
|
|
65
|
+
from: emailFrom,
|
|
66
|
+
to: emailTo,
|
|
67
|
+
html: emailLayout.html(body)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
await EmailTransportServiceFactory.instance.sendEmail(emailOptions)
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default UserEmailService
|
|
77
|
+
|
|
78
|
+
export {UserEmailService}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type {IUser, IUserCreate, IUserUpdate} from "@drax/identity-share";
|
|
2
2
|
import type {IUserRepository} from "../interfaces/IUserRepository";
|
|
3
|
+
|
|
3
4
|
import {ZodError} from "zod";
|
|
4
|
-
import {ValidationError, ZodErrorToValidationError} from "@drax/common-back";
|
|
5
|
+
import {SecuritySensitiveError, ValidationError, ZodErrorToValidationError} from "@drax/common-back";
|
|
5
6
|
import AuthUtils from "../utils/AuthUtils.js";
|
|
6
7
|
import {createUserSchema, editUserSchema, userBaseSchema} from "../zod/UserZod.js";
|
|
7
8
|
import BadCredentialsError from "../errors/BadCredentialsError.js";
|
|
@@ -9,12 +10,12 @@ import {IDraxPaginateOptions, IDraxPaginateResult} from "@drax/crud-share";
|
|
|
9
10
|
import {AbstractService} from "@drax/crud-back";
|
|
10
11
|
import {randomUUID} from "crypto"
|
|
11
12
|
|
|
12
|
-
class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate>{
|
|
13
|
+
class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate> {
|
|
13
14
|
|
|
14
15
|
_repository: IUserRepository
|
|
15
16
|
|
|
16
17
|
constructor(userRepository: IUserRepository) {
|
|
17
|
-
super(userRepository,userBaseSchema);
|
|
18
|
+
super(userRepository, userBaseSchema);
|
|
18
19
|
this._repository = userRepository;
|
|
19
20
|
console.log("UserService constructor")
|
|
20
21
|
}
|
|
@@ -22,7 +23,7 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate>{
|
|
|
22
23
|
async auth(username: string, password: string) {
|
|
23
24
|
let user = null
|
|
24
25
|
console.log("auth username", username)
|
|
25
|
-
user = await this.
|
|
26
|
+
user = await this.findByUsernameWithPassword(username)
|
|
26
27
|
if (user && user.active && AuthUtils.checkPassword(password, user.password)) {
|
|
27
28
|
//TODO: Generar session
|
|
28
29
|
const session = randomUUID()
|
|
@@ -38,7 +39,7 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate>{
|
|
|
38
39
|
console.log("auth email", email)
|
|
39
40
|
user = await this.findByEmail(email)
|
|
40
41
|
|
|
41
|
-
if(!user && createIfNotFound){
|
|
42
|
+
if (!user && createIfNotFound) {
|
|
42
43
|
userData.password = userData.password ? userData.password : randomUUID()
|
|
43
44
|
userData.active = userData.active === undefined ? true : userData.active
|
|
44
45
|
user = await this.create(userData)
|
|
@@ -49,10 +50,11 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate>{
|
|
|
49
50
|
const accessToken = AuthUtils.generateToken(user.id.toString(), user.username, user.role.id, user.tenant?.id, session)
|
|
50
51
|
return {accessToken: accessToken}
|
|
51
52
|
} else {
|
|
52
|
-
|
|
53
|
+
throw new BadCredentialsError()
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
|
|
56
58
|
async changeUserPassword(userId: string, newPassword: string) {
|
|
57
59
|
const user = await this.findById(userId)
|
|
58
60
|
if (user) {
|
|
@@ -68,7 +70,6 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate>{
|
|
|
68
70
|
async changeOwnPassword(userId: string, currentPassword: string, newPassword: string) {
|
|
69
71
|
const user = await this.findById(userId)
|
|
70
72
|
|
|
71
|
-
|
|
72
73
|
if (user && user.active) {
|
|
73
74
|
|
|
74
75
|
if (currentPassword === newPassword) {
|
|
@@ -98,12 +99,95 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate>{
|
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
async recoveryCode(email: string): Promise<string> {
|
|
103
|
+
try{
|
|
104
|
+
const recoveryCode = randomUUID()
|
|
105
|
+
const user = await this._repository.findByEmail(email)
|
|
106
|
+
if(user && user.active){
|
|
107
|
+
await this._repository.updatePartial(user.id, {recoveryCode: recoveryCode})
|
|
108
|
+
return recoveryCode
|
|
109
|
+
}else{
|
|
110
|
+
throw new SecuritySensitiveError()
|
|
111
|
+
}
|
|
112
|
+
}catch (e) {
|
|
113
|
+
console.error("recoveryCode:", e)
|
|
114
|
+
throw e
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async changeUserPasswordByCode(recoveryCode: string, newPassword: string): Promise<boolean> {
|
|
119
|
+
try {
|
|
120
|
+
console.log("changeUserPasswordByCode recoveryCode", recoveryCode)
|
|
121
|
+
const user = await this._repository.findByRecoveryCode(recoveryCode)
|
|
122
|
+
console.log("changeUserPasswordByCode user", user)
|
|
123
|
+
if (user && user.active) {
|
|
124
|
+
newPassword = AuthUtils.hashPassword(newPassword)
|
|
125
|
+
await this._repository.changePassword(user.id, newPassword)
|
|
126
|
+
await this._repository.updatePartial(user.id, {recoveryCode: null})
|
|
127
|
+
return true
|
|
128
|
+
} else {
|
|
129
|
+
throw new ValidationError([{field:'recoveryCode', reason: 'validation.notFound'}])
|
|
130
|
+
}
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.error("changeUserPasswordByCode", e)
|
|
133
|
+
throw e
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async register(userData: IUserCreate): Promise<IUser> {
|
|
138
|
+
try {
|
|
139
|
+
|
|
140
|
+
userData.emailVerified = false
|
|
141
|
+
userData.phoneVerified = false
|
|
142
|
+
userData.active = false
|
|
143
|
+
|
|
144
|
+
userData.emailCode = randomUUID()
|
|
145
|
+
userData.phoneCode = randomUUID()
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
let user = await this.create(userData)
|
|
149
|
+
|
|
150
|
+
return user
|
|
151
|
+
} catch (e) {
|
|
152
|
+
console.error("Error registry user", e)
|
|
153
|
+
if (e instanceof ZodError) {
|
|
154
|
+
throw ZodErrorToValidationError(e, userData)
|
|
155
|
+
}
|
|
156
|
+
throw e
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async verifyEmail(emailCode: string): Promise<boolean> {
|
|
161
|
+
const user = await this._repository.findByEmailCode(emailCode)
|
|
162
|
+
if (user && user.emailVerified === false) {
|
|
163
|
+
await this._repository.updatePartial(user.id, {
|
|
164
|
+
emailVerified: true,
|
|
165
|
+
active: true
|
|
166
|
+
})
|
|
167
|
+
return true
|
|
168
|
+
} else {
|
|
169
|
+
throw new ValidationError([{field: 'emailCode', reason: 'validation.notFound'}])
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async verifyPhone(phoneCode: string): Promise<boolean> {
|
|
174
|
+
const user = await this._repository.findByPhoneCode(phoneCode)
|
|
175
|
+
if (user && user.phoneVerified === false) {
|
|
176
|
+
await this._repository.updatePartial(user.id, {
|
|
177
|
+
phoneVerified: true,
|
|
178
|
+
active: true
|
|
179
|
+
})
|
|
180
|
+
return true
|
|
181
|
+
} else {
|
|
182
|
+
throw new ValidationError([{field: 'phoneCode', reason: 'validation.notFound'}])
|
|
183
|
+
}
|
|
184
|
+
}
|
|
101
185
|
|
|
102
186
|
async create(userData: IUserCreate): Promise<IUser> {
|
|
103
187
|
try {
|
|
104
188
|
userData.name = userData?.name?.trim()
|
|
105
|
-
userData.username = userData
|
|
106
|
-
userData.password = userData
|
|
189
|
+
userData.username = userData?.username.trim()
|
|
190
|
+
userData.password = userData?.password.trim()
|
|
107
191
|
userData.tenant = userData.tenant === "" ? null : userData.tenant
|
|
108
192
|
|
|
109
193
|
await createUserSchema.parseAsync(userData)
|
|
@@ -123,8 +207,8 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate>{
|
|
|
123
207
|
|
|
124
208
|
async update(id: string, userData: IUserUpdate) {
|
|
125
209
|
try {
|
|
126
|
-
userData.name = userData
|
|
127
|
-
userData.username = userData
|
|
210
|
+
userData.name = userData?.name.trim()
|
|
211
|
+
userData.username = userData?.username.trim()
|
|
128
212
|
delete userData.password
|
|
129
213
|
userData.tenant = userData.tenant === "" ? null : userData.tenant
|
|
130
214
|
|
|
@@ -145,7 +229,7 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate>{
|
|
|
145
229
|
async delete(id: string): Promise<boolean> {
|
|
146
230
|
try {
|
|
147
231
|
const result: boolean = await this._repository.delete(id);
|
|
148
|
-
if(!result){
|
|
232
|
+
if (!result) {
|
|
149
233
|
throw new Error("error.deletionFailed")
|
|
150
234
|
}
|
|
151
235
|
return result;
|
|
@@ -178,6 +262,17 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate>{
|
|
|
178
262
|
|
|
179
263
|
}
|
|
180
264
|
|
|
265
|
+
async findByUsernameWithPassword(username: string): Promise<IUser | null> {
|
|
266
|
+
try {
|
|
267
|
+
const user: IUser = await this._repository.findByUsernameWithPassword(username);
|
|
268
|
+
return user
|
|
269
|
+
} catch (e) {
|
|
270
|
+
console.error("Error finding user by username", e)
|
|
271
|
+
throw e
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
}
|
|
275
|
+
|
|
181
276
|
async findByEmail(email: string): Promise<IUser | null> {
|
|
182
277
|
try {
|
|
183
278
|
const user: IUser = await this._repository.findByEmail(email);
|