@@ -2,7 +2,7 @@ import type { User, CreateUser, Scope, BindMfa, MfaVerification } from '@logto/s
2
2
import { MfaFactor , Users , UsersPasswordEncryptionMethod } from '@logto/schemas' ;
3
3
import { generateStandardShortId , generateStandardId } from '@logto/shared' ;
4
4
import type { Nullable } from '@silverhand/essentials' ;
5
- import { deduplicate } from '@silverhand/essentials' ;
5
+ import { deduplicate , conditional } from '@silverhand/essentials' ;
6
6
import { argon2Verify , bcryptVerify , md5 , sha1 , sha256 } from 'hash-wasm' ;
7
7
import pRetry from 'p-retry' ;
8
8
@@ -14,6 +14,7 @@ import type Queries from '#src/tenants/Queries.js';
14
14
import assertThat from '#src/utils/assert-that.js' ;
15
15
import { encryptPassword } from '#src/utils/password.js' ;
16
16
import type { OmitAutoSetFields } from '#src/utils/sql.js' ;
17
+ import { getValidPhoneNumber } from '#src/utils/user.js' ;
17
18
18
19
export const encryptUserPassword = async (
19
20
password : string
@@ -82,7 +83,7 @@ export const createUserLibrary = (queries: Queries) => {
82
83
hasUserWithId,
83
84
hasUserWithPhone,
84
85
findUsersByIds,
85
- updateUserById,
86
+ updateUserById : updateUserByIdQuery ,
86
87
findUserById,
87
88
} ,
88
89
usersRoles : { findUsersRolesByRoleId, findUsersRolesByUserId } ,
@@ -105,18 +106,45 @@ export const createUserLibrary = (queries: Queries) => {
105
106
{ retries, factor : 0 } // No need for exponential backoff
106
107
) ;
107
108
109
+ const updateUserById = async (
110
+ id : string ,
111
+ set : Partial < OmitAutoSetFields < CreateUser > > ,
112
+ jsonbMode ?: 'replace' | 'merge'
113
+ ) => {
114
+ const validPhoneNumber = conditional (
115
+ 'primaryPhone' in set &&
116
+ typeof set . primaryPhone === 'string' &&
117
+ getValidPhoneNumber ( set . primaryPhone )
118
+ ) ;
119
+
120
+ return updateUserByIdQuery (
121
+ id ,
122
+ { ...set , ...conditional ( validPhoneNumber && { primaryPhone : validPhoneNumber } ) } ,
123
+ jsonbMode
124
+ ) ;
125
+ } ;
126
+
108
127
const insertUser = async ( data : OmitAutoSetFields < CreateUser > , additionalRoleNames : string [ ] ) => {
109
128
const roleNames = deduplicate ( [ ...EnvSet . values . userDefaultRoleNames , ...additionalRoleNames ] ) ;
110
129
const roles = await findRolesByRoleNames ( roleNames ) ;
111
130
112
131
assertThat ( roles . length === roleNames . length , 'role.default_role_missing' ) ;
113
132
133
+ const validPhoneNumber = conditional (
134
+ 'primaryPhone' in data &&
135
+ typeof data . primaryPhone === 'string' &&
136
+ getValidPhoneNumber ( data . primaryPhone )
137
+ ) ;
138
+
114
139
return pool . transaction ( async ( connection ) => {
115
140
const insertUserQuery = buildInsertIntoWithPool ( connection ) ( Users , {
116
141
returning : true ,
117
142
} ) ;
118
143
119
- const user = await insertUserQuery ( data ) ;
144
+ const user = await insertUserQuery ( {
145
+ ...data ,
146
+ ...conditional ( validPhoneNumber && { primaryPhone : validPhoneNumber } ) ,
147
+ } ) ;
120
148
121
149
if ( roles . length > 0 ) {
122
150
const { insertUsersRoles } = createUsersRolesQueries ( connection ) ;
@@ -279,5 +307,6 @@ export const createUserLibrary = (queries: Queries) => {
279
307
findUserRoles,
280
308
addUserMfaVerification,
281
309
verifyUserPassword,
310
+ updateUserById,
282
311
} ;
283
312
} ;
0 commit comments