21
21
-->
22
22
23
23
<template >
24
- <section id =" general_settings " class =" federation section" >
24
+ <section id =" federation_settings " class =" federation section" >
25
25
<h2 >
26
26
{{ t('spreed', 'Federation') }}
27
27
<small >{{ t('spreed', 'Beta') }}</small >
33
33
@update:checked =" saveFederationEnabled" >
34
34
{{ t('spreed', 'Enable Federation in Talk app') }}
35
35
</NcCheckboxRadioSwitch >
36
+
37
+ <template v-if =" isFederationEnabled " >
38
+ <h3 >{{ t('spreed', 'Permissions') }}</h3 >
39
+
40
+ <NcCheckboxRadioSwitch :checked =" isFederationIncomingEnabled"
41
+ :disabled =" loading"
42
+ type =" switch"
43
+ @update:checked =" saveFederationIncomingEnabled" >
44
+ {{ t('spreed', 'Allow users to be invited to federated conversations') }}
45
+ </NcCheckboxRadioSwitch >
46
+
47
+ <NcCheckboxRadioSwitch :checked =" isFederationOutgoingEnabled"
48
+ :disabled =" loading"
49
+ type =" switch"
50
+ @update:checked =" saveFederationOutgoingEnabled" >
51
+ {{ t('spreed', 'Allow users to invite federated users into conversation') }}
52
+ </NcCheckboxRadioSwitch >
53
+
54
+ <NcCheckboxRadioSwitch :checked =" isFederationOnlyTrustedServersEnabled"
55
+ :disabled =" loading"
56
+ type =" switch"
57
+ @update:checked =" saveFederationOnlyTrustedServersEnabled" >
58
+ {{ t('spreed', 'Only allow to federate with trusted servers') }}
59
+ </NcCheckboxRadioSwitch >
60
+ <!-- eslint-disable-next-line vue/no-v-html -->
61
+ <p class =" settings-hint additional-top-margin" v-html =" trustedServersLink" />
62
+
63
+ <h3 >{{ t('spreed', 'Limit to groups') }}</h3 >
64
+
65
+ <p class =" settings-hint additional-top-margin" >
66
+ {{ t('spreed', 'When at least one group is selected, only people of the listed groups can invite federated users to conversations.') }}
67
+ </p >
68
+
69
+ <div class =" form" >
70
+ <NcSelect v-model =" allowedGroups"
71
+ input-id =" allow_groups_invite_federated"
72
+ :input-label =" t('spreed', 'Groups allowed to invite federated users')"
73
+ name =" allow_groups_invite_federated"
74
+ class =" form__select"
75
+ :options =" groups"
76
+ :placeholder =" t('spreed', 'Select groups …')"
77
+ :disabled =" loading"
78
+ multiple
79
+ searchable
80
+ :tag-width =" 60"
81
+ :loading =" loadingGroups"
82
+ :show-no-options =" false"
83
+ :close-on-select =" false"
84
+ track-by =" id"
85
+ label =" displayname"
86
+ no-wrap
87
+ @search-change =" debounceSearchGroup" />
88
+
89
+ <NcButton type =" primary"
90
+ :disabled =" loading"
91
+ @click =" saveAllowedGroups" >
92
+ {{ saveLabelAllowedGroups }}
93
+ </NcButton >
94
+ </div >
95
+ </template >
36
96
</section >
37
97
</template >
38
98
39
99
<script >
100
+ import debounce from ' debounce'
101
+
102
+ import axios from ' @nextcloud/axios'
40
103
import { loadState } from ' @nextcloud/initial-state'
104
+ import { generateOcsUrl , generateUrl } from ' @nextcloud/router'
41
105
106
+ import NcButton from ' @nextcloud/vue/dist/Components/NcButton.js'
42
107
import NcCheckboxRadioSwitch from ' @nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
108
+ import NcSelect from ' @nextcloud/vue/dist/Components/NcSelect.js'
109
+
110
+ const FEDERATION_ENABLED = loadState (' spreed' , ' federation_enabled' , ' no' ) === ' yes'
111
+ const FEDERATION_INCOMING_ENABLED = loadState (' spreed' , ' federation_incoming_enabled' , ' 0' ) === ' 1'
112
+ const FEDERATION_OUTGOING_ENABLED = loadState (' spreed' , ' federation_outgoing_enabled' , ' 0' ) === ' 1'
113
+ const FEDERATION_ONLY_TRUSTED_SERVERS = loadState (' spreed' , ' federation_only_trusted_servers' , ' 0' ) === ' 1'
114
+ const FEDERATION_ALLOWED_GROUPS = JSON .parse (loadState (' spreed' , ' federation_allowed_groups' , ' []' ))
43
115
44
116
export default {
45
117
name: ' Federation' ,
46
118
47
119
components: {
120
+ NcButton,
48
121
NcCheckboxRadioSwitch,
122
+ NcSelect,
49
123
},
50
124
51
125
data () {
52
126
return {
53
127
loading: false ,
54
- isFederationEnabled: loadState (' spreed' , ' federation_enabled' ) === ' yes' ,
128
+ isFederationEnabled: FEDERATION_ENABLED ,
129
+ isFederationIncomingEnabled: FEDERATION_INCOMING_ENABLED ,
130
+ isFederationOutgoingEnabled: FEDERATION_OUTGOING_ENABLED ,
131
+ isFederationOnlyTrustedServersEnabled: FEDERATION_ONLY_TRUSTED_SERVERS ,
132
+ loadingGroups: false ,
133
+ groups: [],
134
+ allowedGroups: [],
135
+ saveLabelAllowedGroups: t (' spreed' , ' Save changes' ),
136
+ debounceSearchGroup : () => {},
55
137
}
56
138
},
57
139
140
+ computed: {
141
+ trustedServersLink () {
142
+ const href = generateUrl (' /settings/admin/sharing#ocFederationSettings' )
143
+ return t (' spreed' , ' Trusted servers can be configured at {linkstart}Sharing settings page{linkend}.' )
144
+ .replace (' {linkstart}' , ` <a target="_blank" rel="noreferrer nofollow" class="external" href="${ href} ">` )
145
+ .replaceAll (' {linkend}' , ' ↗</a>' )
146
+ },
147
+ },
148
+
149
+ mounted () {
150
+ // allowed groups come as an array of string ids here
151
+ this .allowedGroups = FEDERATION_ALLOWED_GROUPS .sort ((a , b ) => a .localeCompare (b))
152
+ this .debounceSearchGroup = debounce (this .searchGroup , 500 )
153
+ this .debounceSearchGroup (' ' )
154
+ },
155
+
156
+ beforeDestroy () {
157
+ this .debounceSearchGroup .clear ? .()
158
+ },
159
+
58
160
methods: {
59
161
saveFederationEnabled (value ) {
60
162
this .loading = true
@@ -66,6 +168,80 @@ export default {
66
168
}.bind (this ),
67
169
})
68
170
},
171
+
172
+ saveFederationIncomingEnabled (value ) {
173
+ this .loading = true
174
+
175
+ OCP .AppConfig .setValue (' spreed' , ' federation_incoming_enabled' , value ? ' 1' : ' 0' , {
176
+ success : function () {
177
+ this .loading = false
178
+ this .isFederationIncomingEnabled = value
179
+ }.bind (this ),
180
+ })
181
+ },
182
+
183
+ saveFederationOutgoingEnabled (value ) {
184
+ this .loading = true
185
+
186
+ OCP .AppConfig .setValue (' spreed' , ' federation_outgoing_enabled' , value ? ' 1' : ' 0' , {
187
+ success : function () {
188
+ this .loading = false
189
+ this .isFederationOutgoingEnabled = value
190
+ }.bind (this ),
191
+ })
192
+ },
193
+
194
+ saveFederationOnlyTrustedServersEnabled (value ) {
195
+ this .loading = true
196
+
197
+ OCP .AppConfig .setValue (' spreed' , ' federation_only_trusted_servers' , value ? ' 1' : ' 0' , {
198
+ success : function () {
199
+ this .loading = false
200
+ this .isFederationOnlyTrustedServersEnabled = value
201
+ }.bind (this ),
202
+ })
203
+ },
204
+
205
+ async searchGroup (query ) {
206
+ this .loadingGroups = true
207
+ try {
208
+ const response = await axios .get (generateOcsUrl (' cloud/groups/details' ), {
209
+ search: query,
210
+ limit: 20 ,
211
+ offset: 0 ,
212
+ })
213
+ this .groups = response .data .ocs .data .groups .sort (function (a , b ) {
214
+ return a .displayname .localeCompare (b .displayname )
215
+ })
216
+
217
+ // repopulate allowed groups with full group objects to show display name
218
+ const allowedGroupIds = this .allowedGroups .map (group => typeof group === ' object' ? group .id : group)
219
+ this .allowedGroups = this .groups .filter (group => allowedGroupIds .includes (group .id ))
220
+ } catch (err) {
221
+ console .error (' Could not fetch groups' , err)
222
+ } finally {
223
+ this .loadingGroups = false
224
+ }
225
+ },
226
+
227
+ saveAllowedGroups () {
228
+ this .loading = true
229
+ this .loadingGroups = true
230
+ this .saveLabelAllowedGroups = t (' spreed' , ' Saving …' )
231
+
232
+ const groups = this .allowedGroups .map (group => typeof group === ' object' ? group .id : group)
233
+
234
+ OCP .AppConfig .setValue (' spreed' , ' federation_allowed_groups' , JSON .stringify (groups), {
235
+ success : function () {
236
+ this .loading = false
237
+ this .loadingGroups = false
238
+ this .saveLabelAllowedGroups = t (' spreed' , ' Saved!' )
239
+ setTimeout (function () {
240
+ this .saveLabelAllowedGroups = t (' spreed' , ' Save changes' )
241
+ }.bind (this ), 5000 )
242
+ }.bind (this ),
243
+ })
244
+ },
69
245
},
70
246
}
71
247
< / script>
@@ -77,4 +253,24 @@ small {
77
253
border- radius: 16px ;
78
254
padding: 0 9px ;
79
255
}
256
+
257
+ h3 {
258
+ margin- top: 24px ;
259
+ font- weight: bold;
260
+ }
261
+
262
+ .additional - top- margin {
263
+ margin- top: 10px ;
264
+ }
265
+
266
+ .form {
267
+ display: flex;
268
+ align- items: flex- end;
269
+ gap: 10px ;
270
+ padding- top: 5px ;
271
+
272
+ & __select {
273
+ min- width: 300px ! important;
274
+ }
275
+ }
80
276
< / style>
0 commit comments