Skip to content

Commit ab6cb7a

Browse files
authored
Merge pull request #950 from joshtrichards/jtr/guestUUID
refactor: improve guest UUID generation and docs
2 parents d6f748c + 00b5eb3 commit ab6cb7a

1 file changed

Lines changed: 38 additions & 10 deletions

File tree

lib/guest.ts

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ import { emit, subscribe } from '@nextcloud/event-bus'
1010

1111
const 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+
*/
1319
class GuestUser implements NextcloudUser {
1420
private _displayName: string | null
1521
readonly uid: string
@@ -44,7 +50,7 @@ class GuestUser implements NextcloudUser {
4450
let 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
*/
4955
export 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
*/
6066
export 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
*/
95103
function 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(/[xy]/g, (c) => {
103131
const r = Math.random() * 16 | 0
104132
const v = c === 'x' ? r : (r & 0x3 | 0x8)

0 commit comments

Comments
 (0)