Skip to content

feat: warning about folders public links #178

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

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
:label="label"
type="date"
:min="minDate?.toISODate()"
:max="maxDate?.toISODate()"
:fix-message-line="true"
:error-message="errorMessage"
:clear-button-enabled="isClearable"
Expand All @@ -25,7 +26,8 @@ export default defineComponent({
label: { type: String, required: true },
isClearable: { type: Boolean, default: true },
currentDate: { type: Object as PropType<DateTime>, required: false, default: null },
minDate: { type: Object as PropType<DateTime>, required: false, default: null }
minDate: { type: Object as PropType<DateTime>, required: false, default: null },
maxDate: { type: Object as PropType<DateTime>, required: false, default: null }
},
emits: ['dateChanged'],
setup(props, { emit }) {
Expand All @@ -44,6 +46,13 @@ export default defineComponent({
return unref(date) < props.minDate
})

const isMaxDateExceeded = computed(() => {
if (!props.maxDate || !unref(date)) {
return false
}
return unref(date) > props.maxDate
})

const errorMessage = computed(() => {
if (unref(isMinDateUndercut)) {
return $gettext('The date must be after %{date}', {
Expand All @@ -53,6 +62,14 @@ export default defineComponent({
.toLocaleString(DateTime.DATE_SHORT)
})
}
if (unref(isMaxDateExceeded)) {
return $gettext('The date must be before %{date}', {
date: props.maxDate
.plus({ day: 1 })
.setLocale(current)
.toLocaleString(DateTime.DATE_SHORT)
})
}
return ''
})

Expand All @@ -73,6 +90,7 @@ export default defineComponent({
date,
() => {
emit('dateChanged', { date: unref(date), error: unref(isMinDateUndercut) })
emit('dateChanged', { date: unref(date), error: unref(isMaxDateExceeded) })
},
{
deep: true
Expand All @@ -97,7 +115,7 @@ export default defineComponent({
```js
<template>
<div>
<oc-datepicker :current-date="currentDate" :min-date="minDate" label="Enter or pick a date"
<oc-datepicker :current-date="currentDate" :min-date="minDate" :max-date="maxDate" label="Enter or pick a date"
@date-changed="onDateChanged"/>
<p v-if="selectedDate" v-text="selectedDate"/>
</div>
Expand All @@ -107,7 +125,7 @@ export default defineComponent({

export default {
data: () => ({
minDate: DateTime.now(), currentDate: DateTime.now(), selectedDate: ''
minDate: DateTime.now(), currentDate: DateTime.now(), selectedDate: '', maxDate: null
}),
methods: {
onDateChanged({date}) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
:label="$gettext('Expiration date')"
type="date"
:min-date="minDate"
:max-date="maxDate"
:current-date="currentDate"
:is-clearable="isClearable"
@date-changed="onDateChanged"
Expand Down Expand Up @@ -38,6 +39,7 @@ export default defineComponent({
modal: { type: Object as PropType<Modal>, required: true },
currentDate: { type: Object as PropType<DateTime>, required: false, default: null },
minDate: { type: Object as PropType<DateTime>, required: false, default: null },
maxDate: { type: Object as PropType<DateTime>, required: false, default: null },
isClearable: { type: Boolean, default: true }
},
emits: ['confirm', 'cancel'],
Expand Down
64 changes: 62 additions & 2 deletions packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ import {
useResourcesStore,
useLinkTypes,
useCanShare,
UpdateLinkOptions
UpdateLinkOptions,
useCapabilityStore
} from '@ownclouders/web-pkg'
import { shareViaLinkHelp, shareViaIndirectLinkHelp } from '../../../helpers/contextualHelpers'
import { isSpaceResource, LinkShare } from '@ownclouders/web-client'
Expand All @@ -102,11 +103,14 @@ import { isLocationSharesActive, useSharesStore } from '@ownclouders/web-pkg'
import { useGettext } from 'vue3-gettext'
import { storeToRefs } from 'pinia'
import { SharingLinkType } from '@ownclouders/web-client/graph/generated'
import { DateTime, Duration } from 'luxon'

export default defineComponent({
name: 'FileLinks',
components: { ListItem },
setup() {
const { sharingPublicExpireDateDefaultRWFolders, sharingPublicExpireDateMaxRWFolders } =
useCapabilityStore()
const { showMessage, showErrorMessage } = useMessages()
const { $gettext } = useGettext()
const ability = useAbility()
Expand All @@ -124,12 +128,15 @@ export default defineComponent({
return canShare({ space: unref(space), resource: unref(resource) })
})

const language = useGettext()

const sharesStore = useSharesStore()
const { updateLink, deleteLink } = sharesStore
const { linkShares } = storeToRefs(sharesStore)

const configStore = useConfigStore()
const { options: configOptions } = storeToRefs(configStore)
const alertRwFolders = configStore.options.alertRwFolders

const { actions: createLinkActions } = useFileActionsCreateLink()
const createLinkAction = computed<FileAction>(() =>
Expand Down Expand Up @@ -192,14 +199,62 @@ export default defineComponent({
options: UpdateLinkOptions['options']
}) => {
try {
if (
options.type === 'edit' &&
unref(resource).isFolder &&
!linkShare.expirationDateTime &&
sharingPublicExpireDateDefaultRWFolders
) {
Object.assign(options, {
...options,
expirationDateTime: DateTime.now()
.plus(sharingPublicExpireDateDefaultRWFolders)
.endOf('day')
.toISO()
})
}
if (
unref(resource).isFolder &&
linkShare.expirationDateTime &&
sharingPublicExpireDateDefaultRWFolders &&
sharingPublicExpireDateMaxRWFolders
) {
if (
DateTime.fromISO(linkShare.expirationDateTime).diff(DateTime.now(), 'days').as('days') >
Duration.fromObject(sharingPublicExpireDateMaxRWFolders).as('days')
) {
Object.assign(options, {
...options,
expirationDateTime: DateTime.now()
.plus(sharingPublicExpireDateDefaultRWFolders)
.endOf('day')
.toISO()
})
}
}
await updateLink({
clientService,
space: unref(space),
resource: unref(resource),
linkShare,
options
}).then(() => {
showMessage({ title: $gettext('Link was updated successfully') })
})
showMessage({ title: $gettext('Link was updated successfully') })
if (options.type === 'edit' && unref(resource).isFolder && alertRwFolders) {
if (!document.getElementById('files-file-link-warning')) {
const warningMessage = document.createElement('div')
warningMessage.className = 'oc-mb-m oc-p-s oc-background-secondary oc-rounded'
warningMessage.id = 'files-file-link-warning'
warningMessage.innerHTML = $gettext(
alertRwFolders[language.current] ?? alertRwFolders[Object.keys(alertRwFolders)[0]]
)
document.getElementById('files-links-list').parentElement.prepend(warningMessage)
setTimeout(() => {
warningMessage.remove()
}, 10000)
}
}
} catch (e) {
console.error(e)
showErrorMessage({
Expand Down Expand Up @@ -349,4 +404,9 @@ export default defineComponent({
margin-top: var(--oc-space-medium);
}
}
#files-file-link-warning {
color: var(--oc-color-swatch-danger-default);
text-align: center;
border: solid 1px var(--oc-color-swatch-danger-muted);
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import { DateTime } from 'luxon'
import {
createLocationSpaces,
useCapabilityStore,
useGetMatchingSpace,
useModals,
useResourcesStore
Expand Down Expand Up @@ -97,6 +98,7 @@ export default defineComponent({
const { $gettext } = useGettext()
const { getMatchingSpace } = useGetMatchingSpace()
const resourcesStore = useResourcesStore()
const { sharingPublicExpireDateMaxRWFolders } = useCapabilityStore()
const editPublicLinkDropdown = useTemplateRef<typeof OcDrop>('editPublicLinkDropdown')

const resource = inject<Ref<Resource>>('resource')
Expand All @@ -110,7 +112,13 @@ export default defineComponent({
customComponent: DatePickerModal,
customComponentAttrs: () => ({
currentDate: currentDate.isValid ? currentDate : null,
minDate: DateTime.now()
minDate: DateTime.now(),
maxDate:
resource.value.isFolder &&
props.linkShare.type === SharingLinkType.Edit &&
sharingPublicExpireDateMaxRWFolders
? DateTime.now().plus(sharingPublicExpireDateMaxRWFolders).endOf('day')
: null
}),
onConfirm: (expirationDateTime: DateTime) => {
emit('updateLink', {
Expand Down Expand Up @@ -214,18 +222,27 @@ export default defineComponent({
method: showDatePickerModal
})

result.push({
id: 'remove-expiration',
title: $gettext('Remove expiration date'),
icon: 'calendar-close',
method: () => {
emit('updateLink', {
linkShare: { ...props.linkShare },
options: { expirationDateTime: null }
})
unref(editPublicLinkDropdown).hide()
}
})
// only if it isn't a edit folder link
if (
!(
props.linkShare.type === SharingLinkType.Edit &&
resource.value.isFolder &&
sharingPublicExpireDateMaxRWFolders
)
) {
result.push({
id: 'remove-expiration',
title: $gettext('Remove expiration date'),
icon: 'calendar-close',
method: () => {
emit('updateLink', {
linkShare: { ...props.linkShare },
options: { expirationDateTime: null }
})
unref(editPublicLinkDropdown).hide()
}
})
}
} else if (!unref(isInternalLink)) {
result.push({
id: 'add-expiration',
Expand Down
13 changes: 13 additions & 0 deletions packages/web-client/src/ocs/capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,19 @@ export interface Capabilities {
send_mail?: boolean
supports_upload_only?: boolean
upload?: boolean
expire_date?: {
enabled?: boolean
default_rw_folders?: {
years?: number
months?: number
days?: number
}
max_rw_folders?: {
years?: number
months?: number
days?: number
}
}
}
search_min_length?: number
user?: {
Expand Down
30 changes: 27 additions & 3 deletions packages/web-pkg/src/components/CreateLinkModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@
v-if="isAdvancedMode"
class="oc-mt-s"
:min-date="DateTime.now()"
:max-date="
isFolder && selectedType === 'edit' && sharingPublicExpireDateMaxRWFolders
? DateTime.now().plus(sharingPublicExpireDateMaxRWFolders).endOf('day')
: null
"
:label="$gettext('Expiry date')"
@date-changed="onExpiryDateChanged"
/>
Expand All @@ -69,7 +74,7 @@
appearance="filled"
variation="primary"
:disabled="confirmButtonDisabled"
@click="$emit('confirm')"
@click="$emit('confirm', { isRW: selectedType === 'edit', isFolder })"
>{{ confirmButtonText }}
</oc-button>
<oc-button
Expand All @@ -94,7 +99,13 @@
<oc-button
class="oc-modal-body-actions-confirm-password action-menu-item"
appearance="raw"
@click="$emit('confirm', { copyPassword: true })"
@click="
$emit('confirm', {
copyPassword: true,
isRW: selectedType === 'edit',
isFolder
})
"
>{{ $gettext('Copy link and password') }}
</oc-button>
</li>
Expand Down Expand Up @@ -125,7 +136,8 @@ import {
useLinkTypes,
Modal,
useSharesStore,
useClientService
useClientService,
useCapabilityStore
} from '../composables'
import { LinkShare, SpaceResource } from '@ownclouders/web-client'
import { Resource } from '@ownclouders/web-client'
Expand Down Expand Up @@ -169,6 +181,7 @@ export default defineComponent({
const { addLink } = useSharesStore()
const isAdvancedMode = ref(false)
const isInvalidExpiryDate = ref(false)
const { sharingPublicExpireDateMaxRWFolders } = useCapabilityStore()

const isFolder = computed(() => props.resources.every(({ isFolder }) => isFolder))

Expand Down Expand Up @@ -297,6 +310,15 @@ export default defineComponent({

const updateSelectedLinkType = (type: SharingLinkType) => {
selectedType.value = type
onExpiryDateChanged({
date: unref(selectedExpiry),
error:
sharingPublicExpireDateMaxRWFolders &&
unref(selectedExpiry)?.toISO() >
DateTime.now().plus(sharingPublicExpireDateMaxRWFolders).endOf('day').toISO() &&
isFolder &&
unref(selectedType) === 'edit'
})
}

onMounted(() => {
Expand Down Expand Up @@ -332,7 +354,9 @@ export default defineComponent({
setAdvancedMode,
onExpiryDateChanged,
confirmButtonDisabled,
isFolder,
DateTime,
sharingPublicExpireDateMaxRWFolders,

// unit tests
onConfirm
Expand Down
Loading