mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-04 03:27:05 -04:00
144 lines
4.7 KiB
Vue
144 lines
4.7 KiB
Vue
<template>
|
|
<section>
|
|
<Alert type="danger" :message="error"/>
|
|
|
|
<div v-if="token === null">
|
|
<form @submit.prevent="login" :disabled="saving">
|
|
<p>
|
|
<Icon v="info-circle"/>
|
|
<T>user.login.why</T>
|
|
</p>
|
|
<div class="input-group mb-3">
|
|
<input type="text" class="form-control" v-model="usernameOrEmail"
|
|
:placeholder="$t('user.login.placeholder')" autofocus required/>
|
|
<button class="btn btn-primary">
|
|
<Icon v="sign-in"/>
|
|
<T>user.login.action</T>
|
|
</button>
|
|
</div>
|
|
<div class="btn-group w-100 mb-3">
|
|
<a :href="`/api/connect/${provider}`" v-for="(providerOptions, provider) in socialProviders" class="btn btn-outline-primary">
|
|
<Icon :v="providerOptions.icon || provider" set="b"/>
|
|
{{ providerOptions.name }}
|
|
</a>
|
|
</div>
|
|
<p class="small text-muted">
|
|
<Icon v="gavel"/>
|
|
<T>terms.consent</T>
|
|
</p>
|
|
<p class="small text-muted">
|
|
<Icon v="lock"/>
|
|
<T>user.login.passwordless</T>
|
|
</p>
|
|
</form>
|
|
</div>
|
|
<div v-else-if="payload && !payload.code">
|
|
<div class="alert alert-success">
|
|
<p class="mb-0">
|
|
<Icon v="envelope-open-text"/>
|
|
<T>user.login.emailSent</T>
|
|
</p>
|
|
</div>
|
|
|
|
<form @submit.prevent="validate" :disabled="saving">
|
|
<div class="input-group mb-3">
|
|
<input type="text" class="form-control text-center" v-model="code"
|
|
placeholder="000000" autofocus required minlength="0" maxlength="6"
|
|
inputmode="numeric" pattern="[0-9]{6}" autocomplete="one-time-code"
|
|
ref="code"
|
|
/>
|
|
<button class="btn btn-primary">
|
|
<Icon v="key"/>
|
|
<T>user.code.action</T>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script>
|
|
import jwt from 'jsonwebtoken';
|
|
import {socialProviders} from "../src/data";
|
|
import cookieSettings from "../src/cookieSettings";
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
token: null,
|
|
usernameOrEmail: '',
|
|
code: '',
|
|
|
|
error: '',
|
|
|
|
socialProviders,
|
|
|
|
saving: false,
|
|
};
|
|
},
|
|
computed: {
|
|
payload() {
|
|
if (!this.token) {
|
|
return null;
|
|
}
|
|
|
|
this.$store.commit('setToken', this.token);
|
|
this.$cookies.set('token', this.$store.state.token, cookieSettings);
|
|
|
|
return jwt.verify(this.token, process.env.PUBLIC_KEY, {
|
|
algorithm: 'RS256',
|
|
audience: this.$base,
|
|
issuer: this.$base,
|
|
});
|
|
}
|
|
},
|
|
methods: {
|
|
async login() {
|
|
if (this.saving) {
|
|
return;
|
|
}
|
|
this.saving = true;
|
|
await this.post(`/user/init`, {
|
|
usernameOrEmail: this.usernameOrEmail
|
|
});
|
|
this.saving = false;
|
|
},
|
|
async validate() {
|
|
if (this.saving) {
|
|
return;
|
|
}
|
|
this.saving = true;
|
|
await this.post(`/user/validate`, {
|
|
code: this.code
|
|
}, {
|
|
headers: {
|
|
authorization: 'Bearer ' + this.token,
|
|
},
|
|
});
|
|
this.saving = false;
|
|
},
|
|
async post(url, data, options = {}) {
|
|
this.error = '';
|
|
|
|
const response = await this.$axios.$post(url, data, options);
|
|
|
|
this.usernameOrEmail = '';
|
|
this.code = '';
|
|
|
|
if (response.error) {
|
|
this.error = response.error;
|
|
return;
|
|
}
|
|
|
|
this.token = response.token;
|
|
|
|
this.$nextTick(_ => {
|
|
if (this.$refs.code) {
|
|
this.$refs.code.focus();
|
|
}
|
|
})
|
|
},
|
|
},
|
|
}
|
|
</script>
|