@@ -50,6 +50,12 @@ const sanitizeBio = (value: unknown): string | null => {
5050 return bio . length <= 300 ? bio : bio . slice ( 0 , 300 ) ;
5151} ;
5252
53+ const sanitizeAccessRequestNote = ( value : unknown ) : string | null => {
54+ if ( typeof value !== "string" ) return null ;
55+ const note = value . trim ( ) ;
56+ return note . length <= 1200 ? note : note . slice ( 0 , 1200 ) ;
57+ } ;
58+
5359const sanitizeAvatar = ( value : unknown ) : string | null => {
5460 if ( typeof value !== "string" ) return null ;
5561 const raw = value . trim ( ) ;
@@ -111,6 +117,7 @@ const ensureSchema = async (env: Env): Promise<void> => {
111117 username TEXT,
112118 email TEXT,
113119 bio TEXT,
120+ access_request_note TEXT,
114121 avatar_url TEXT,
115122 is_admin INTEGER NOT NULL DEFAULT 0,
116123 is_approved INTEGER NOT NULL DEFAULT 0,
@@ -198,6 +205,7 @@ const ensureSchema = async (env: Env): Promise<void> => {
198205 ! userNames . has ( "username" ) ? "ALTER TABLE users ADD COLUMN username TEXT" : "" ,
199206 ! userNames . has ( "email" ) ? "ALTER TABLE users ADD COLUMN email TEXT" : "" ,
200207 ! userNames . has ( "bio" ) ? "ALTER TABLE users ADD COLUMN bio TEXT" : "" ,
208+ ! userNames . has ( "access_request_note" ) ? "ALTER TABLE users ADD COLUMN access_request_note TEXT" : "" ,
201209 ! userNames . has ( "avatar_url" ) ? "ALTER TABLE users ADD COLUMN avatar_url TEXT" : "" ,
202210 ! userNames . has ( "is_admin" ) ? "ALTER TABLE users ADD COLUMN is_admin INTEGER NOT NULL DEFAULT 0" : "" ,
203211 ! userNames . has ( "is_approved" ) ? "ALTER TABLE users ADD COLUMN is_approved INTEGER NOT NULL DEFAULT 0" : "" ,
@@ -239,6 +247,7 @@ type UserRow = {
239247 username : string | null ;
240248 email : string | null ;
241249 bio : string | null ;
250+ access_request_note : string | null ;
242251 avatar_url : string | null ;
243252 is_admin : number ;
244253 is_approved : number ;
@@ -253,6 +262,7 @@ const toUserProfile = (row: UserRow) => ({
253262 username : sanitizeName ( row . username ) ?? "User" ,
254263 email : sanitizeEmail ( row . email ) ?? "unknown@users.linksim.local" ,
255264 bio : row . bio ?? "" ,
265+ accessRequestNote : row . access_request_note ?? "" ,
256266 avatarUrl : row . avatar_url ?? "" ,
257267 isAdmin : row . is_admin === 1 ,
258268 isApproved : row . is_approved === 1 ,
@@ -266,7 +276,7 @@ const readUserRow = async (env: Env, userId: string): Promise<UserRow | null> =>
266276 await ensureSchema ( env ) ;
267277 return env . DB
268278 . prepare (
269- "SELECT id, username, email, bio, avatar_url, is_admin, is_approved, approved_at, approved_by_user_id, created_at, updated_at FROM users WHERE id = ?" ,
279+ "SELECT id, username, email, bio, access_request_note, avatar_url, is_admin, is_approved, approved_at, approved_by_user_id, created_at, updated_at FROM users WHERE id = ?" ,
270280 )
271281 . bind ( userId )
272282 . first < UserRow > ( ) ;
@@ -278,7 +288,7 @@ const reconcileUserIdentityByEmail = async (env: Env, userId: string, email: str
278288
279289 const existing = await env . DB
280290 . prepare (
281- `SELECT id, username, email, bio, avatar_url, is_admin, is_approved, approved_at, approved_by_user_id, created_at, updated_at
291+ `SELECT id, username, email, bio, access_request_note, avatar_url, is_admin, is_approved, approved_at, approved_by_user_id, created_at, updated_at
282292 FROM users
283293 WHERE lower(email) = lower(?) AND id <> ?
284294 ORDER BY is_admin DESC, is_approved DESC, created_at ASC
@@ -348,8 +358,8 @@ export const ensureUser = async (
348358
349359 await env . DB . prepare (
350360 `INSERT OR IGNORE INTO users
351- (id, username, email, bio, avatar_url, is_admin, is_approved, approved_at, approved_by_user_id, created_at, updated_at)
352- VALUES (?, ?, ?, '', '', ?, ?, ?, ?, ?, ?)` ,
361+ (id, username, email, bio, access_request_note, avatar_url, is_admin, is_approved, approved_at, approved_by_user_id, created_at, updated_at)
362+ VALUES (?, ?, ?, '', '', '', ?, ?, ?, ?, ?, ?)` ,
353363 )
354364 . bind (
355365 userId ,
@@ -409,14 +419,24 @@ export const assertUserAccess = async (env: Env, userId: string) => {
409419export const updateUserProfile = async (
410420 env : Env ,
411421 userId : string ,
412- patch : { username ?: unknown ; email ?: unknown ; bio ?: unknown ; avatarUrl ?: unknown } ,
422+ patch : {
423+ username ?: unknown ;
424+ email ?: unknown ;
425+ bio ?: unknown ;
426+ accessRequestNote ?: unknown ;
427+ avatarUrl ?: unknown ;
428+ } ,
413429) => {
414430 const existing = await readUserRow ( env , userId ) ;
415431 if ( ! existing ) throw new Error ( "User not found." ) ;
416432
417433 const nextName = patch . username === undefined ? sanitizeName ( existing . username ) : sanitizeName ( patch . username ) ;
418434 const nextEmail = patch . email === undefined ? sanitizeEmail ( existing . email ) : sanitizeEmail ( patch . email ) ;
419435 const nextBio = patch . bio === undefined ? existing . bio ?? "" : sanitizeBio ( patch . bio ) ?? "" ;
436+ const nextAccessRequestNote =
437+ patch . accessRequestNote === undefined
438+ ? existing . access_request_note ?? ""
439+ : sanitizeAccessRequestNote ( patch . accessRequestNote ) ?? "" ;
420440 const nextAvatar = patch . avatarUrl === undefined ? existing . avatar_url ?? "" : sanitizeAvatar ( patch . avatarUrl ) ;
421441
422442 if ( ! nextName ) throw new Error ( "Name is required (2-80 chars)." ) ;
@@ -425,10 +445,18 @@ export const updateUserProfile = async (
425445
426446 await env . DB . prepare (
427447 `UPDATE users
428- SET username = ?, email = ?, bio = ?, avatar_url = ?, updated_at = ?
448+ SET username = ?, email = ?, bio = ?, access_request_note = ?, avatar_url = ?, updated_at = ?
429449 WHERE id = ?` ,
430450 )
431- . bind ( nextName , nextEmail , nextBio , nextAvatar ?? "" , new Date ( ) . toISOString ( ) , userId )
451+ . bind (
452+ nextName ,
453+ nextEmail ,
454+ nextBio ,
455+ nextAccessRequestNote ,
456+ nextAvatar ?? "" ,
457+ new Date ( ) . toISOString ( ) ,
458+ userId ,
459+ )
432460 . run ( ) ;
433461
434462 const profile = await fetchUserProfile ( env , userId ) ;
@@ -440,7 +468,7 @@ export const listUsers = async (env: Env) => {
440468 await ensureSchema ( env ) ;
441469 const rows = await env . DB
442470 . prepare (
443- "SELECT id, username, email, bio, avatar_url, is_admin, is_approved, approved_at, approved_by_user_id, created_at, updated_at FROM users ORDER BY created_at DESC LIMIT 2000" ,
471+ "SELECT id, username, email, bio, access_request_note, avatar_url, is_admin, is_approved, approved_at, approved_by_user_id, created_at, updated_at FROM users ORDER BY created_at DESC LIMIT 2000" ,
444472 )
445473 . all < UserRow > ( ) ;
446474 return rows . results . map ( toUserProfile ) ;
0 commit comments