1
1
<template >
2
2
<div id =" incoming" class =" sciencemesh-app" >
3
3
<div >
4
- <div class =" oc-flex oc-flex-middle oc-px-m oc-py -s" >
4
+ <div class =" oc-flex oc-flex-middle oc-px-m oc-pt -s" >
5
5
<oc-icon name =" user-received" />
6
6
<h2 class =" oc-px-s" v-text =" $gettext('Accept invitations')" />
7
7
<oc-contextual-helper class =" oc-pl-xs" v-bind =" helperContent" />
8
8
</div >
9
- <div v-if =" !providers.length" class =" oc-flex oc-flex-center oc-flex-middle" >
10
- <oc-icon name =" error-warning" fill-type =" line" class =" oc-mr-s" size =" large" />
11
- <span v-text =" $gettext('The list of institutions is empty. Please contact your admin.')" />
12
- </div >
13
- <div v-else class =" oc-flex oc-flex-column oc-flex-middle oc-flex-center oc-p-m" >
9
+ <div class =" oc-flex oc-flex-column oc-flex-middle oc-flex-center oc-p-m" >
14
10
<div class =" oc-width-1-2" >
15
11
<oc-text-input
16
- ref =" tokenInput"
17
12
v-model =" token"
18
13
:label =" $gettext('Enter invite token')"
19
14
:clear-button-enabled =" true"
20
- class =" oc-mb-m"
15
+ class =" oc-mb-s"
16
+ @update:model-value =" decodeInviteToken"
21
17
/>
22
- <oc-select
23
- v-model =" provider"
24
- :label =" $gettext('Select institution of inviter')"
25
- :options =" providers"
26
- class =" oc-mb-m"
27
- :position-fixed =" true"
28
- :loading =" loading"
18
+ <div
19
+ :class =" {
20
+ 'oc-text-input-danger': providerError && token,
21
+ 'oc-text-input-success': provider
22
+ }"
29
23
>
30
- <template #option =" { full_name , domain } " >
31
- <div class =" oc-text-break" >
32
- <span class =" option" >
33
- <strong v-text =" full_name" />
34
- </span >
35
- <span class =" option" v-text =" domain" />
36
- </div >
37
- </template >
38
- <template #no-options > No institutions found with this name</template >
39
- <template #selected-option =" { full_name , domain } " >
40
- <div class =" options-wrapper oc-text-break" >
41
- <strong class =" oc-mr-s oc-text-break" v-text =" full_name" />
42
- <small
43
- v-oc-tooltip =" domain"
44
- v-text =" domain.length > 17 ? domain.slice(0, 20) + '...' : domain"
45
- />
46
- </div >
47
- </template >
48
- </oc-select >
49
- <div v-if =" providerError" class =" oc-text-input-message" >
50
- <span
51
- class =" oc-text-input-danger"
52
- v-text =" $gettext('Unknown institution. Check invitation url or select from list')"
53
- />
24
+ <span v-text =" $gettext('Institution:')" />
25
+ <span v-if =" !token" v-text =" '-'" />
26
+ <span v-else-if =" provider" v-text =" provider" />
27
+ <span v-else v-text =" $gettext('invalid invite token')" />
54
28
</div >
55
29
</div >
56
- <oc-button size =" small" :disabled =" acceptInvitationButtonDisabled" @click =" acceptInvite" >
30
+ <oc-button
31
+ size =" small"
32
+ :disabled =" acceptInvitationButtonDisabled"
33
+ class =" oc-mt-s"
34
+ @click =" acceptInvite"
35
+ >
57
36
<oc-icon name =" add" />
58
37
<span v-text =" $gettext('Accept invitation')" />
59
38
</oc-button >
63
42
</template >
64
43
65
44
<script lang="ts">
66
- import { computed , defineComponent , onMounted , ref , unref } from ' vue'
67
- import {
68
- queryItemAsString ,
69
- useClientService ,
70
- useRoute ,
71
- useRouter ,
72
- useMessages ,
73
- useConfigStore
74
- } from ' @ownclouders/web-pkg'
45
+ import { computed , defineComponent , ref , unref } from ' vue'
46
+ import { useClientService , useRoute , useRouter , useMessages } from ' @ownclouders/web-pkg'
75
47
import { useGettext } from ' vue3-gettext'
76
- import { onBeforeRouteUpdate , RouteLocationNormalized } from ' vue-router'
77
- import { ProviderSchema , providerListSchema } from ' ../schemas'
78
- import { OcTextInput } from ' @ownclouders/design-system/components'
79
48
80
49
export default defineComponent ({
81
50
emits: [' highlightNewConnections' ],
82
51
setup(props , { emit }) {
83
52
const { showErrorMessage } = useMessages ()
84
53
const router = useRouter ()
54
+ const route = useRoute ()
85
55
const clientService = useClientService ()
86
- const configStore = useConfigStore ()
87
56
const { $gettext } = useGettext ()
88
57
89
58
const token = ref <string >(undefined )
90
- const provider = ref <ProviderSchema >(undefined )
91
- const providers = ref <ProviderSchema []>([])
92
- const loading = ref (true )
59
+ const decodedToken = ref <string >(undefined )
60
+ const provider = ref <string >(undefined )
93
61
const providerError = ref (false )
94
- const tokenInput = ref <InstanceType <typeof OcTextInput >>()
95
62
96
63
const helperContent = computed (() => {
97
64
return {
@@ -103,7 +70,7 @@ export default defineComponent({
103
70
})
104
71
105
72
const acceptInvitationButtonDisabled = computed (() => {
106
- return ! unref (token ) || ! unref (provider ) || unref ( provider ). full_name === ' Unknown provider '
73
+ return ! unref (decodedToken ) || ! unref (provider )
107
74
})
108
75
109
76
const errorPopup = (error : Error ) => {
@@ -117,8 +84,8 @@ export default defineComponent({
117
84
const acceptInvite = async () => {
118
85
try {
119
86
await clientService .httpAuthenticated .post (' /sciencemesh/accept-invite' , {
120
- token: unref (token ),
121
- providerDomain: unref (provider ). domain
87
+ token: unref (decodedToken ),
88
+ providerDomain: unref (provider )
122
89
})
123
90
token .value = undefined
124
91
provider .value = undefined
@@ -134,90 +101,32 @@ export default defineComponent({
134
101
errorPopup (error )
135
102
}
136
103
}
137
- const listProviders = async () => {
138
- try {
139
- const { data : allProviders } = await clientService .httpAuthenticated .get (
140
- ' /sciencemesh/list-providers' ,
141
- {
142
- schema: providerListSchema
143
- }
144
- )
145
- providers .value = allProviders .filter ((p ) => ! isMyProviderSelectedProvider (p ))
146
- } catch (error ) {
147
- errorPopup (error )
148
- } finally {
149
- loading .value = false
150
- }
151
- }
152
- const scrollToForm = () => {
153
- const el = document .getElementById (' sciencemesh-accept-invites' )
154
- if (el ) {
155
- el .scrollIntoView ()
156
- }
157
- }
158
- const isMyProviderSelectedProvider = (p : ProviderSchema ) => {
159
- // the protocol is not important, we just need the host and port, it's there to make it compatible with URL
160
- const toURL = (purl : string ) =>
161
- new URL (purl .split (' ://' ).length === 1 ? ` https://${purl } ` : purl )
162
- const { host : configStoreHost, port : configStorePort } = toURL (configStore .serverUrl )
163
- const { host : providerSchemaHost, port : providerSchemaPort } = toURL (p .domain )
164
104
165
- return [
166
- // ensure that the config store host is not empty, minimal check
167
- !! configStoreHost ,
168
- // ensure that the provider schema host is not empty, minimal check
169
- !! providerSchemaHost ,
170
- // check if the host is the same
171
- configStoreHost === providerSchemaHost ,
172
- // also check the port, multiple instances can run on the same host but not on the same port...
173
- configStorePort === providerSchemaPort
174
- ].every ((c ) => c )
175
- }
176
-
177
- const handleParams = (to : RouteLocationNormalized ) => {
178
- const tokenQuery = to .query .token
179
- if (tokenQuery ) {
180
- token .value = queryItemAsString (tokenQuery )
181
- unref (tokenInput ).focus ()
182
- scrollToForm ()
183
- }
184
- const providerDomainQuery = to .query .providerDomain
185
- if (providerDomainQuery ) {
186
- const matchedProvider = unref (providers )?.find (
187
- (p ) => p .domain === queryItemAsString (providerDomainQuery )
188
- )
189
- if (matchedProvider ) {
190
- provider .value = matchedProvider
191
- providerError .value = false
192
- } else {
193
- provider .value = {
194
- full_name: ' Unknown provider' ,
195
- domain: queryItemAsString (providerDomainQuery )
196
- }
197
- providerError .value = true
105
+ const decodeInviteToken = (value : string ) => {
106
+ try {
107
+ const decoded = atob (value )
108
+ if (! decoded .includes (' @' )) {
109
+ throw new Error ()
198
110
}
111
+ const [token, serverUrl] = decoded .split (' @' )
112
+ provider .value = serverUrl
113
+ decodedToken .value = token
114
+ providerError .value = false
115
+ } catch (e ) {
116
+ provider .value = ' '
117
+ decodedToken .value = ' '
118
+ providerError .value = true
199
119
}
200
120
}
201
121
202
- const route = useRoute ()
203
- onMounted (async () => {
204
- await listProviders ()
205
- handleParams (unref (route ))
206
- })
207
- onBeforeRouteUpdate ((to ) => {
208
- handleParams (to )
209
- })
210
-
211
122
return {
212
- tokenInput ,
213
123
helperContent ,
214
124
token ,
215
125
provider ,
216
- providers ,
217
- loading ,
218
126
providerError ,
219
127
acceptInvitationButtonDisabled ,
220
- acceptInvite
128
+ acceptInvite ,
129
+ decodeInviteToken
221
130
}
222
131
}
223
132
})
0 commit comments