Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: move link expiration rules to a helper method #10080

Merged
merged 2 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 10 additions & 37 deletions packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
<name-and-copy v-if="quicklink" :link="quicklink" />
<create-quick-link
v-else-if="canCreateLinks"
:expiration-date="expirationDate"
:expiration-rules="expirationRules"
@create-public-link="checkLinkToCreate"
/>
<details-and-edit
v-if="quicklink"
:available-role-options="getAvailableRoleOptions(quicklink)"
:can-rename="false"
:expiration-date="expirationDate"
:expiration-rules="expirationRules"
:is-folder-share="resource.isFolder"
:is-modifiable="canEditLink(quicklink)"
:is-password-enforced="isPasswordEnforcedFor(quicklink)"
Expand Down Expand Up @@ -54,7 +54,7 @@
<details-and-edit
:available-role-options="getAvailableRoleOptions(link)"
:can-rename="true"
:expiration-date="expirationDate"
:expiration-rules="expirationRules"
:is-folder-share="resource.isFolder"
:is-modifiable="canEditLink(link)"
:is-password-enforced="isPasswordEnforcedFor(link)"
Expand Down Expand Up @@ -89,7 +89,7 @@
<name-and-copy :link="link" />
<details-and-edit
:available-role-options="getAvailableRoleOptions(link)"
:expiration-date="expirationDate"
:expiration-rules="expirationRules"
:is-folder-share="true"
:is-modifiable="false"
:link="link"
Expand Down Expand Up @@ -124,7 +124,8 @@ import {
useCapabilityFilesSharingPublicPasswordEnforcedFor,
useAbility,
usePasswordPolicyService,
getDefaultLinkPermissions
getDefaultLinkPermissions,
useExpirationRules
} from '@ownclouders/web-pkg'
import { shareViaLinkHelp, shareViaIndirectLinkHelp } from '../../../helpers/contextualHelpers'
import {
Expand Down Expand Up @@ -162,6 +163,7 @@ export default defineComponent({
const store = useStore()
const ability = useAbility()
const { can } = ability
const { expirationRules } = useExpirationRules()
const passwordPolicyService = usePasswordPolicyService()
const hasResharing = useCapabilityFilesSharingResharing()

Expand Down Expand Up @@ -241,7 +243,8 @@ export default defineComponent({
configurationManager,
passwordPolicyService,
canCreateLinks,
canEditLink
canEditLink,
expirationRules
}
},
computed: {
Expand All @@ -264,36 +267,6 @@ export default defineComponent({
return this.outgoingLinks.find((link) => link.quicklink === true && !link.indirect)
},

expirationDate() {
const expireDate = this.capabilities.files_sharing.public.expire_date

let defaultExpireDate = null
let maxExpireDateFromCaps = null

if (expireDate.days) {
const days = parseInt(expireDate.days)
defaultExpireDate = DateTime.now()
.setLocale(getLocaleFromLanguage(this.$language.current))
.plus({ days })
.toJSDate()
}

if (expireDate.enforced) {
const days = parseInt(expireDate.days)
maxExpireDateFromCaps = DateTime.now()
.setLocale(getLocaleFromLanguage(this.$language.current))
.plus({ days })
.toJSDate()
}

return {
enforced: expireDate.enforced,
default: defaultExpireDate,
min: DateTime.now().setLocale(getLocaleFromLanguage(this.$language.current)).toJSDate(),
max: maxExpireDateFromCaps
}
},

helpersEnabled() {
return this.configuration?.options?.contextHelpers
},
Expand Down Expand Up @@ -415,7 +388,7 @@ export default defineComponent({
ability: this.ability,
store: this.$store
}).toString(),
expiration: this.expirationDate.default,
expiration: this.expirationRules.default,
password: false
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,20 @@
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { useAbility, getDefaultLinkPermissions, useStore } from '@ownclouders/web-pkg'
import { defineComponent, PropType } from 'vue'
import {
useAbility,
getDefaultLinkPermissions,
useStore,
ExpirationRules
} from '@ownclouders/web-pkg'
import { useGettext } from 'vue3-gettext'

export default defineComponent({
name: 'CreateQuickLink',
props: {
expirationDate: {
type: Object,
default: () => {},
expirationRules: {
type: Object as PropType<ExpirationRules>,
required: true
}
},
Expand All @@ -50,7 +54,7 @@ export default defineComponent({
link: {
name: $gettext('Link'),
permissions: getDefaultLinkPermissions({ ability, store }).toString(),
expiration: props.expirationDate.enforced ? props.expirationDate.default : null,
expiration: props.expirationRules.enforced ? props.expirationRules.default : null,
quicklink: true,
password: false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,10 @@
v-if="option.showDatepicker"
v-model="newExpiration"
class="link-expiry-picker oc-flex oc-width-1-1"
:min-date="expirationDate.min"
:max-date="expirationDate.max"
:min-date="expirationRules.min"
:max-date="expirationRules.max"
:locale="$language.current"
:is-required="expirationDate.enforce"
:is-required="expirationRules.enforced"
>
<template #default="{ togglePopover }">
<oc-button
Expand Down Expand Up @@ -212,7 +212,7 @@ import { formatDateFromDateTime, formatRelativeDateFromDateTime } from '@ownclou
import { Resource, SpaceResource } from '@ownclouders/web-client/src/helpers'
import { createFileRouteOptions } from '@ownclouders/web-pkg'
import { OcDrop } from 'design-system/src/components'
import { usePasswordPolicyService } from '@ownclouders/web-pkg'
import { usePasswordPolicyService, ExpirationRules } from '@ownclouders/web-pkg'
import { useGettext } from 'vue3-gettext'

export default defineComponent({
Expand All @@ -226,9 +226,8 @@ export default defineComponent({
type: Boolean,
default: false
},
expirationDate: {
type: Object,
default: () => ({}),
expirationRules: {
type: Object as PropType<ExpirationRules>,
required: true
},
isFolderShare: {
Expand Down Expand Up @@ -316,7 +315,7 @@ export default defineComponent({
id: 'remove-expiration',
title: this.$gettext('Remove expiration date'),
icon: 'close',
isRemovable: !this.expirationDate.enforced,
isRemovable: !this.expirationRules.enforced,
method: () =>
this.updateLink({
link: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function getShallowMountedWrapper(link, expireDateEnforced = false, isModifiable
props: {
availableRoleOptions,
canRename: true,
expirationDate: {
expirationRules: {
enforced: expireDateEnforced,
default: null,
min: 'Wed Apr 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ exports[`DetailsAndEdit component if user can edit renders dropdown and edit but
</oc-button-stub>
</li>
<li class="oc-rounded oc-menu-item-hover">
<date-picker-stub class="oc-datepicker link-expiry-picker oc-flex oc-width-1-1 link-expiry-picker oc-flex oc-width-1-1" inputdebounce="1000" is24hr="false" isrange="false" locale="en" min-date="Wed Apr 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)" mode="date" modelconfig="[object Object]" popover="[object Object]" updateoninput="true">
<date-picker-stub class="oc-datepicker link-expiry-picker oc-flex oc-width-1-1 link-expiry-picker oc-flex oc-width-1-1" inputdebounce="1000" is24hr="false" isrange="false" isrequired="false" locale="en" min-date="Wed Apr 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)" mode="date" modelconfig="[object Object]" popover="[object Object]" updateoninput="true">
<!-- @slot Default slot to use as the popover anchor for datepicker -->
<!-- args is undefined during initial render, hence we check it here -->
<!--v-if-->
Expand Down
10 changes: 7 additions & 3 deletions packages/web-client/src/ocs/capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ export interface PasswordEnforcedForCapability {
read_write_delete?: boolean
}

export interface PublicExpirationCapability {
days?: string
enabled?: boolean
enforced?: boolean
}

export interface LastModifiedFilterCapability {
keywords?: string[]
enabled?: boolean
Expand Down Expand Up @@ -101,9 +107,7 @@ export interface Capabilities {
alias?: boolean
can_edit: boolean
enabled: boolean
expire_date: {
enabled: boolean
}
expire_date: PublicExpirationCapability
multiple: boolean
password: {
enforced: boolean
Expand Down
1 change: 1 addition & 0 deletions packages/web-pkg/src/composables/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export * from './fileListHeaderPosition'
export * from './filesList'
export * from './folderLink'
export * from './keyboardActions'
export * from './links'
export * from './loadingService'
export * from './localStorage'
export * from './pagination'
Expand Down
1 change: 1 addition & 0 deletions packages/web-pkg/src/composables/links/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useExpirationRules'
13 changes: 13 additions & 0 deletions packages/web-pkg/src/composables/links/useExpirationRules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { computed } from 'vue'
import { getExpirationRules } from '../../helpers'
import { useStore } from '../store'
import { useGettext } from 'vue3-gettext'

export const useExpirationRules = () => {
const store = useStore()
const { current: currentLanguage } = useGettext()

const expirationRules = computed(() => getExpirationRules({ store, currentLanguage }))

return { expirationRules }
}
41 changes: 41 additions & 0 deletions packages/web-pkg/src/helpers/share/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { Resource } from '@ownclouders/web-client'
import { Language } from 'vue3-gettext'
import { unref } from 'vue'
import { showQuickLinkPasswordModal } from '../../quickActions'
import { getLocaleFromLanguage } from '../locale'
import { PublicExpirationCapability } from '@ownclouders/web-client/src/ocs/capabilities'

export interface CreateQuicklink {
clientService: ClientService
Expand Down Expand Up @@ -181,3 +183,42 @@ export const getDefaultLinkPermissions = ({

return defaultPermissions
}

export type ExpirationRules = { enforced: boolean; default: DateTime; min: DateTime; max: DateTime }

export const getExpirationRules = ({
store,
currentLanguage
}: {
store: Store<any>
currentLanguage: string
}): ExpirationRules => {
const expireDate: PublicExpirationCapability =
store.getters.capabilities.files_sharing.public.expire_date

let defaultExpireDate: DateTime = null
let maxExpireDateFromCaps: DateTime = null

if (expireDate.days) {
const days = parseInt(expireDate.days)
defaultExpireDate = DateTime.now()
.setLocale(getLocaleFromLanguage(currentLanguage))
.plus({ days })
.toJSDate()
}

if (expireDate.enforced) {
const days = parseInt(expireDate.days)
maxExpireDateFromCaps = DateTime.now()
.setLocale(getLocaleFromLanguage(currentLanguage))
.plus({ days })
.toJSDate()
}

return {
enforced: expireDate.enforced,
default: defaultExpireDate,
min: DateTime.now().setLocale(getLocaleFromLanguage(currentLanguage)).toJSDate(),
max: maxExpireDateFromCaps
}
}
23 changes: 22 additions & 1 deletion packages/web-pkg/tests/unit/helpers/share/link.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {
copyQuicklink,
createQuicklink,
CreateQuicklink,
getDefaultLinkPermissions
getDefaultLinkPermissions,
getExpirationRules
} from '../../../../src/helpers/share'
import { DateTime } from 'luxon'
import { Store } from 'vuex'
Expand All @@ -13,6 +14,7 @@ import { mock, mockDeep } from 'jest-mock-extended'
import { Language } from 'vue3-gettext'
import { Resource } from '@ownclouders/web-client'
import { SharePermissionBit } from '@ownclouders/web-client/src/helpers'
import { PublicExpirationCapability } from '@ownclouders/web-client/src/ocs/capabilities'

jest.mock('@vueuse/core', () => ({
useClipboard: jest.fn().mockReturnValue({ copy: jest.fn() })
Expand Down Expand Up @@ -186,3 +188,22 @@ describe('getDefaultLinkPermissions', () => {
}
)
})

describe('getExpirationRules', () => {
it('correctly computes rules based on the "expire_date"-capability', () => {
jest.useFakeTimers().setSystemTime(new Date('2000-01-01'))

const capabilities = mock<PublicExpirationCapability>({ enforced: true, days: '10' })
const rules = getExpirationRules({
currentLanguage: 'de',
store: {
getters: { capabilities: { files_sharing: { public: { expire_date: capabilities } } } }
} as Store<any>
})

expect(rules.enforced).toEqual(capabilities.enforced)
expect(rules.default).toEqual(new Date('2000-01-11'))
expect(rules.min).toEqual(new Date('2000-01-01'))
expect(rules.max).toEqual(new Date('2000-01-11'))
})
})
2 changes: 1 addition & 1 deletion packages/web-runtime/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
<template v-if="modal.customContent || modal.customComponent" #content>
<div v-if="modal.customContent" v-html="modal.customContent" />
<component
ref="modalComponent"
:is="modal.customComponent"
v-else
ref="modalComponent"
:modal="modal"
v-bind="modal.customComponentAttrs"
/>
Expand Down