-
Notifications
You must be signed in to change notification settings - Fork 20
/
Login.vue
149 lines (147 loc) · 5.76 KB
/
Login.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<template>
<section class="hero is-fullheight">
<div class="hero-body">
<div class="container has-text-centered">
<div class="column is-4 is-offset-4">
<div class="box has-background-shade-3">
<form @submit.prevent="login">
<h3 class="title has-text-grey is-flex is-justify-content-center is-align-items-center"><img class="image is-48x48 is-inline mr-2" :src="logoSrc">{{ appName }}</h3>
<p class="subtitle has-text-grey">Login</p>
<div class="field">
<div class="control has-icons-left">
<input v-model="credentials.jid" class="input is-medium" type="text" name="jid" :placeholder="jidPlaceholder">
<span class="icon is-small is-left">
<i class="fa fa-user" />
</span>
</div>
</div>
<div class="field">
<div class="control has-icons-left">
<input v-model="credentials.password" class="input is-medium" type="password" name="password" placeholder="Password">
<span class="icon is-small is-left">
<i class="fa fa-lock" />
</span>
</div>
</div>
<div class="field has-text-left pl-3">
<o-checkbox v-model="credentials.remember" variant="primary" class="has-text-grey-light">
Store my password in browser
</o-checkbox>
</div>
<o-collapse v-if="isTransportsUserAllowed" class="card has-background-shade-3 mb-3" :open="false" aria-id="connection-settings">
<template #trigger="props">
<div role="button" aria-controls="connection-settings" class="card-header">
<p class="card-header-title has-text-grey-light"><span class="fa fa-cog fa-fw mr-3" aria-hidden="true" />Connection settings</p>
<a class="card-header-icon has-text-grey-light">
<span class="fa fa-fw mr-3" :class="[props.open ? 'fa-caret-down': 'fa-caret-up']" aria-hidden="true" />
</a>
</div>
</template>
<div class="card-content">
<div class="field">
<div class="control">
<input v-model="transportsUser.websocket" class="input" type="url" name="websocket" placeholder="wss://chat.domain.ltd/xmpp-websocket" title="Websocket url">
</div>
</div>
</div>
</o-collapse>
<div class="field">
<button type="submit" class="button is-block is-primary is-medium is-fullwidth" :class="{ 'is-loading': isLoading }" :disabled="isDisabled"><span class="fa fa-sign-in fa-fw mr-3" aria-hidden="true" />Login</button>
</div>
<div v-if="error" class="message is-danger">
<div class="message-body has-text-danger">{{ error }}</div>
</div>
</form>
</div>
</div>
</div>
</div>
<version />
</section>
</template>
<script>
import { mapState } from 'pinia'
import { useStore } from '@/store'
import Version from '../components/Version.vue'
export default {
name: 'Login',
components: {
Version,
},
data () {
return {
credentials: {
jid: '',
password: '',
remember: false,
},
transportsUser: {
websocket: window.config.transports.websocket,
},
isLoading: false,
error: '',
isTransportsUserAllowed: window.config.isTransportsUserAllowed,
}
},
computed: {
isDisabled () {
return this.isLoading || !this.credentials.jid || !this.credentials.password || !this.hasNetwork
},
jidPlaceholder () {
return (typeof window.config.defaultDomain === 'string' && window.config.defaultDomain !== '') ? `username@${window.config.defaultDomain}` : 'username@domain.ltd'
},
appName () {
return (typeof window.config.name === 'string' && window.config.name !== '') ? window.config.name : 'XMPP webchat'
},
logoSrc () {
return window.config.logoUrl || 'img/icons/android-chrome-192x192.png'
},
...mapState(useStore, ['hasNetwork']),
},
mounted () {
// remove navbar spacing
document.body.classList.remove('has-navbar-fixed-top')
// get stored credentials
const jid = localStorage.getItem('jid')
if (jid) {
this.credentials.jid = jid
}
const password = localStorage.getItem('p')
if (password) {
// auto login
const reverse = (value) => value.split('').reverse().join('')
this.credentials.password = reverse(atob(reverse(password)))
this.login()
}
},
methods: {
async login () {
this.error = ''
const reverse = (value) => value.split('').reverse().join('')
// check credentials are set
if (this.credentials.jid === '' || this.credentials.password === '') {
return
}
// call the auth service
this.isLoading = true
try {
await this.$xmpp.create(this.credentials.jid, this.credentials.password, null, this.transportsUser, this)
await this.$xmpp.connect()
// authentication succeeded, route to requested page or default
if (this.credentials.remember) {
localStorage.setItem('p', reverse(btoa(reverse(this.credentials.password))))
}
if (this.$route.query.redirect !== undefined) {
return this.$router.push(this.$route.query.redirect)
}
this.$router.push('/')
} catch (error) {
// authentication failed, display error
this.error = error.message
}
// remove loading status
this.isLoading = false
},
},
}
</script>