feat(webui): claim server from login screen

closes #207
This commit is contained in:
Gauthier Roebroeck 2020-07-05 12:00:00 +08:00
parent 47dd2f66e0
commit d4810bdc80
6 changed files with 117 additions and 6 deletions

View file

@ -11,6 +11,7 @@ module.exports = {
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-fallthrough': 'off',
'comma-dangle': ['error', 'always-multiline'],
},
parserOptions: {

View file

@ -9,6 +9,7 @@ import App from './App.vue'
import actuator from './plugins/actuator.plugin'
import httpPlugin from './plugins/http.plugin'
import komgaBooks from './plugins/komga-books.plugin'
import komgaClaim from './plugins/komga-claim.plugin'
import komgaCollections from './plugins/komga-collections.plugin'
import komgaFileSystem from './plugins/komga-filesystem.plugin'
import komgaLibraries from './plugins/komga-libraries.plugin'
@ -31,6 +32,7 @@ Vue.use(komgaSeries, { http: Vue.prototype.$http })
Vue.use(komgaCollections, { http: Vue.prototype.$http })
Vue.use(komgaBooks, { http: Vue.prototype.$http })
Vue.use(komgaReferential, { http: Vue.prototype.$http })
Vue.use(komgaClaim, { http: Vue.prototype.$http })
Vue.use(komgaUsers, { store: store, http: Vue.prototype.$http })
Vue.use(komgaLibraries, { store: store, http: Vue.prototype.$http })
Vue.use(actuator, { http: Vue.prototype.$http })

View file

@ -0,0 +1,17 @@
import KomgaClaimService from '@/services/komga-claim.service'
import { AxiosInstance } from 'axios'
import _Vue from 'vue'
export default {
install (
Vue: typeof _Vue,
{ http }: { http: AxiosInstance }) {
Vue.prototype.$komgaClaim = new KomgaClaimService(http)
},
}
declare module 'vue/types/vue' {
interface Vue {
$komgaClaim: KomgaClaimService;
}
}

View file

@ -0,0 +1,40 @@
import { AxiosInstance } from 'axios'
const API_CLAIM = '/api/v1/claim'
export default class KomgaClaimService {
private http: AxiosInstance
constructor (http: AxiosInstance) {
this.http = http
}
async getClaimStatus (): Promise<ClaimStatus> {
try {
return (await this.http.get(API_CLAIM)).data
} catch (e) {
let msg = 'An error occurred while trying to retrieve claim status'
if (e.response.data.message) {
msg += `: ${e.response.data.message}`
}
throw new Error(msg)
}
}
async claimServer (user: ClaimAdmin): Promise<UserDto> {
try {
return (await this.http.post(API_CLAIM, {}, {
headers: {
'X-Komga-Email': user.email,
'X-Komga-Password': user.password,
},
})).data
} catch (e) {
let msg = 'An error occurred while trying to claim server'
if (e.response.data.message) {
msg += `: ${e.response.data.message}`
}
throw new Error(msg)
}
}
}

View file

@ -0,0 +1,8 @@
interface ClaimStatus {
isClaimed: boolean
}
interface ClaimAdmin {
email: string,
password: string
}

View file

@ -7,10 +7,25 @@
</v-row>
<form novalidate @submit.prevent="performLogin">
<v-row justify="center" v-if="unclaimed">
<v-col
cols="12" sm="8" md="6" lg="4" xl="2"
class="body-1 mt-2"
>
<v-alert type="info"
icon="mdi-account-plus"
prominent
text
>This Komga server is not yet active, you need to create a user account to be able to access it.<br/><br/>Choose
an <strong>email</strong> and <strong>password</strong> and click on <strong>Create user account</strong>.
</v-alert>
</v-col>
</v-row>
<v-row justify="center">
<v-col cols="12" sm="8" md="6" lg="4" xl="2">
<v-text-field v-model="form.login"
label="Login"
label="Email"
autocomplete="username"
autofocus
/>
@ -31,8 +46,15 @@
<v-col cols="12" sm="8" md="6" lg="4" xl="2">
<v-btn color="primary"
type="submit"
:disabled="unclaimed"
>Login
</v-btn>
<v-btn v-if="unclaimed"
class="ml-4"
color="primary"
@click="claim"
>Create user account
</v-btn>
</v-col>
</v-row>
</form>
@ -65,23 +87,32 @@ export default Vue.extend({
},
snackbar: false,
snackText: '',
unclaimed: false,
}),
computed: {
logoWidth (): number {
let l = 100
switch (this.$vuetify.breakpoint.name) {
case 'xs':
return 100
l = 100
case 'sm':
case 'md':
return 200
l = 200
case 'lg':
case 'xl':
default:
return 400
l = 300
}
return l / (this.unclaimed ? 2 : 1)
},
},
mounted () {
this.getClaimStatus()
},
methods: {
async getClaimStatus () {
this.unclaimed = !(await this.$komgaClaim.getClaimStatus()).isClaimed
},
async performLogin () {
try {
await this.$store.dispatch(
@ -94,9 +125,9 @@ export default Vue.extend({
await this.$store.dispatch('getLibraries')
if (this.$route.query.redirect) {
this.$router.push({ path: this.$route.query.redirect.toString() })
await this.$router.push({ path: this.$route.query.redirect.toString() })
} else {
this.$router.push({ name: 'home' })
await this.$router.push({ name: 'home' })
}
} catch (e) {
this.showSnack(e.message)
@ -106,6 +137,18 @@ export default Vue.extend({
this.snackText = message
this.snackbar = true
},
async claim () {
try {
await this.$komgaClaim.claimServer({
email: this.form.login,
password: this.form.password,
} as ClaimAdmin)
await this.performLogin()
} catch (e) {
this.showSnack(e.message)
}
},
},
})
</script>