diff --git a/komga-webui/.eslintrc.js b/komga-webui/.eslintrc.js index ac30a86fb..35ef034b5 100644 --- a/komga-webui/.eslintrc.js +++ b/komga-webui/.eslintrc.js @@ -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: { diff --git a/komga-webui/src/main.ts b/komga-webui/src/main.ts index fa37c9ee7..305b6a1bb 100644 --- a/komga-webui/src/main.ts +++ b/komga-webui/src/main.ts @@ -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 }) diff --git a/komga-webui/src/plugins/komga-claim.plugin.ts b/komga-webui/src/plugins/komga-claim.plugin.ts new file mode 100644 index 000000000..ec5813b0e --- /dev/null +++ b/komga-webui/src/plugins/komga-claim.plugin.ts @@ -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; + } +} diff --git a/komga-webui/src/services/komga-claim.service.ts b/komga-webui/src/services/komga-claim.service.ts new file mode 100644 index 000000000..6e539b240 --- /dev/null +++ b/komga-webui/src/services/komga-claim.service.ts @@ -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 { + 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 { + 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) + } + } +} diff --git a/komga-webui/src/types/komga-claim.ts b/komga-webui/src/types/komga-claim.ts new file mode 100644 index 000000000..c6279385d --- /dev/null +++ b/komga-webui/src/types/komga-claim.ts @@ -0,0 +1,8 @@ +interface ClaimStatus { + isClaimed: boolean +} + +interface ClaimAdmin { + email: string, + password: string +} diff --git a/komga-webui/src/views/Login.vue b/komga-webui/src/views/Login.vue index 4f795467d..67a75c446 100644 --- a/komga-webui/src/views/Login.vue +++ b/komga-webui/src/views/Login.vue @@ -7,10 +7,25 @@
+ + + This Komga server is not yet active, you need to create a user account to be able to access it.

Choose + an email and password and click on Create user account. +
+
+
+ @@ -31,8 +46,15 @@ Login + Create user account +
@@ -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) + } + }, }, })