Skip to content

Commit 2fc2e82

Browse files
authored
Merge pull request #5979 from LibreSign/feat/support-whatsapp-signal-telegram-xmpp-token-methods
feat: support whatsapp signal telegram xmpp token methods
2 parents 3d4e969 + dbac40e commit 2fc2e82

File tree

5 files changed

+81
-42
lines changed

5 files changed

+81
-42
lines changed

lib/Service/IdentifyMethod/SignatureMethod/TokenService.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ private function getGateway(string $gatewayName) {
4747
throw new LibresignException('App Two-Factor Gateway is not installed.');
4848

4949
}
50-
$gateway = $factory->getGateway($gatewayName);
51-
if (!$gateway->getConfig()->isComplete()) {
50+
$gateway = $factory->get($gatewayName);
51+
if (!$gateway->isComplete()) {
5252
throw new OCSForbiddenException($this->l10n->t('Gateway %s not configured on Two-Factor Gateway.', $gatewayName));
5353
}
5454
return $gateway;

lib/Service/SignFileService.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,8 @@ public function requestCode(
612612
continue;
613613
}
614614
/** @var IToken $signatureMethod */
615-
$signatureMethod->requestCode($identify, $identifyMethod->getEntity()->getIdentifierKey());
615+
$identifier = $identify ?: $identifyMethod->getEntity()->getIdentifierValue();
616+
$signatureMethod->requestCode($identifier, $identifyMethod->getEntity()->getIdentifierKey());
616617
return;
617618
}
618619
throw new LibresignException($this->l10n->t('Sending authorization code not enabled.'));

src/store/signMethods.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ export const useSignMethodsStore = defineStore('signMethods', {
7777
return Object.hasOwn(this.settings, 'sms')
7878
&& this.settings.sms.needCode
7979
},
80+
needTokenCode() {
81+
const tokenMethods = ['sms', 'whatsapp', 'signal', 'telegram', 'xmpp']
82+
return tokenMethods.some(method =>
83+
Object.hasOwn(this.settings, method) && this.settings[method].needCode
84+
)
85+
},
8086
needCertificate() {
8187
return this.certificateEngine === 'none' && !this.hasSignatureFile()
8288
},

src/views/SignPDF/_partials/ModalSMSManager.vue renamed to src/views/SignPDF/_partials/ModalTokenManager.vue

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44
-->
55
<template>
66
<NcDialog v-if="signMethodsStore.modal.sms"
7-
:name="t('libresign', 'Sign with your cellphone number.')"
7+
:name="t('libresign', 'Sign with your phone number.')"
88
@closing="signMethodsStore.closeModal('sms')">
9-
<div v-if="newPhoneNumber" class="code-request">
9+
<div v-if="tokenRequested" class="code-request">
1010
<h3 class="phone">
1111
{{ newPhoneNumber }}
1212
</h3>
1313

14-
<NcTextField v-if="tokenRequested"
15-
v-model="token"
14+
<NcTextField v-model="token"
1615
:disabled="loading"
1716
name="code"
1817
type="text" />
@@ -26,24 +25,18 @@
2625
@change="sanitizeNumber" />
2726
</div>
2827
<template #actions>
29-
<NcButton v-if="newPhoneNumber && !tokenRequested" :disabled="loading" @click="requestCode">
28+
<NcButton v-if="!tokenRequested" :disabled="loading || newPhoneNumber.length < 10" @click="requestCode">
3029
<template #icon>
3130
<NcLoadingIcon v-if="loading" :size="20" />
3231
</template>
3332
{{ t('libresign', 'Request code.') }}
3433
</NcButton>
35-
<NcButton v-if="newPhoneNumber && tokenRequested" :disabled="loading" @click="sendCode">
34+
<NcButton v-else :disabled="loading || token.length < 3" @click="sendCode">
3635
<template #icon>
3736
<NcLoadingIcon v-if="loading" :size="20" />
3837
</template>
3938
{{ t('libresign', 'Send code.') }}
4039
</NcButton>
41-
<NcButton v-if="!newPhoneNumber" :disabled="loading || newPhoneNumber.length < 10" @click="saveNumber">
42-
<template #icon>
43-
<NcLoadingIcon v-if="loading" :size="20" />
44-
</template>
45-
{{ t('libresign', 'Save your number.') }}
46-
</NcButton>
4740
</template>
4841
</NcDialog>
4942
</template>
@@ -61,14 +54,15 @@ import NcTextField from '@nextcloud/vue/components/NcTextField'
6154
6255
import { settingsService } from '../../../domains/settings/index.js'
6356
import { useSignStore } from '../../../store/sign.js'
57+
import { useSignMethodsStore } from '../../../store/signMethods.js'
6458
6559
const sanitizeNumber = val => {
6660
val = val.replace(/\D/g, '')
6761
return `+${val}`
6862
}
6963
7064
export default {
71-
name: 'ModalSMSManager',
65+
name: 'ModalTokenManager',
7266
components: {
7367
NcDialog,
7468
NcLoadingIcon,
@@ -78,19 +72,34 @@ export default {
7872
props: {
7973
phoneNumber: {
8074
type: String,
81-
required: true,
75+
required: false,
76+
default: '',
8277
},
8378
},
8479
setup() {
8580
const signStore = useSignStore()
86-
return { signStore }
81+
const signMethodsStore = useSignMethodsStore()
82+
return { signStore, signMethodsStore }
83+
},
84+
data() {
85+
return {
86+
token: '',
87+
newPhoneNumber: this.phoneNumber || '',
88+
tokenRequested: false,
89+
loading: false,
90+
}
91+
},
92+
computed: {
93+
activeTokenMethod() {
94+
const tokenMethods = ['sms', 'whatsapp', 'signal', 'telegram', 'xmpp']
95+
return tokenMethods.find(method =>
96+
Object.hasOwn(this.signMethodsStore.settings, method)
97+
) || 'sms'
98+
},
99+
activeIdentifyMethod() {
100+
return this.activeTokenMethod
101+
},
87102
},
88-
data: () => ({
89-
token: '',
90-
newPhoneNumber: this.phoneNumber,
91-
tokenRequested: false,
92-
loading: false,
93-
}),
94103
methods: {
95104
async saveNumber() {
96105
this.loading = true
@@ -123,22 +132,40 @@ export default {
123132
await this.$nextTick()
124133
125134
try {
135+
const params = {
136+
identifyMethod: this.activeIdentifyMethod,
137+
signMethod: this.activeTokenMethod,
138+
}
139+
126140
if (this.signStore.document.fileId) {
127-
const { data } = await axios.post(generateOcsUrl('/apps/libresign/api/v1/sign/file_id/{fileId}/code', {
128-
fileId: this.signStore.document.fileId,
129-
}))
141+
const { data } = await axios.post(
142+
generateOcsUrl('/apps/libresign/api/v1/sign/file_id/{fileId}/code', {
143+
fileId: this.signStore.document.fileId,
144+
}),
145+
params
146+
)
130147
showSuccess(data.ocs.data.message)
131148
} else {
132-
const signer = this.signStore.document.signers.find(row => row.me) || {}
133-
const { data } = await axios.post(generateOcsUrl('/apps/libresign/api/v1/sign/uuid/{fileId}/code', {
149+
const signer = this.signStore.document.signers.find(row => row.me) || {}
150+
const { data } = await axios.post(
151+
generateOcsUrl('/apps/libresign/api/v1/sign/uuid/{uuid}/code', {
134152
uuid: signer.sign_uuid,
135-
}))
153+
}),
154+
params
155+
)
136156
showSuccess(data.ocs.data.message)
137157
}
138-
this.tokenRequested = true
139-
} catch (err) {
140-
showError(err.response.data.ocs.data.message)
141-
} finally {
158+
this.tokenRequested = true
159+
} catch (err) {
160+
const errorMessage = err.response?.data?.ocs?.data?.message || err.response?.data?.message || err.message
161+
162+
if (errorMessage && errorMessage.includes('Invalid configuration')) {
163+
const method = this.activeTokenMethod.charAt(0).toUpperCase() + this.activeTokenMethod.slice(1)
164+
showError(t('libresign', '{method} is not configured. Please contact your administrator.', { method }))
165+
} else {
166+
showError(errorMessage)
167+
}
168+
} finally {
142169
this.loading = false
143170
}
144171
},

src/views/SignPDF/_partials/Sign.vue

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@
130130
:useModal="true"
131131
:errors="errors"
132132
@certificate:uploaded="onSignatureFileCreated" />
133-
<SMSManager v-if="signMethodsStore.modal.sms"
134-
:phone-number="user?.account?.phoneNumber"
135-
@change="signWithSMSCode"
133+
<TokenManager v-if="signMethodsStore.modal.sms"
134+
:phone-number="user?.account?.phoneNumber || ''"
135+
@change="signWithTokenCode"
136136
@update:phone="val => $emit('update:phone', val)"
137137
@close="signMethodsStore.closeModal('sms')" />
138138
<EmailManager v-if="signMethodsStore.modal.emailToken"
@@ -156,7 +156,7 @@ import NcPasswordField from '@nextcloud/vue/components/NcPasswordField'
156156
import NcRichText from '@nextcloud/vue/components/NcRichText'
157157
158158
import EmailManager from './ModalEmailManager.vue'
159-
import SMSManager from './ModalSMSManager.vue'
159+
import TokenManager from './ModalTokenManager.vue'
160160
import Draw from '../../../Components/Draw/Draw.vue'
161161
import Documents from '../../../views/Account/partials/Documents.vue'
162162
import Signatures from '../../../views/Account/partials/Signatures.vue'
@@ -180,7 +180,7 @@ export default {
180180
NcPasswordField,
181181
NcRichText,
182182
CreatePassword,
183-
SMSManager,
183+
TokenManager,
184184
EmailManager,
185185
Documents,
186186
Signatures,
@@ -324,9 +324,14 @@ export default {
324324
token: this.signPassword,
325325
})
326326
},
327-
async signWithSMSCode(token) {
327+
async signWithTokenCode(token) {
328+
const tokenMethods = ['sms', 'whatsapp', 'signal', 'telegram', 'xmpp']
329+
const activeMethod = tokenMethods.find(method =>
330+
Object.hasOwn(this.signMethodsStore.settings, method)
331+
) || 'sms'
332+
328333
await this.signDocument({
329-
method: 'sms',
334+
method: activeMethod,
330335
token,
331336
})
332337
},
@@ -395,7 +400,7 @@ export default {
395400
this.showModalAndResetErrors('createSignature')
396401
return
397402
}
398-
if (this.signMethodsStore.needSmsCode()) {
403+
if (this.signMethodsStore.needTokenCode()) {
399404
this.showModalAndResetErrors('sms')
400405
return
401406
}

0 commit comments

Comments
 (0)