aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_sharing/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_sharing/src/utils')
-rw-r--r--apps/files_sharing/src/utils/AccountIcon.spec.ts40
-rw-r--r--apps/files_sharing/src/utils/AccountIcon.ts28
-rw-r--r--apps/files_sharing/src/utils/GeneratePassword.js44
-rw-r--r--apps/files_sharing/src/utils/GeneratePassword.ts66
-rw-r--r--apps/files_sharing/src/utils/NodeShareUtils.ts10
-rw-r--r--apps/files_sharing/src/utils/SharedWithMe.js8
6 files changed, 143 insertions, 53 deletions
diff --git a/apps/files_sharing/src/utils/AccountIcon.spec.ts b/apps/files_sharing/src/utils/AccountIcon.spec.ts
new file mode 100644
index 00000000000..bbc7f031774
--- /dev/null
+++ b/apps/files_sharing/src/utils/AccountIcon.spec.ts
@@ -0,0 +1,40 @@
+/*!
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+import { describe, expect, it, afterEach } from 'vitest'
+import { generateAvatarSvg } from './AccountIcon'
+describe('AccountIcon', () => {
+
+ afterEach(() => {
+ delete document.body.dataset.themes
+ })
+
+ it('should generate regular account avatar svg', () => {
+ const svg = generateAvatarSvg('admin')
+ expect(svg).toContain('/avatar/admin/32')
+ expect(svg).not.toContain('dark')
+ expect(svg).toContain('?guestFallback=true')
+ })
+
+ it('should generate guest account avatar svg', () => {
+ const svg = generateAvatarSvg('admin', true)
+ expect(svg).toContain('/avatar/guest/admin/32')
+ expect(svg).not.toContain('dark')
+ expect(svg).not.toContain('?guestFallback=true')
+ })
+
+ it('should generate dark mode account avatar svg', () => {
+ document.body.dataset.themes = 'dark'
+ const svg = generateAvatarSvg('admin')
+ expect(svg).toContain('/avatar/admin/32/dark')
+ expect(svg).toContain('?guestFallback=true')
+ })
+
+ it('should generate dark mode guest account avatar svg', () => {
+ document.body.dataset.themes = 'dark'
+ const svg = generateAvatarSvg('admin', true)
+ expect(svg).toContain('/avatar/guest/admin/32/dark')
+ expect(svg).not.toContain('?guestFallback=true')
+ })
+})
diff --git a/apps/files_sharing/src/utils/AccountIcon.ts b/apps/files_sharing/src/utils/AccountIcon.ts
new file mode 100644
index 00000000000..21732f08f68
--- /dev/null
+++ b/apps/files_sharing/src/utils/AccountIcon.ts
@@ -0,0 +1,28 @@
+/*!
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+import { generateUrl } from '@nextcloud/router'
+
+const isDarkMode = () => {
+ return window?.matchMedia?.('(prefers-color-scheme: dark)')?.matches === true
+ || document.querySelector('[data-themes*=dark]') !== null
+}
+
+export const generateAvatarSvg = (userId: string, isGuest = false) => {
+ // normal avatar url: /avatar/{userId}/32?guestFallback=true
+ // dark avatar url: /avatar/{userId}/32/dark?guestFallback=true
+ // guest avatar url: /avatar/guest/{userId}/32
+ // guest dark avatar url: /avatar/guest/{userId}/32/dark
+ const basePath = isGuest ? `/avatar/guest/${userId}` : `/avatar/${userId}`
+ const darkModePath = isDarkMode() ? '/dark' : ''
+ const guestFallback = isGuest ? '' : '?guestFallback=true'
+
+ const url = `${basePath}/32${darkModePath}${guestFallback}`
+ const avatarUrl = generateUrl(url, { userId })
+
+ return `<svg width="32" height="32" viewBox="0 0 32 32"
+ xmlns="http://www.w3.org/2000/svg" class="sharing-status__avatar">
+ <image href="${avatarUrl}" height="32" width="32" />
+ </svg>`
+}
diff --git a/apps/files_sharing/src/utils/GeneratePassword.js b/apps/files_sharing/src/utils/GeneratePassword.js
deleted file mode 100644
index e40b12c53d1..00000000000
--- a/apps/files_sharing/src/utils/GeneratePassword.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-import axios from '@nextcloud/axios'
-import Config from '../services/ConfigService.js'
-import { showError, showSuccess } from '@nextcloud/dialogs'
-
-const config = new Config()
-// note: some chars removed on purpose to make them human friendly when read out
-const passwordSet = 'abcdefgijkmnopqrstwxyzABCDEFGHJKLMNPQRSTWXYZ23456789'
-
-/**
- * Generate a valid policy password or
- * request a valid password if password_policy
- * is enabled
- *
- * @return {string} a valid password
- */
-export default async function() {
- // password policy is enabled, let's request a pass
- if (config.passwordPolicy.api && config.passwordPolicy.api.generate) {
- try {
- const request = await axios.get(config.passwordPolicy.api.generate)
- if (request.data.ocs.data.password) {
- showSuccess(t('files_sharing', 'Password created successfully'))
- return request.data.ocs.data.password
- }
- } catch (error) {
- console.info('Error generating password from password_policy', error)
- showError(t('files_sharing', 'Error generating password from password policy'))
- }
- }
-
- const array = new Uint8Array(10)
- const ratio = passwordSet.length / 255
- self.crypto.getRandomValues(array)
- let password = ''
- for (let i = 0; i < array.length; i++) {
- password += passwordSet.charAt(array[i] * ratio)
- }
- return password
-}
diff --git a/apps/files_sharing/src/utils/GeneratePassword.ts b/apps/files_sharing/src/utils/GeneratePassword.ts
new file mode 100644
index 00000000000..82efaaa69d4
--- /dev/null
+++ b/apps/files_sharing/src/utils/GeneratePassword.ts
@@ -0,0 +1,66 @@
+/**
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import axios from '@nextcloud/axios'
+import Config from '../services/ConfigService.ts'
+import { showError, showSuccess } from '@nextcloud/dialogs'
+import { translate as t } from '@nextcloud/l10n'
+
+const config = new Config()
+// note: some chars removed on purpose to make them human friendly when read out
+const passwordSet = 'abcdefgijkmnopqrstwxyzABCDEFGHJKLMNPQRSTWXYZ23456789'
+
+/**
+ * Generate a valid policy password or request a valid password if password_policy is enabled
+ *
+ * @param {boolean} verbose If enabled the the status is shown to the user via toast
+ */
+export default async function(verbose = false): Promise<string> {
+ // password policy is enabled, let's request a pass
+ if (config.passwordPolicy.api && config.passwordPolicy.api.generate) {
+ try {
+ const request = await axios.get(config.passwordPolicy.api.generate)
+ if (request.data.ocs.data.password) {
+ if (verbose) {
+ showSuccess(t('files_sharing', 'Password created successfully'))
+ }
+ return request.data.ocs.data.password
+ }
+ } catch (error) {
+ console.info('Error generating password from password_policy', error)
+ if (verbose) {
+ showError(t('files_sharing', 'Error generating password from password policy'))
+ }
+ }
+ }
+
+ const array = new Uint8Array(10)
+ const ratio = passwordSet.length / 255
+ getRandomValues(array)
+ let password = ''
+ for (let i = 0; i < array.length; i++) {
+ password += passwordSet.charAt(array[i] * ratio)
+ }
+ return password
+}
+
+/**
+ * Fills the given array with cryptographically secure random values.
+ * If the crypto API is not available, it falls back to less secure Math.random().
+ * Crypto API is available in modern browsers on secure contexts (HTTPS).
+ *
+ * @param {Uint8Array} array - The array to fill with random values.
+ */
+function getRandomValues(array: Uint8Array): void {
+ if (self?.crypto?.getRandomValues) {
+ self.crypto.getRandomValues(array)
+ return
+ }
+
+ let len = array.length
+ while (len--) {
+ array[len] = Math.floor(Math.random() * 256)
+ }
+}
diff --git a/apps/files_sharing/src/utils/NodeShareUtils.ts b/apps/files_sharing/src/utils/NodeShareUtils.ts
index 7c51e3add69..f14f981e2ad 100644
--- a/apps/files_sharing/src/utils/NodeShareUtils.ts
+++ b/apps/files_sharing/src/utils/NodeShareUtils.ts
@@ -5,7 +5,7 @@
import { getCurrentUser } from '@nextcloud/auth'
import type { Node } from '@nextcloud/files'
-import { Type } from '@nextcloud/sharing'
+import { ShareType } from '@nextcloud/sharing'
type Share = {
/** The recipient display name */
@@ -13,7 +13,7 @@ type Share = {
/** The recipient user id */
id: string
/** The share type */
- type: Type
+ type: ShareType
}
const getSharesAttribute = function(node: Node) {
@@ -31,10 +31,10 @@ export const isNodeSharedWithMe = function(node: Node) {
return shares.length > 0 && (
// If some shares are shared with you as a direct user share
- shares.some(share => share.id === uid && share.type === Type.SHARE_TYPE_USER)
+ shares.some(share => share.id === uid && share.type === ShareType.User)
// Or of the file is shared with a group you're in
// (if it's returned by the backend, we assume you're in it)
- || shares.some(share => share.type === Type.SHARE_TYPE_GROUP)
+ || shares.some(share => share.type === ShareType.Group)
)
}
@@ -49,7 +49,7 @@ export const isNodeSharedWithOthers = function(node: Node) {
return shares.length > 0
// If some shares are shared with you as a direct user share
- && shares.some(share => share.id !== uid && share.type !== Type.SHARE_TYPE_GROUP)
+ && shares.some(share => share.id !== uid && share.type !== ShareType.Group)
}
export const isNodeShared = function(node: Node) {
diff --git a/apps/files_sharing/src/utils/SharedWithMe.js b/apps/files_sharing/src/utils/SharedWithMe.js
index 0b76e925ec9..2f63932bfbe 100644
--- a/apps/files_sharing/src/utils/SharedWithMe.js
+++ b/apps/files_sharing/src/utils/SharedWithMe.js
@@ -3,10 +3,10 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { Type as ShareTypes } from '@nextcloud/sharing'
+import { ShareType } from '@nextcloud/sharing'
const shareWithTitle = function(share) {
- if (share.type === ShareTypes.SHARE_TYPE_GROUP) {
+ if (share.type === ShareType.Group) {
return t(
'files_sharing',
'Shared with you and the group {group} by {owner}',
@@ -17,7 +17,7 @@ const shareWithTitle = function(share) {
undefined,
{ escape: false },
)
- } else if (share.type === ShareTypes.SHARE_TYPE_CIRCLE) {
+ } else if (share.type === ShareType.Team) {
return t(
'files_sharing',
'Shared with you and {circle} by {owner}',
@@ -28,7 +28,7 @@ const shareWithTitle = function(share) {
undefined,
{ escape: false },
)
- } else if (share.type === ShareTypes.SHARE_TYPE_ROOM) {
+ } else if (share.type === ShareType.Room) {
if (share.shareWithDisplayName) {
return t(
'files_sharing',