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

Force the user to scroll text to be able to accept the TOS #950

Merged
merged 1 commit into from
Jul 23, 2024
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
4 changes: 2 additions & 2 deletions js/terms_of_service-admin.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/terms_of_service-admin.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/terms_of_service-public.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/terms_of_service-public.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/terms_of_service-registration.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/terms_of_service-registration.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/terms_of_service-user.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/terms_of_service-user.js.map

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<template>
<Fragment>
<NcSettingsSection :title="t('terms_of_service', 'Terms of service')"
<NcSettingsSection :name="t('terms_of_service', 'Terms of service')"
:description="t('terms_of_service', 'Require users to accept the terms of service before accessing the service.')">
<NcCheckboxRadioSwitch type="switch"
:checked.sync="showForLoggedInUser">
Expand All @@ -21,11 +21,13 @@
<NcSelect v-model="country"
:options="countryOptions"
:placeholder="t('terms_of_service', 'Select a region')"
:aria-label-combobox="t('terms_of_service', 'Select a region')"
label="label"
track-by="value" />
<NcSelect v-model="language"
:options="languageOptions"
:placeholder="t('terms_of_service', 'Select a language')"
:aria-label-combobox="t('terms_of_service', 'Select a language')"
label="label"
track-by="value" />
</span>
Expand All @@ -45,7 +47,7 @@
</NcSettingsSection>

<NcSettingsSection v-if="hasTerms"
:title="t('terms_of_service', 'Existing terms of service')">
:name="t('terms_of_service', 'Existing terms of service')">
<NcButton :disabled="resetButtonDisabled"
type="error"
@click="onResetSignatories">
Expand Down
16 changes: 14 additions & 2 deletions src/Registration.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<NcModal v-if="showModal"
:can-close="hasSigned"
@close="handleCloseModal">
<ModalContent @click="acceptTerms">
<ModalContent :is-scroll-complete="hasScrolledToBottom" @click="acceptTerms">
<template #header>
<h3>{{ t('terms_of_service', 'Terms of service') }}</h3>
<select v-if="terms.length > 1" v-model="selectedLanguage">
Expand All @@ -35,7 +35,10 @@
</template>

<!-- eslint-disable-next-line vue/no-v-html -->
<div class="text-content" v-html="termsBody" />
<div ref="termsContent"
class="text-content"
@scroll="checkScroll"
v-html="termsBody" />

Check warning on line 41 in src/Registration.vue

View workflow job for this annotation

GitHub Actions / NPM lint

'v-html' directive can lead to XSS attack
</ModalContent>
</NcModal>
</div>
Expand Down Expand Up @@ -68,6 +71,7 @@
termsId: 0,
termsBody: '',
publicContent: null,
hasScrolledToBottom: false,
}
},

Expand Down Expand Up @@ -128,6 +132,14 @@
return
}
this.showModal = true
this.$nextTick(() => {
this.checkScroll()
})
},
checkScroll() {
const termsContent = this.$refs.termsContent
const isScrollable = termsContent.scrollHeight > termsContent.clientHeight
this.hasScrolledToBottom = !isScrollable || (termsContent.scrollHeight - termsContent.scrollTop <= termsContent.clientHeight + 1)
},

acceptTerms() {
Expand Down
83 changes: 48 additions & 35 deletions src/UserApp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<NcModal v-if="showModal"
:can-close="hasSigned"
@close="handleCloseModal">
<ModalContent @click="acceptTerms">
<ModalContent :is-scroll-complete="hasScrolledToBottom" @click="acceptTerms">
<template #header>
<h3>{{ t('terms_of_service', 'Terms of service') }}</h3>
<select v-if="terms.length > 1" v-model="selectedLanguage">
Expand All @@ -19,7 +19,10 @@
</template>

<!-- eslint-disable-next-line vue/no-v-html -->
<div class="text-content" v-html="termsBody" />
<div ref="termsContent"
class="text-content"
@scroll="checkScroll"
v-html="termsBody" />

Check warning on line 25 in src/UserApp.vue

View workflow job for this annotation

GitHub Actions / NPM lint

'v-html' directive can lead to XSS attack
</ModalContent>
</NcModal>
</div>
Expand Down Expand Up @@ -49,6 +52,7 @@
termsId: 0,
termsBody: '',
publicContent: null,
hasScrolledToBottom: false,
}
},

Expand All @@ -63,38 +67,38 @@
},

methods: {
loadTerms() {
axios
.get(generateUrl('/apps/terms_of_service/terms'))
.then(response => {
this.hasSigned = response.data.hasSigned
this.terms = response.data.terms

const language = OC.getLanguage().split('-')[0]

if (!this.terms.length || this.hasSigned) {
return
}

// make it Vue
this.publicContent = document.getElementById('files-public-content')
if (this.publicContent !== null) {
this.publicContent.style.visibility = 'hidden'
}

this.selectTerms(0)
if (this.terms.length > 1) {
Object.keys(this.terms).forEach((index) => {
if (language === this.terms[index].languageCode) {
this.selectedLanguage = index
}

this.languages.push(response.data.languages[this.terms[index].languageCode])
})
}

this.showTerms()
})
async loadTerms() {
try {
const response = await axios.get(generateUrl('/apps/terms_of_service/terms'))
this.hasSigned = response.data.hasSigned
this.terms = response.data.terms

const language = OC.getLanguage().split('-')[0]

if (!this.terms.length || this.hasSigned) {
return
}

this.publicContent = document.getElementById('files-public-content')
if (this.publicContent !== null) {
this.publicContent.style.visibility = 'hidden'
}

this.selectTerms(0)
if (this.terms.length > 1) {
Object.keys(this.terms).forEach((index) => {
if (language === this.terms[index].languageCode) {
this.selectedLanguage = index
}

this.languages.push(response.data.languages[this.terms[index].languageCode])
})
}

this.showTerms()
} catch (error) {
console.error('Error loading terms:', error)
}
},

selectTerms(index) {
Expand All @@ -104,6 +108,9 @@

showTerms() {
this.showModal = true
this.$nextTick(() => {
this.checkScroll()
})
},

acceptTerms() {
Expand All @@ -126,12 +133,18 @@
handleCloseModal() {
this.showModal = false
},

checkScroll() {
const termsContent = this.$refs.termsContent
const isScrollable = termsContent.scrollHeight > termsContent.clientHeight

this.hasScrolledToBottom = !isScrollable || (termsContent.scrollHeight - termsContent.scrollTop <= termsContent.clientHeight + 1)
},
},
}
</script>

<style lang="scss" scoped>

:deep .modal-container {
display: flex;
height: 100%;
Expand Down
32 changes: 26 additions & 6 deletions src/components/ModalContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
- SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<template>
<div id="terms_of_service_content"
class="modal-content"
Expand All @@ -13,7 +12,9 @@
</div>

<!-- Scrollable terms of service -->
<slot />
<div ref="termsContent" class="terms-content">
<slot />
</div>

<!-- Sticky button -->
<NcButton ref="acceptButton"
Expand All @@ -22,6 +23,7 @@
:wide="true"
autofocus
:title="t('terms_of_service', 'I acknowledge that I have read and agree to the above terms of service')"
:disabled="!isScrollComplete"
@click.prevent.stop="handleClick"
@keydown.enter="handleClick">
{{ t('terms_of_service', 'I acknowledge that I have read and agree to the above terms of service') }}
Expand All @@ -39,6 +41,13 @@ export default {
NcButton,
},

props: {
isScrollComplete: {
type: Boolean,
default: false,
},
},

mounted() {
this.$nextTick(() => {
this.$refs.acceptButton.$el.focus()
Expand All @@ -47,12 +56,13 @@ export default {

methods: {
handleClick() {
this.$emit('click')
if (this.isScrollComplete) {
this.$emit('click')
}
},
},
}
</script>

<style lang="scss" scoped>
/* Little hack to strengthen the css selector so links with dark mode on the registration page are readable */
#terms_of_service_content.modal-content,
Expand All @@ -76,10 +86,15 @@ export default {
margin: 8px 0 12px 0;
}

.terms-content {
height: 100%;
overflow-y: auto;
flex: 1;
}

select {
float: right;
padding: 0 12px;

/**
* Need to overwrite the rules of guest.css
*/
Expand All @@ -90,7 +105,6 @@ export default {
border-color: var(--color-primary-element);
}
}

/**
* Basic Markdown support
*/
Expand Down Expand Up @@ -123,5 +137,11 @@ export default {
}
}
}
</style>

<style lang="scss" scoped>
:deep .modal-container {
display: flex;
height: 100%;
}
</style>