Skip to content

Commit

Permalink
feat(federation): provide UI toggles in Admin settings for federation…
Browse files Browse the repository at this point in the history
… options

Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
  • Loading branch information
Antreesy committed Feb 20, 2024
1 parent cabba5a commit d45bd04
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 2 deletions.
4 changes: 4 additions & 0 deletions lib/Settings/Admin/AdminSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ protected function initCommands(): void {

protected function initFederation(): void {
$this->initialState->provideInitialState('federation_enabled', $this->serverConfig->getAppValue('spreed', 'federation_enabled', 'no'));
$this->initialState->provideInitialState('federation_incoming_enabled', $this->serverConfig->getAppValue('spreed', 'federation_incoming_enabled', '1'));
$this->initialState->provideInitialState('federation_outgoing_enabled', $this->serverConfig->getAppValue('spreed', 'federation_outgoing_enabled', '1'));
$this->initialState->provideInitialState('federation_only_trusted_servers', $this->serverConfig->getAppValue('spreed', 'federation_only_trusted_servers', '0'));
$this->initialState->provideInitialState('federation_allowed_groups', $this->serverConfig->getAppValue('spreed', 'federation_allowed_groups', '[]'));
}

protected function initMatterbridge(): void {
Expand Down
200 changes: 198 additions & 2 deletions src/components/AdminSettings/Federation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
-->

<template>
<section id="general_settings" class="federation section">
<section id="federation_settings" class="federation section">
<h2>
{{ t('spreed', 'Federation') }}
<small>{{ t('spreed', 'Beta') }}</small>
Expand All @@ -33,28 +33,130 @@
@update:checked="saveFederationEnabled">
{{ t('spreed', 'Enable Federation in Talk app') }}
</NcCheckboxRadioSwitch>

<template v-if="isFederationEnabled">
<h3>{{ t('spreed', 'Permissions') }}</h3>

<NcCheckboxRadioSwitch :checked="isFederationIncomingEnabled"
:disabled="loading"
type="switch"
@update:checked="saveFederationIncomingEnabled">
{{ t('spreed', 'Allow users to be invited to federated conversations') }}
</NcCheckboxRadioSwitch>

<NcCheckboxRadioSwitch :checked="isFederationOutgoingEnabled"
:disabled="loading"
type="switch"
@update:checked="saveFederationOutgoingEnabled">
{{ t('spreed', 'Allow users to invite federated users into conversation') }}
</NcCheckboxRadioSwitch>

<NcCheckboxRadioSwitch :checked="isFederationOnlyTrustedServersEnabled"
:disabled="loading"
type="switch"
@update:checked="saveFederationOnlyTrustedServersEnabled">
{{ t('spreed', 'Only allow to federate with trusted servers') }}
</NcCheckboxRadioSwitch>
<!-- eslint-disable-next-line vue/no-v-html -->
<p class="settings-hint additional-top-margin" v-html="trustedServersLink" />

<h3>{{ t('spreed', 'Limit to groups') }}</h3>

<p class="settings-hint additional-top-margin">
{{ t('spreed', 'When at least one group is selected, only people of the listed groups can invite federated users to conversations.') }}
</p>

<div class="form">
<NcSelect v-model="allowedGroups"
input-id="allow_groups_invite_federated"
:input-label="t('spreed', 'Groups allowed to invite federated users')"
name="allow_groups_invite_federated"
class="form__select"
:options="groups"
:placeholder="t('spreed', 'Select groups …')"
:disabled="loading"
multiple
searchable
:tag-width="60"
:loading="loadingGroups"
:show-no-options="false"
:close-on-select="false"
track-by="id"
label="displayname"
no-wrap
@search-change="debounceSearchGroup" />

<NcButton type="primary"
:disabled="loading"
@click="saveAllowedGroups">
{{ saveLabelAllowedGroups }}
</NcButton>
</div>
</template>
</section>
</template>

<script>
import debounce from 'debounce'

import axios from '@nextcloud/axios'
import { loadState } from '@nextcloud/initial-state'
import { generateOcsUrl, generateUrl } from '@nextcloud/router'

import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js'

const FEDERATION_ENABLED = loadState('spreed', 'federation_enabled', 'no') === 'yes'
const FEDERATION_INCOMING_ENABLED = loadState('spreed', 'federation_incoming_enabled', '0') === '1'
const FEDERATION_OUTGOING_ENABLED = loadState('spreed', 'federation_outgoing_enabled', '0') === '1'
const FEDERATION_ONLY_TRUSTED_SERVERS = loadState('spreed', 'federation_only_trusted_servers', '0') === '1'
const FEDERATION_ALLOWED_GROUPS = JSON.parse(loadState('spreed', 'federation_allowed_groups', '[]'))

export default {
name: 'Federation',

components: {
NcButton,
NcCheckboxRadioSwitch,
NcSelect,
},

data() {
return {
loading: false,
isFederationEnabled: loadState('spreed', 'federation_enabled') === 'yes',
isFederationEnabled: FEDERATION_ENABLED,
isFederationIncomingEnabled: FEDERATION_INCOMING_ENABLED,
isFederationOutgoingEnabled: FEDERATION_OUTGOING_ENABLED,
isFederationOnlyTrustedServersEnabled: FEDERATION_ONLY_TRUSTED_SERVERS,
loadingGroups: false,
groups: [],
allowedGroups: [],
saveLabelAllowedGroups: t('spreed', 'Save changes'),
debounceSearchGroup: () => {},
}
},

computed: {
trustedServersLink() {
const href = generateUrl('/settings/admin/sharing#ocFederationSettings')
return t('spreed', 'Trusted servers can be configured at {linkstart}Sharing settings page{linkend}.')
.replace('{linkstart}', `<a target="_blank" rel="noreferrer nofollow" class="external" href="${href}">`)
.replaceAll('{linkend}', ' ↗</a>')
},
},

mounted() {
// allowed groups come as an array of string ids here
this.allowedGroups = FEDERATION_ALLOWED_GROUPS.sort((a, b) => a.localeCompare(b))
this.debounceSearchGroup = debounce(this.searchGroup, 500)
this.debounceSearchGroup('')
},

beforeDestroy() {
this.debounceSearchGroup.clear?.()
},

methods: {
saveFederationEnabled(value) {
this.loading = true
Expand All @@ -66,6 +168,80 @@ export default {
}.bind(this),
})
},

saveFederationIncomingEnabled(value) {
this.loading = true

OCP.AppConfig.setValue('spreed', 'federation_incoming_enabled', value ? '1' : '0', {
success: function() {
this.loading = false
this.isFederationIncomingEnabled = value
}.bind(this),
})
},

saveFederationOutgoingEnabled(value) {
this.loading = true

OCP.AppConfig.setValue('spreed', 'federation_outgoing_enabled', value ? '1' : '0', {
success: function() {
this.loading = false
this.isFederationOutgoingEnabled = value
}.bind(this),
})
},

saveFederationOnlyTrustedServersEnabled(value) {
this.loading = true

OCP.AppConfig.setValue('spreed', 'federation_only_trusted_servers', value ? '1' : '0', {
success: function() {
this.loading = false
this.isFederationOnlyTrustedServersEnabled = value
}.bind(this),
})
},

async searchGroup(query) {
this.loadingGroups = true
try {
const response = await axios.get(generateOcsUrl('cloud/groups/details'), {
search: query,
limit: 20,
offset: 0,
})
this.groups = response.data.ocs.data.groups.sort(function(a, b) {
return a.displayname.localeCompare(b.displayname)
})

// repopulate allowed groups with full group objects to show display name
const allowedGroupIds = this.allowedGroups.map(group => typeof group === 'object' ? group.id : group)
this.allowedGroups = this.groups.filter(group => allowedGroupIds.includes(group.id))
} catch (err) {
console.error('Could not fetch groups', err)
} finally {
this.loadingGroups = false
}
},

saveAllowedGroups() {
this.loading = true
this.loadingGroups = true
this.saveLabelAllowedGroups = t('spreed', 'Saving …')

const groups = this.allowedGroups.map(group => typeof group === 'object' ? group.id : group)

OCP.AppConfig.setValue('spreed', 'federation_allowed_groups', JSON.stringify(groups), {
success: function() {
this.loading = false
this.loadingGroups = false
this.saveLabelAllowedGroups = t('spreed', 'Saved!')
setTimeout(function() {
this.saveLabelAllowedGroups = t('spreed', 'Save changes')
}.bind(this), 5000)
}.bind(this),
})
},
},
}
</script>
Expand All @@ -77,4 +253,24 @@ small {
border-radius: 16px;
padding: 0 9px;
}

h3 {
margin-top: 24px;
font-weight: bold;
}

.additional-top-margin {
margin-top: 10px;
}

.form {
display: flex;
align-items: flex-end;
gap: 10px;
padding-top: 5px;

&__select {
min-width: 300px !important;
}
}
</style>

0 comments on commit d45bd04

Please sign in to comment.