@@ -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 } ,
@@ -106,18 +107,45 @@ export const createUserLibrary = (queries: Queries) => {
106
107
{ retries, factor : 0 } // No need for exponential backoff
107
108
) ;
108
109
110
+ const updateUserById = async (
111
+ id : string ,
112
+ set : Partial < OmitAutoSetFields < CreateUser > > ,
113
+ jsonbMode ?: 'replace' | 'merge'
114
+ ) => {
115
+ const validPhoneNumber = conditional (
116
+ 'primaryPhone' in set &&
117
+ typeof set . primaryPhone === 'string' &&
118
+ getValidPhoneNumber ( set . primaryPhone )
119
+ ) ;
120
+
121
+ return updateUserByIdQuery (
122
+ id ,
123
+ { ...set , ...conditional ( validPhoneNumber && { primaryPhone : validPhoneNumber } ) } ,
124
+ jsonbMode
125
+ ) ;
126
+ } ;
127
+
109
128
const insertUser = async ( data : OmitAutoSetFields < CreateUser > , additionalRoleNames : string [ ] ) => {
110
129
const roleNames = deduplicate ( [ ...EnvSet . values . userDefaultRoleNames , ...additionalRoleNames ] ) ;
111
130
const roles = await findRolesByRoleNames ( roleNames ) ;
112
131
113
132
assertThat ( roles . length === roleNames . length , 'role.default_role_missing' ) ;
114
133
134
+ const validPhoneNumber = conditional (
135
+ 'primaryPhone' in data &&
136
+ typeof data . primaryPhone === 'string' &&
137
+ getValidPhoneNumber ( data . primaryPhone )
138
+ ) ;
139
+
115
140
return pool . transaction ( async ( connection ) => {
116
141
const insertUserQuery = buildInsertIntoWithPool ( connection ) ( Users , {
117
142
returning : true ,
118
143
} ) ;
119
144
120
- const user = await insertUserQuery ( data ) ;
145
+ const user = await insertUserQuery ( {
146
+ ...data ,
147
+ ...conditional ( validPhoneNumber && { primaryPhone : validPhoneNumber } ) ,
148
+ } ) ;
121
149
122
150
if ( roles . length > 0 ) {
123
151
const { insertUsersRoles } = createUsersRolesQueries ( connection ) ;
@@ -289,5 +317,6 @@ export const createUserLibrary = (queries: Queries) => {
289
317
addUserMfaVerification,
290
318
verifyUserPassword,
291
319
signOutUser,
320
+ updateUserById,
292
321
} ;
293
322
} ;
0 commit comments