Skip to content

Commit

Permalink
feat(webui): restrict page streaming and file download per user
Browse files Browse the repository at this point in the history
also add the ability to edit user roles

closes gotson#146
  • Loading branch information
gotson committed Jun 10, 2020
1 parent 6291dab commit 381b196
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 16 deletions.
7 changes: 5 additions & 2 deletions komga-webui/src/components/ItemCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

<!-- FAB reading (center) -->
<v-btn
v-if="bookReady && !selected && !preselect"
v-if="bookReady && !selected && !preselect && canReadPages"
fab
x-large
color="accent"
Expand Down Expand Up @@ -144,8 +144,11 @@ export default Vue.extend({
return {}
},
computed: {
canReadPages (): boolean {
return this.$store.getters.mePageStreaming
},
overlay (): boolean {
return this.onEdit !== undefined || this.onSelected !== undefined || this.bookReady
return this.onEdit !== undefined || this.onSelected !== undefined || this.bookReady || this.canReadPages
},
computedItem (): Item<BookDto | SeriesDto> {
return createItem(this.item)
Expand Down
22 changes: 19 additions & 3 deletions komga-webui/src/components/UserAddDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,22 @@
<v-col>
<span>Roles</span>
<v-checkbox
v-model="form.admin"
v-model="form.roles"
label="Administrator"
:value="UserRoles.ADMIN"
hide-details
/>
<v-checkbox
v-model="form.roles"
label="Page Streaming"
:value="UserRoles.PAGE_STREAMING"
hide-details
/>
<v-checkbox
v-model="form.roles"
label="File Download"
:value="UserRoles.FILE_DOWNLOAD"
hide-details
/>
</v-col>
</v-row>
Expand Down Expand Up @@ -87,13 +101,15 @@
</template>

<script lang="ts">
import { UserRoles } from '@/types/enum-users'
import Vue from 'vue'
import { email, required } from 'vuelidate/lib/validators'
export default Vue.extend({
name: 'UserAddDialog',
data: () => {
return {
UserRoles,
modalAddUser: true,
showPassword: false,
snackbar: false,
Expand All @@ -103,7 +119,7 @@ export default Vue.extend({
form: {
email: '',
password: '',
admin: false,
roles: [UserRoles.PAGE_STREAMING, UserRoles.FILE_DOWNLOAD],
},
validationFieldNames: new Map([]),
}
Expand Down Expand Up @@ -149,7 +165,7 @@ export default Vue.extend({
return {
email: this.form.email,
password: this.form.password,
roles: this.form.admin ? ['ADMIN'] : [],
roles: this.form.roles,
}
}
return null
Expand Down
142 changes: 142 additions & 0 deletions komga-webui/src/components/UserEditDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<template>
<div>
<v-dialog v-model="modal"
max-width="450"
>
<v-card>
<v-card-title>Edit user</v-card-title>

<v-card-text>
<v-container fluid>
<v-row>
<v-col>
<span class="subtitle-1">Roles for {{ user.email }}</span>
</v-col>
</v-row>

<v-row>
<v-col>
<v-checkbox
v-model="roles"
label="Administrator"
:value="UserRoles.ADMIN"
hide-details
/>
<v-checkbox
v-model="roles"
label="Page Streaming"
:value="UserRoles.PAGE_STREAMING"
hide-details
/>
<v-checkbox
v-model="roles"
label="File Download"
:value="UserRoles.FILE_DOWNLOAD"
hide-details
/>
</v-col>
</v-row>

</v-container>
</v-card-text>

<v-card-actions>
<v-spacer/>
<v-btn text @click="dialogCancel">Cancel</v-btn>
<v-btn text class="primary--text"
@click="dialogConfirm"
>Save changes
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>

<v-snackbar
v-model="snackbar"
bottom
color="error"
>
{{ snackText }}
<v-btn
text
@click="snackbar = false"
>
Close
</v-btn>
</v-snackbar>
</div>
</template>

<script lang="ts">
import { UserRoles } from '@/types/enum-users'
import Vue from 'vue'
export default Vue.extend({
name: 'UserEditDialog',
data: () => {
return {
UserRoles,
snackbar: false,
snackText: '',
modal: false,
roles: [] as string[],
}
},
props: {
value: Boolean,
user: {
type: Object,
required: true,
},
},
watch: {
value (val) {
this.modal = val
},
modal (val) {
!val && this.dialogCancel()
},
user (val) {
this.dialogReset(val)
},
},
computed: {
libraries (): LibraryDto[] {
return this.$store.state.komgaLibraries.libraries
},
},
methods: {
dialogReset (user: UserDto) {
this.roles = user.roles
},
dialogCancel () {
this.$emit('input', false)
this.dialogReset(this.user)
},
dialogConfirm () {
this.editUser()
this.$emit('input', false)
this.dialogReset(this.user)
},
showSnack (message: string) {
this.snackText = message
this.snackbar = true
},
async editUser () {
try {
const roles = {
roles: this.roles,
} as RolesUpdateDto
await this.$store.dispatch('updateUserRoles', { userId: this.user.id, roles: roles })
} catch (e) {
this.showSnack(e.message)
}
},
},
})
</script>

<style scoped>
</style>
9 changes: 8 additions & 1 deletion komga-webui/src/plugins/komga-users.plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import KomgaUsersService from '@/services/komga-users.service'
import { UserRoles } from '@/types/enum-users'
import { AxiosInstance } from 'axios'
import _Vue from 'vue'
import { Module } from 'vuex/types'
Expand All @@ -11,7 +12,9 @@ const vuexModule: Module<any, any> = {
users: [] as UserWithSharedLibrariesDto[],
},
getters: {
meAdmin: state => state.me.hasOwnProperty('roles') && state.me.roles.includes('ADMIN'),
meAdmin: state => state.me.hasOwnProperty('roles') && state.me.roles.includes(UserRoles.ADMIN),
meFileDownload: state => state.me.hasOwnProperty('roles') && state.me.roles.includes(UserRoles.FILE_DOWNLOAD),
mePageStreaming: state => state.me.hasOwnProperty('roles') && state.me.roles.includes(UserRoles.PAGE_STREAMING),
authenticated: state => state.me.hasOwnProperty('id'),
},
mutations: {
Expand Down Expand Up @@ -46,6 +49,10 @@ const vuexModule: Module<any, any> = {
await service.postUser(user)
dispatch('getAllUsers')
},
async updateUserRoles ({ dispatch }, { userId, roles }: { userId: number, roles: RolesUpdateDto }) {
await service.patchUserRoles(userId, roles)
dispatch('getAllUsers')
},
async deleteUser ({ dispatch }, user: UserDto) {
await service.deleteUser(user)
dispatch('getAllUsers')
Expand Down
12 changes: 12 additions & 0 deletions komga-webui/src/services/komga-users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,18 @@ export default class KomgaUsersService {
}
}

async patchUserRoles (userId: number, roles: RolesUpdateDto): Promise<UserDto> {
try {
return (await this.http.patch(`${API_USERS}/${userId}`, roles)).data
} catch (e) {
let msg = `An error occurred while trying to patch user '${userId}'`
if (e.response.data.message) {
msg += `: ${e.response.data.message}`
}
throw new Error(msg)
}
}

async deleteUser (user: UserDto) {
try {
await this.http.delete(`${API_USERS}/${user.id}`)
Expand Down
5 changes: 5 additions & 0 deletions komga-webui/src/types/enum-users.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum UserRoles {
ADMIN = 'ADMIN',
FILE_DOWNLOAD = 'FILE_DOWNLOAD',
PAGE_STREAMING = 'PAGE_STREAMING'
}
4 changes: 4 additions & 0 deletions komga-webui/src/types/komga-users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ interface SharedLibrariesUpdateDto {
all: boolean,
libraryIds: number[]
}

interface RolesUpdateDto {
roles: string[]
}
9 changes: 8 additions & 1 deletion komga-webui/src/views/BrowseBook.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
<v-btn icon
title="Download file"
class="pb-1"
:disabled="!canDownload"
:href="fileUrl">
<v-icon>mdi-file-download</v-icon>
</v-btn>
Expand All @@ -117,7 +118,7 @@
title="Read book"
class="pb-1"
:to="{name: 'read-book', params: { bookId: bookId}}"
:disabled="book.media.status !== 'READY'"
:disabled="book.media.status !== 'READY' || !canReadPages"
>
<v-icon>mdi-book-open-page-variant</v-icon>
</v-btn>
Expand Down Expand Up @@ -216,6 +217,12 @@ export default Vue.extend({
isAdmin (): boolean {
return this.$store.getters.meAdmin
},
canReadPages (): boolean {
return this.$store.getters.mePageStreaming
},
canDownload (): boolean {
return this.$store.getters.meFileDownload
},
thumbnailUrl (): string {
return bookThumbnailUrl(this.bookId)
},
Expand Down

0 comments on commit 381b196

Please sign in to comment.