Skip to content

Commit

Permalink
refactor: move link expiration rules to a helper method
Browse files Browse the repository at this point in the history
This is necessary because we need the method in more than one place in the future. Also, previously this was named "expiration date", although it defines rules for setting an expiration date for a link. Hence the rename to "expiration rules".
  • Loading branch information
JammingBen committed Nov 29, 2023
1 parent 98fb886 commit 5040593
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 58 deletions.
50 changes: 13 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 All @@ -113,6 +113,7 @@
import { computed, defineComponent, inject, ref, Ref, unref } from 'vue'
import { DateTime } from 'luxon'
import { mapGetters, mapActions, mapMutations } from 'vuex'
import { useGettext } from 'vue3-gettext'
import {
useStore,
useCapabilitySpacesEnabled,
Expand All @@ -124,7 +125,8 @@ import {
useCapabilityFilesSharingPublicPasswordEnforcedFor,
useAbility,
usePasswordPolicyService,
getDefaultLinkPermissions
getDefaultLinkPermissions,
getExpirationRules
} from '@ownclouders/web-pkg'
import { shareViaLinkHelp, shareViaIndirectLinkHelp } from '../../../helpers/contextualHelpers'
import {
Expand Down Expand Up @@ -160,6 +162,7 @@ export default defineComponent({
},
setup() {
const store = useStore()
const { current: currentLanguage } = useGettext()
const ability = useAbility()
const { can } = ability
const passwordPolicyService = usePasswordPolicyService()
Expand Down Expand Up @@ -219,6 +222,8 @@ export default defineComponent({
)
}
const expirationRules = computed(() => getExpirationRules({ store, currentLanguage }))
return {
$store: store,
ability,
Expand All @@ -241,7 +246,8 @@ export default defineComponent({
configurationManager,
passwordPolicyService,
canCreateLinks,
canEditLink
canEditLink,
expirationRules
}
},
computed: {
Expand All @@ -264,36 +270,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 +391,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
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

0 comments on commit 5040593

Please sign in to comment.