@@ -10,6 +10,12 @@ import { emit, subscribe } from '@nextcloud/event-bus'
1010
1111const browserStorage = getBuilder ( 'public' ) . persist ( ) . build ( )
1212
13+ /**
14+ * Client-side guest user implementation for public pages.
15+ *
16+ * Persists a generated guest UID and nickname in browser storage and
17+ * emits updates when the guest display name changes.
18+ */
1319class GuestUser implements NextcloudUser {
1420 private _displayName : string | null
1521 readonly uid : string
@@ -44,7 +50,7 @@ class GuestUser implements NextcloudUser {
4450let currentUser : NextcloudUser | undefined
4551
4652/**
47- * Get the currently Guest user or null if not logged in
53+ * Get the current guest user for public pages.
4854 */
4955export function getGuestUser ( ) : NextcloudUser {
5056 if ( ! currentUser ) {
@@ -55,14 +61,14 @@ export function getGuestUser(): NextcloudUser {
5561}
5662
5763/**
58- * Get the guest nickname for public pages
64+ * Get the guest nickname for public pages.
5965 */
6066export function getGuestNickname ( ) : string | null {
61- return getGuestUser ( ) ? .displayName || null
67+ return getGuestUser ( ) . displayName || null
6268}
6369
6470/**
65- * Set the guest nickname for public pages
71+ * Set the guest nickname for public pages.
6672 *
6773 * @param nickname - The nickname to set
6874 */
@@ -86,19 +92,41 @@ export function resetGuestUser(): void {
8692}
8793
8894/**
89- * Generate a random UUID (version 4) if the crypto API is not available.
90- * If the crypto API is available, it uses the less secure `randomUUID` method.
91- * Crypto API is available in modern browsers on secure contexts (HTTPS).
95+ * Generate a UUID v4 for identifying a guest user.
9296 *
93- * @return A random UUID.
97+ * Uses `crypto.randomUUID()` when available, falls back to
98+ * `crypto.getRandomValues()`, and finally to a non-cryptographic
99+ * `Math.random()` implementation when needed.
100+ *
101+ * @return A UUID string.
94102 */
95103function randomUUID ( ) : string {
96- // Use the crypto API if available
104+ // Use the native crypto API when available.
97105 if ( globalThis . crypto ?. randomUUID ) {
98106 return globalThis . crypto . randomUUID ( )
99107 }
100108
101- // Generate a random UUID (version 4)
109+ // Fall back to generating a UUID v4 from random bytes.
110+ if ( globalThis . crypto ?. getRandomValues ) {
111+ const bytes = new Uint8Array ( 16 )
112+ globalThis . crypto . getRandomValues ( bytes )
113+
114+ // Set the UUID version (4) and variant bits.
115+ bytes [ 6 ] = ( bytes [ 6 ] & 0x0f ) | 0x40
116+ bytes [ 8 ] = ( bytes [ 8 ] & 0x3f ) | 0x80
117+
118+ const hex = Array . from ( bytes , ( byte ) => byte . toString ( 16 ) . padStart ( 2 , '0' ) )
119+
120+ return [
121+ hex . slice ( 0 , 4 ) . join ( '' ) ,
122+ hex . slice ( 4 , 6 ) . join ( '' ) ,
123+ hex . slice ( 6 , 8 ) . join ( '' ) ,
124+ hex . slice ( 8 , 10 ) . join ( '' ) ,
125+ hex . slice ( 10 , 16 ) . join ( '' ) ,
126+ ] . join ( '-' )
127+ }
128+
129+ // Final fallback for environments without the crypto API.
102130 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' . replace ( / [ x y ] / g, ( c ) => {
103131 const r = Math . random ( ) * 16 | 0
104132 const v = c === 'x' ? r : ( r & 0x3 | 0x8 )
0 commit comments