mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
add lock controls for users.
This commit is contained in:
parent
2290c4a065
commit
61fcf7f699
@ -404,7 +404,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
member(id: string) {
|
member(id: string) {
|
||||||
return this.$accessor.user.members[id]
|
return this.$accessor.user.members[id] || { id, displayname: this.$t('somebody') }
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp(time: Date) {
|
timestamp(time: Date) {
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if="!isTouch">
|
<li v-if="!isTouch && seesControl">
|
||||||
<i
|
<i
|
||||||
:class="[
|
:class="[
|
||||||
shakeKbd ? 'shake' : '',
|
!disabeld && shakeKbd ? 'shake' : '',
|
||||||
hosted && !hosting ? 'disabled' : '',
|
disabeld && !hosting ? 'disabled' : '',
|
||||||
!hosted && !hosting ? 'faded' : '',
|
!disabeld && !hosting ? 'faded' : '',
|
||||||
'fas',
|
'fas',
|
||||||
'fa-keyboard',
|
'fa-keyboard',
|
||||||
'request',
|
'request',
|
||||||
]"
|
]"
|
||||||
v-tooltip="{
|
v-tooltip="{
|
||||||
content: !hosted || hosting ? (hosting ? $t('controls.release') : $t('controls.request')) : '',
|
content: !disabeld || hosting ? (hosting ? $t('controls.release') : $t('controls.request')) : '',
|
||||||
placement: 'top',
|
placement: 'top',
|
||||||
offset: 5,
|
offset: 5,
|
||||||
boundariesElement: 'body',
|
boundariesElement: 'body',
|
||||||
@ -20,7 +20,7 @@
|
|||||||
@click.stop.prevent="toggleControl"
|
@click.stop.prevent="toggleControl"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li v-if="seesControl">
|
||||||
<label
|
<label
|
||||||
class="switch"
|
class="switch"
|
||||||
v-tooltip="{
|
v-tooltip="{
|
||||||
@ -240,7 +240,7 @@
|
|||||||
|
|
||||||
@Component({ name: 'neko-controls' })
|
@Component({ name: 'neko-controls' })
|
||||||
export default class extends Vue {
|
export default class extends Vue {
|
||||||
@Prop(Boolean) readonly shakeKbd = false
|
@Prop(Boolean) readonly shakeKbd!: boolean
|
||||||
|
|
||||||
get isTouch() {
|
get isTouch() {
|
||||||
return (
|
return (
|
||||||
@ -249,7 +249,15 @@
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
get hosted() {
|
get severLocked(): boolean {
|
||||||
|
return 'control' in this.$accessor.locked && this.$accessor.locked['control']
|
||||||
|
}
|
||||||
|
|
||||||
|
get seesControl(): boolean {
|
||||||
|
return !this.severLocked || this.$accessor.user.admin || this.hosting
|
||||||
|
}
|
||||||
|
|
||||||
|
get disabeld() {
|
||||||
return this.$accessor.remote.hosted
|
return this.$accessor.remote.hosted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,16 +7,23 @@
|
|||||||
<ul class="menu">
|
<ul class="menu">
|
||||||
<li>
|
<li>
|
||||||
<i
|
<i
|
||||||
:class="[{ disabled: !admin }, { 'fa-lock-open': !locked }, { 'fa-lock': locked }, 'fas', 'lock']"
|
:class="[{ disabled: !admin }, { locked: isLocked('control') }, 'fas', 'fa-mouse']"
|
||||||
@click="toggleLock"
|
@click="toggleLock('control')"
|
||||||
v-tooltip="{
|
v-tooltip="{
|
||||||
content: admin
|
content: lockedTooltip('control'),
|
||||||
? locked
|
placement: 'bottom',
|
||||||
? $t('room.unlock')
|
offset: 5,
|
||||||
: $t('room.lock')
|
boundariesElement: 'body',
|
||||||
: locked
|
delay: { show: 300, hide: 100 },
|
||||||
? $t('room.locked')
|
}"
|
||||||
: $t('room.unlocked'),
|
/>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<i
|
||||||
|
:class="[{ disabled: !admin }, { locked: isLocked('login') }, locked ? 'fa-lock' : 'fa-lock-open', 'fas']"
|
||||||
|
@click="toggleLock('login')"
|
||||||
|
v-tooltip="{
|
||||||
|
content: lockedTooltip('login'),
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
offset: 5,
|
offset: 5,
|
||||||
boundariesElement: 'body',
|
boundariesElement: 'body',
|
||||||
@ -90,7 +97,7 @@
|
|||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fa-lock {
|
.locked {
|
||||||
color: rgba($color: $style-error, $alpha: 0.5);
|
color: rgba($color: $style-error, $alpha: 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +145,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Ref, Watch, Vue } from 'vue-property-decorator'
|
import { Component, Ref, Watch, Vue } from 'vue-property-decorator'
|
||||||
|
import { AdminLockResource } from '~/neko/messages'
|
||||||
|
|
||||||
@Component({ name: 'neko-settings' })
|
@Component({ name: 'neko-settings' })
|
||||||
export default class extends Vue {
|
export default class extends Vue {
|
||||||
@ -167,14 +175,26 @@
|
|||||||
this.readTexts = this.texts
|
this.readTexts = this.texts
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleLock() {
|
toggleLock(resource: AdminLockResource) {
|
||||||
if (this.admin) {
|
if (!this.admin) return
|
||||||
if (this.locked) {
|
|
||||||
this.$accessor.unlock()
|
if (this.isLocked(resource)) {
|
||||||
|
this.$accessor.unlock(resource)
|
||||||
} else {
|
} else {
|
||||||
this.$accessor.lock()
|
this.$accessor.lock(resource)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isLocked(resource: AdminLockResource): boolean {
|
||||||
|
return resource in this.locked && this.locked[resource]
|
||||||
|
}
|
||||||
|
|
||||||
|
lockedTooltip(resource: AdminLockResource) {
|
||||||
|
if (this.admin) {
|
||||||
|
return this.$t(`locks.${resource}.` + (this.isLocked(resource) ? `unlock` : `lock`))
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.$t(`locks.${resource}.` + (this.isLocked(resource) ? `locked` : `unlocked`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -213,7 +213,7 @@
|
|||||||
@Ref('resolution') readonly _resolution!: any
|
@Ref('resolution') readonly _resolution!: any
|
||||||
@Ref('clipboard') readonly _clipboard!: any
|
@Ref('clipboard') readonly _clipboard!: any
|
||||||
|
|
||||||
@Prop(Boolean) readonly hideControls = false
|
@Prop(Boolean) readonly hideControls!: boolean
|
||||||
|
|
||||||
private keyboard = GuacamoleKeyboard()
|
private keyboard = GuacamoleKeyboard()
|
||||||
private observer = new ResizeObserver(this.onResise.bind(this))
|
private observer = new ResizeObserver(this.onResise.bind(this))
|
||||||
|
@ -2,6 +2,7 @@ export const logout = 'log out'
|
|||||||
export const unsupported = 'this web-browser does not support WebRTC'
|
export const unsupported = 'this web-browser does not support WebRTC'
|
||||||
export const admin_loggedin = 'You are logged in as an admin'
|
export const admin_loggedin = 'You are logged in as an admin'
|
||||||
export const you = 'You'
|
export const you = 'You'
|
||||||
|
export const somebody = 'Somebody'
|
||||||
export const send_a_message = 'Send a message'
|
export const send_a_message = 'Send a message'
|
||||||
|
|
||||||
export const side = {
|
export const side = {
|
||||||
@ -50,11 +51,23 @@ export const controls = {
|
|||||||
unlock: 'Unlock Controls',
|
unlock: 'Unlock Controls',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const room = {
|
export const locks = {
|
||||||
|
control: {
|
||||||
|
lock: 'Lock Controls (for users)',
|
||||||
|
unlock: 'Unlock Controls (for users)',
|
||||||
|
locked: 'Controls Locked (for users)',
|
||||||
|
unlocked: 'Controls Unlocked (for users)',
|
||||||
|
notif_locked: 'locked controls for users',
|
||||||
|
notif_unlocked: 'unlocked controls for users',
|
||||||
|
},
|
||||||
|
login: {
|
||||||
lock: 'Lock Room (for users)',
|
lock: 'Lock Room (for users)',
|
||||||
unlock: 'Unlock Room (for users)',
|
unlock: 'Unlock Room (for users)',
|
||||||
locked: 'Room Locked (for users)',
|
locked: 'Room Locked (for users)',
|
||||||
unlocked: 'Room Unlocked (for users)',
|
unlocked: 'Room Unlocked (for users)',
|
||||||
|
notif_locked: 'locked the room',
|
||||||
|
notif_unlocked: 'unlocked the room',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setting = {
|
export const setting = {
|
||||||
@ -94,6 +107,4 @@ export const notifications = {
|
|||||||
kicked: 'kicked {name}',
|
kicked: 'kicked {name}',
|
||||||
muted: 'muted {name}',
|
muted: 'muted {name}',
|
||||||
unmuted: 'unmuted {name}',
|
unmuted: 'unmuted {name}',
|
||||||
room_locked: 'locked the room',
|
|
||||||
room_unlocked: 'unlocked the room',
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ export const logout = 'salir'
|
|||||||
export const unsupported = 'este navegador no soporta webrtc'
|
export const unsupported = 'este navegador no soporta webrtc'
|
||||||
export const admin_loggedin = 'Registrado como admin'
|
export const admin_loggedin = 'Registrado como admin'
|
||||||
export const you = 'Tú'
|
export const you = 'Tú'
|
||||||
|
// TODO
|
||||||
|
//export const somebody = 'Somebody'
|
||||||
export const send_a_message = 'Enviar un mensaje'
|
export const send_a_message = 'Enviar un mensaje'
|
||||||
|
|
||||||
export const side = {
|
export const side = {
|
||||||
@ -51,11 +53,24 @@ export const controls = {
|
|||||||
unlock: 'Controles desbloqueados',
|
unlock: 'Controles desbloqueados',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const room = {
|
export const locks = {
|
||||||
|
// TODO
|
||||||
|
//control: {
|
||||||
|
// lock: 'Lock Controls (for users)',
|
||||||
|
// unlock: 'Unlock Controls (for users)',
|
||||||
|
// locked: 'Controls Locked (for users)',
|
||||||
|
// unlocked: 'Controls Unlocked (for users)',
|
||||||
|
// notif_locked: 'locked controls for users',
|
||||||
|
// notif_unlocked: 'unlocked controls for users',
|
||||||
|
//},
|
||||||
|
login: {
|
||||||
lock: 'Bloquear sala (para usuarios)',
|
lock: 'Bloquear sala (para usuarios)',
|
||||||
unlock: 'Desbloquear sala (para usuarios)',
|
unlock: 'Desbloquear sala (para usuarios)',
|
||||||
locked: 'Sala bloqueada (para usuarios)',
|
locked: 'Sala bloqueada (para usuarios)',
|
||||||
unlocked: 'Sala desbloqueada (para usuarios)',
|
unlocked: 'Sala desbloqueada (para usuarios)',
|
||||||
|
notif_locked: 'bloqueó la sala',
|
||||||
|
notif_unlocked: 'desbloqueó la sala',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setting = {
|
export const setting = {
|
||||||
@ -98,6 +113,4 @@ export const notifications = {
|
|||||||
kicked: '{name} expulsado',
|
kicked: '{name} expulsado',
|
||||||
muted: '{name} silenciado',
|
muted: '{name} silenciado',
|
||||||
unmuted: '{name} no silenciado',
|
unmuted: '{name} no silenciado',
|
||||||
room_locked: 'bloqueó la sala',
|
|
||||||
room_unlocked: 'desbloqueó la sala',
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ export const logout = 'Se déconnecter'
|
|||||||
export const unsupported = 'ce navigateur ne prend pas en charge WebRTC'
|
export const unsupported = 'ce navigateur ne prend pas en charge WebRTC'
|
||||||
export const admin_loggedin = "Vous êtes connecté en tant qu'admin"
|
export const admin_loggedin = "Vous êtes connecté en tant qu'admin"
|
||||||
export const you = 'Vous'
|
export const you = 'Vous'
|
||||||
|
// TODO
|
||||||
|
//export const somebody = 'Somebody'
|
||||||
export const send_a_message = 'Envoyer un message'
|
export const send_a_message = 'Envoyer un message'
|
||||||
|
|
||||||
export const side = {
|
export const side = {
|
||||||
@ -44,11 +46,24 @@ export const context = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const controls = {
|
export const locks = {
|
||||||
|
// TODO
|
||||||
|
//control: {
|
||||||
|
// lock: 'Lock Controls (for users)',
|
||||||
|
// unlock: 'Unlock Controls (for users)',
|
||||||
|
// locked: 'Controls Locked (for users)',
|
||||||
|
// unlocked: 'Controls Unlocked (for users)',
|
||||||
|
// notif_locked: 'locked controls for users',
|
||||||
|
// notif_unlocked: 'unlocked controls for users',
|
||||||
|
//},
|
||||||
|
login: {
|
||||||
release: 'Relacher le contrôle',
|
release: 'Relacher le contrôle',
|
||||||
request: 'Demander le contrôle',
|
request: 'Demander le contrôle',
|
||||||
lock: 'Vérouiller le contrôle',
|
lock: 'Vérouiller le contrôle',
|
||||||
unlock: 'Débloquer le contrôle',
|
unlock: 'Débloquer le contrôle',
|
||||||
|
notif_locked: 'a vérouillé la salle',
|
||||||
|
notif_unlocked: 'a dévérouillé la salle',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const room = {
|
export const room = {
|
||||||
@ -98,6 +113,4 @@ export const notifications = {
|
|||||||
kicked: 'a kick {name}',
|
kicked: 'a kick {name}',
|
||||||
muted: 'a mute {name}',
|
muted: 'a mute {name}',
|
||||||
unmuted: 'a démute {name}',
|
unmuted: 'a démute {name}',
|
||||||
room_locked: 'a vérouillé la salle',
|
|
||||||
room_unlocked: 'a dévérouillé la salle',
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ export const logout = 'logg ut'
|
|||||||
export const unsupported = 'Denne nettleseren støtter ikke WebRTC'
|
export const unsupported = 'Denne nettleseren støtter ikke WebRTC'
|
||||||
export const admin_loggedin = 'Du er innlogget som administrator'
|
export const admin_loggedin = 'Du er innlogget som administrator'
|
||||||
export const you = 'Deg'
|
export const you = 'Deg'
|
||||||
|
// TODO
|
||||||
|
//export const somebody = 'Somebody'
|
||||||
export const send_a_message = 'Send en melding'
|
export const send_a_message = 'Send en melding'
|
||||||
|
|
||||||
export const side = {
|
export const side = {
|
||||||
@ -51,11 +53,24 @@ export const controls = {
|
|||||||
unlock: 'Lås opp kontrollen',
|
unlock: 'Lås opp kontrollen',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const room = {
|
export const locks = {
|
||||||
|
// TODO
|
||||||
|
//control: {
|
||||||
|
// lock: 'Lock Controls (for users)',
|
||||||
|
// unlock: 'Unlock Controls (for users)',
|
||||||
|
// locked: 'Controls Locked (for users)',
|
||||||
|
// unlocked: 'Controls Unlocked (for users)',
|
||||||
|
// notif_locked: 'locked controls for users',
|
||||||
|
// notif_unlocked: 'unlocked controls for users',
|
||||||
|
//},
|
||||||
|
login: {
|
||||||
lock: 'Lås rommet (for brukere)',
|
lock: 'Lås rommet (for brukere)',
|
||||||
unlock: 'Lås opp rommet (for brukere)',
|
unlock: 'Lås opp rommet (for brukere)',
|
||||||
locked: 'Rom låst (for brukere)',
|
locked: 'Rom låst (for brukere)',
|
||||||
unlocked: 'Rom opplåst (for brukere)',
|
unlocked: 'Rom opplåst (for brukere)',
|
||||||
|
notif_locked: 'låste rommet',
|
||||||
|
notif_unlocked: 'låste opp rommet',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setting = {
|
export const setting = {
|
||||||
@ -98,6 +113,4 @@ export const notifications = {
|
|||||||
kicked: 'kastet ut {name}',
|
kicked: 'kastet ut {name}',
|
||||||
muted: 'forstummet {name}',
|
muted: 'forstummet {name}',
|
||||||
unmuted: 'opphevet forstummingen av {name}',
|
unmuted: 'opphevet forstummingen av {name}',
|
||||||
room_locked: 'låste rommet',
|
|
||||||
room_unlocked: 'låste opp rommet',
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ export const logout = 'odhlásiť sa'
|
|||||||
export const unsupported = 'tento prehliadač nepodporuje webrtc'
|
export const unsupported = 'tento prehliadač nepodporuje webrtc'
|
||||||
export const admin_loggedin = 'Ste prihlásení/á ako administrátor'
|
export const admin_loggedin = 'Ste prihlásení/á ako administrátor'
|
||||||
// export const you = '' // Incorrect in some translations! Cannot be used!
|
// export const you = '' // Incorrect in some translations! Cannot be used!
|
||||||
|
// TODO
|
||||||
|
//export const somebody = 'Somebody'
|
||||||
export const send_a_message = 'Odoslať správu'
|
export const send_a_message = 'Odoslať správu'
|
||||||
|
|
||||||
export const side = {
|
export const side = {
|
||||||
@ -51,11 +53,23 @@ export const controls = {
|
|||||||
unlock: 'Odomknúť ovládanie',
|
unlock: 'Odomknúť ovládanie',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const room = {
|
export const locks = {
|
||||||
|
control: {
|
||||||
|
lock: 'Zakázať ovládanie (pre používateľov)',
|
||||||
|
unlock: 'Povoliť ovládanie (pre používateľov)',
|
||||||
|
locked: 'Ovládanie je zakázané (pre používateľov)',
|
||||||
|
unlocked: 'Ovládanie je povolené (pre používateľov)',
|
||||||
|
notif_locked: 'zakázal/a ovládanie pre používateľov',
|
||||||
|
notif_unlocked: 'povolil/a ovládanie pre používateľov',
|
||||||
|
},
|
||||||
|
login: {
|
||||||
lock: 'Zamknúť miestnosť (pre používateľov)',
|
lock: 'Zamknúť miestnosť (pre používateľov)',
|
||||||
unlock: 'Odomknúť miestnosť (pre používateľov)',
|
unlock: 'Odomknúť miestnosť (pre používateľov)',
|
||||||
locked: 'Miestnosť je zamknutá (pre používateľov)',
|
locked: 'Miestnosť je zamknutá (pre používateľov)',
|
||||||
unlocked: 'Miestnosť odomknutá (pre používateľov)',
|
unlocked: 'Miestnosť odomknutá (pre používateľov)',
|
||||||
|
notif_locked: 'miestnosť bola zamknutá',
|
||||||
|
notif_unlocked: 'miestnosť bola odomknutá',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setting = {
|
export const setting = {
|
||||||
@ -95,6 +109,4 @@ export const notifications = {
|
|||||||
kicked: '{name} bol/a vykopnutý/a',
|
kicked: '{name} bol/a vykopnutý/a',
|
||||||
muted: 'zakázal chat používateľovi {name}',
|
muted: 'zakázal chat používateľovi {name}',
|
||||||
unmuted: 'povolil chat používateľovi {name}',
|
unmuted: 'povolil chat používateľovi {name}',
|
||||||
room_locked: 'miestnosť bola zamknutá',
|
|
||||||
room_unlocked: 'miestnosť bola odomknutá',
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ export const logout = 'logga ut'
|
|||||||
export const unsupported = 'denna webbläsare har inte stöd för webrtc'
|
export const unsupported = 'denna webbläsare har inte stöd för webrtc'
|
||||||
export const admin_loggedin = 'Du är inloggad som en administratör'
|
export const admin_loggedin = 'Du är inloggad som en administratör'
|
||||||
export const you = 'Du'
|
export const you = 'Du'
|
||||||
|
// TODO
|
||||||
|
//export const somebody = 'Somebody'
|
||||||
export const send_a_message = 'Skicka ett meddelande'
|
export const send_a_message = 'Skicka ett meddelande'
|
||||||
|
|
||||||
export const side = {
|
export const side = {
|
||||||
@ -51,11 +53,24 @@ export const controls = {
|
|||||||
unlock: 'Lås upp kontrollen',
|
unlock: 'Lås upp kontrollen',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const room = {
|
export const locks = {
|
||||||
|
// TODO
|
||||||
|
//control: {
|
||||||
|
// lock: 'Lock Controls (for users)',
|
||||||
|
// unlock: 'Unlock Controls (for users)',
|
||||||
|
// locked: 'Controls Locked (for users)',
|
||||||
|
// unlocked: 'Controls Unlocked (for users)',
|
||||||
|
// notif_locked: 'locked controls for users',
|
||||||
|
// notif_unlocked: 'unlocked controls for users',
|
||||||
|
//},
|
||||||
|
login: {
|
||||||
lock: 'Lås rum (för användare)',
|
lock: 'Lås rum (för användare)',
|
||||||
unlock: 'Lås upp rummet (för användare)',
|
unlock: 'Lås upp rummet (för användare)',
|
||||||
locked: 'Rum låst (för användare)',
|
locked: 'Rum låst (för användare)',
|
||||||
unlocked: 'Rum upplåst (för användare)',
|
unlocked: 'Rum upplåst (för användare)',
|
||||||
|
notif_locked: 'låste rummet',
|
||||||
|
notif_unlocked: 'låste upp rummet',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setting = {
|
export const setting = {
|
||||||
@ -98,6 +113,4 @@ export const notifications = {
|
|||||||
kicked: 'sparkade {name}',
|
kicked: 'sparkade {name}',
|
||||||
muted: 'tystade {name}',
|
muted: 'tystade {name}',
|
||||||
unmuted: 'tog bort tystningen på {name}',
|
unmuted: 'tog bort tystningen på {name}',
|
||||||
room_locked: 'låste rummet',
|
|
||||||
room_unlocked: 'låste upp rummet',
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import {
|
|||||||
BroadcastStatusPayload,
|
BroadcastStatusPayload,
|
||||||
AdminPayload,
|
AdminPayload,
|
||||||
AdminTargetPayload,
|
AdminTargetPayload,
|
||||||
|
AdminLockMessage,
|
||||||
} from './messages'
|
} from './messages'
|
||||||
|
|
||||||
interface NekoEvents extends BaseEvents {}
|
interface NekoEvents extends BaseEvents {}
|
||||||
@ -461,21 +462,23 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
protected [EVENT.ADMIN.LOCK]({ id }: AdminPayload) {
|
protected [EVENT.ADMIN.LOCK]({ id, resource }: AdminLockMessage) {
|
||||||
this.$accessor.setLocked(true)
|
this.$accessor.setLocked(resource)
|
||||||
|
|
||||||
this.$accessor.chat.newMessage({
|
this.$accessor.chat.newMessage({
|
||||||
id,
|
id,
|
||||||
content: this.$vue.$t('notifications.room_locked') as string,
|
content: this.$vue.$t(`locks.${resource}.notif_locked`) as string,
|
||||||
type: 'event',
|
type: 'event',
|
||||||
created: new Date(),
|
created: new Date(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
protected [EVENT.ADMIN.UNLOCK]({ id }: AdminPayload) {
|
protected [EVENT.ADMIN.UNLOCK]({ id, resource }: AdminLockMessage) {
|
||||||
this.$accessor.setLocked(false)
|
this.$accessor.setUnlocked(resource)
|
||||||
|
|
||||||
this.$accessor.chat.newMessage({
|
this.$accessor.chat.newMessage({
|
||||||
id,
|
id,
|
||||||
content: this.$vue.$t('notifications.room_unlocked') as string,
|
content: this.$vue.$t(`locks.${resource}.notif_unlocked`) as string,
|
||||||
type: 'event',
|
type: 'event',
|
||||||
created: new Date(),
|
created: new Date(),
|
||||||
})
|
})
|
||||||
|
@ -39,6 +39,7 @@ export type WebSocketPayloads =
|
|||||||
| ScreenResolutionPayload
|
| ScreenResolutionPayload
|
||||||
| ScreenConfigurationsPayload
|
| ScreenConfigurationsPayload
|
||||||
| AdminPayload
|
| AdminPayload
|
||||||
|
| AdminLockPayload
|
||||||
| BroadcastStatusPayload
|
| BroadcastStatusPayload
|
||||||
| BroadcastCreatePayload
|
| BroadcastCreatePayload
|
||||||
|
|
||||||
@ -222,3 +223,14 @@ export interface AdminTargetPayload {
|
|||||||
id: string
|
id: string
|
||||||
target?: string
|
target?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AdminLockMessage extends WebSocketMessage, AdminLockPayload {
|
||||||
|
event: AdminEvents
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AdminLockResource = 'login' | 'control'
|
||||||
|
|
||||||
|
export interface AdminLockPayload {
|
||||||
|
resource: AdminLockResource
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ import Vue from 'vue'
|
|||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import { useAccessor, mutationTree, actionTree } from 'typed-vuex'
|
import { useAccessor, mutationTree, actionTree } from 'typed-vuex'
|
||||||
import { EVENT } from '~/neko/events'
|
import { EVENT } from '~/neko/events'
|
||||||
|
import { AdminLockResource } from '~/neko/messages'
|
||||||
import { get, set } from '~/utils/localstorage'
|
import { get, set } from '~/utils/localstorage'
|
||||||
|
|
||||||
import * as video from './video'
|
import * as video from './video'
|
||||||
@ -18,7 +19,7 @@ export const state = () => ({
|
|||||||
active: false,
|
active: false,
|
||||||
connecting: false,
|
connecting: false,
|
||||||
connected: false,
|
connected: false,
|
||||||
locked: false,
|
locked: {} as Record<string, boolean>,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const mutations = mutationTree(state, {
|
export const mutations = mutationTree(state, {
|
||||||
@ -31,8 +32,12 @@ export const mutations = mutationTree(state, {
|
|||||||
state.password = password
|
state.password = password
|
||||||
},
|
},
|
||||||
|
|
||||||
setLocked(state, locked: boolean) {
|
setLocked(state, resource: string) {
|
||||||
state.locked = locked
|
Vue.set(state.locked, resource, true)
|
||||||
|
},
|
||||||
|
|
||||||
|
setUnlocked(state, resource: string) {
|
||||||
|
Vue.set(state.locked, resource, false)
|
||||||
},
|
},
|
||||||
|
|
||||||
setConnnecting(state) {
|
setConnnecting(state) {
|
||||||
@ -58,20 +63,20 @@ export const actions = actionTree(
|
|||||||
accessor.settings.initialise()
|
accessor.settings.initialise()
|
||||||
},
|
},
|
||||||
|
|
||||||
lock() {
|
lock(_, resource: AdminLockResource) {
|
||||||
if (!accessor.connected || !accessor.user.admin) {
|
if (!accessor.connected || !accessor.user.admin) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$client.sendMessage(EVENT.ADMIN.LOCK)
|
$client.sendMessage(EVENT.ADMIN.LOCK, { resource })
|
||||||
},
|
},
|
||||||
|
|
||||||
unlock() {
|
unlock(_, resource: AdminLockResource) {
|
||||||
if (!accessor.connected || !accessor.user.admin) {
|
if (!accessor.connected || !accessor.user.admin) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$client.sendMessage(EVENT.ADMIN.UNLOCK)
|
$client.sendMessage(EVENT.ADMIN.UNLOCK, { resource })
|
||||||
},
|
},
|
||||||
|
|
||||||
login({ state }, { displayname, password }: { displayname: string; password: string }) {
|
login({ state }, { displayname, password }: { displayname: string; password: string }) {
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
## master branch
|
## master branch
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
- Lock controls for users, globally.
|
||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
- ARM-based images not bound to Raspberry Pi only.
|
- ARM-based images not bound to Raspberry Pi only.
|
||||||
- Add japanese characters support.
|
- Add japanese characters support.
|
||||||
|
@ -106,6 +106,12 @@ type AdminTarget struct {
|
|||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AdminLock struct {
|
||||||
|
Event string `json:"event"`
|
||||||
|
Resource string `json:"resource"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
type ScreenResolution struct {
|
type ScreenResolution struct {
|
||||||
Event string `json:"event"`
|
Event string `json:"event"`
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
|
@ -8,23 +8,30 @@ import (
|
|||||||
"m1k1o/neko/internal/types/message"
|
"m1k1o/neko/internal/types/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *MessageHandler) adminLock(id string, session types.Session) error {
|
func (h *MessageHandler) adminLock(id string, session types.Session, payload *message.AdminLock) error {
|
||||||
if !session.Admin() {
|
if !session.Admin() {
|
||||||
h.logger.Debug().Msg("user not admin")
|
h.logger.Debug().Msg("user not admin")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.locked {
|
_, ok := h.locked[payload.Resource]
|
||||||
h.logger.Debug().Msg("server already locked...")
|
if ok {
|
||||||
|
h.logger.Debug().Str("resource", payload.Resource).Msg("resource already locked...")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
h.locked = true
|
if payload.Resource != "login" && payload.Resource != "control" {
|
||||||
|
h.logger.Debug().Msg("unknown lock resource")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
h.locked[payload.Resource] = id
|
||||||
|
|
||||||
if err := h.sessions.Broadcast(
|
if err := h.sessions.Broadcast(
|
||||||
message.Admin{
|
message.AdminLock{
|
||||||
Event: event.ADMIN_LOCK,
|
Event: event.ADMIN_LOCK,
|
||||||
ID: id,
|
ID: id,
|
||||||
|
Resource: payload.Resource,
|
||||||
}, nil); err != nil {
|
}, nil); err != nil {
|
||||||
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.ADMIN_LOCK)
|
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.ADMIN_LOCK)
|
||||||
return err
|
return err
|
||||||
@ -33,23 +40,25 @@ func (h *MessageHandler) adminLock(id string, session types.Session) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *MessageHandler) adminUnlock(id string, session types.Session) error {
|
func (h *MessageHandler) adminUnlock(id string, session types.Session, payload *message.AdminLock) error {
|
||||||
if !session.Admin() {
|
if !session.Admin() {
|
||||||
h.logger.Debug().Msg("user not admin")
|
h.logger.Debug().Msg("user not admin")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !h.locked {
|
_, ok := h.locked[payload.Resource]
|
||||||
h.logger.Debug().Msg("server not locked...")
|
if !ok {
|
||||||
|
h.logger.Debug().Str("resource", payload.Resource).Msg("resource not locked...")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
h.locked = false
|
delete(h.locked, payload.Resource)
|
||||||
|
|
||||||
if err := h.sessions.Broadcast(
|
if err := h.sessions.Broadcast(
|
||||||
message.Admin{
|
message.AdminLock{
|
||||||
Event: event.ADMIN_UNLOCK,
|
Event: event.ADMIN_UNLOCK,
|
||||||
ID: id,
|
ID: id,
|
||||||
|
Resource: payload.Resource,
|
||||||
}, nil); err != nil {
|
}, nil); err != nil {
|
||||||
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.ADMIN_UNLOCK)
|
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.ADMIN_UNLOCK)
|
||||||
return err
|
return err
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (h *MessageHandler) controlRelease(id string, session types.Session) error {
|
func (h *MessageHandler) controlRelease(id string, session types.Session) error {
|
||||||
|
|
||||||
// check if session is host
|
// check if session is host
|
||||||
if !h.sessions.IsHost(id) {
|
if !h.sessions.IsHost(id) {
|
||||||
h.logger.Debug().Str("id", id).Msg("is not the host")
|
h.logger.Debug().Str("id", id).Msg("is not the host")
|
||||||
@ -34,6 +33,13 @@ func (h *MessageHandler) controlRelease(id string, session types.Session) error
|
|||||||
func (h *MessageHandler) controlRequest(id string, session types.Session) error {
|
func (h *MessageHandler) controlRequest(id string, session types.Session) error {
|
||||||
// check for host
|
// check for host
|
||||||
if !h.sessions.HasHost() {
|
if !h.sessions.HasHost() {
|
||||||
|
// check if control is locked or user is admin
|
||||||
|
_, ok := h.locked["control"]
|
||||||
|
if ok && !session.Admin() {
|
||||||
|
h.logger.Debug().Msg("control is locked")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// set host
|
// set host
|
||||||
err := h.sessions.SetHost(id)
|
err := h.sessions.SetHost(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -91,6 +97,13 @@ func (h *MessageHandler) controlGive(id string, session types.Session, payload *
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if control is locked or giver is admin
|
||||||
|
_, ok := h.locked["control"]
|
||||||
|
if ok && !session.Admin() {
|
||||||
|
h.logger.Debug().Msg("control is locked")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// set host
|
// set host
|
||||||
err := h.sessions.SetHost(payload.ID)
|
err := h.sessions.SetHost(payload.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -19,7 +19,7 @@ type MessageHandler struct {
|
|||||||
remote types.RemoteManager
|
remote types.RemoteManager
|
||||||
broadcast types.BroadcastManager
|
broadcast types.BroadcastManager
|
||||||
banned map[string]bool
|
banned map[string]bool
|
||||||
locked bool
|
locked map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *MessageHandler) Connected(admin bool, socket *WebSocket) (bool, string, error) {
|
func (h *MessageHandler) Connected(admin bool, socket *WebSocket) (bool, string, error) {
|
||||||
@ -34,7 +34,8 @@ func (h *MessageHandler) Connected(admin bool, socket *WebSocket) (bool, string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.locked && !admin {
|
_, ok := h.locked["login"]
|
||||||
|
if ok && !admin {
|
||||||
h.logger.Debug().Msg("server locked")
|
h.logger.Debug().Msg("server locked")
|
||||||
return false, "locked", nil
|
return false, "locked", nil
|
||||||
}
|
}
|
||||||
@ -128,9 +129,17 @@ func (h *MessageHandler) Message(id string, raw []byte) error {
|
|||||||
|
|
||||||
// Admin Events
|
// Admin Events
|
||||||
case event.ADMIN_LOCK:
|
case event.ADMIN_LOCK:
|
||||||
return errors.Wrapf(h.adminLock(id, session), "%s failed", header.Event)
|
payload := &message.AdminLock{}
|
||||||
|
return errors.Wrapf(
|
||||||
|
utils.Unmarshal(payload, raw, func() error {
|
||||||
|
return h.adminLock(id, session, payload)
|
||||||
|
}), "%s failed", header.Event)
|
||||||
case event.ADMIN_UNLOCK:
|
case event.ADMIN_UNLOCK:
|
||||||
return errors.Wrapf(h.adminUnlock(id, session), "%s failed", header.Event)
|
payload := &message.AdminLock{}
|
||||||
|
return errors.Wrapf(
|
||||||
|
utils.Unmarshal(payload, raw, func() error {
|
||||||
|
return h.adminUnlock(id, session, payload)
|
||||||
|
}), "%s failed", header.Event)
|
||||||
case event.ADMIN_CONTROL:
|
case event.ADMIN_CONTROL:
|
||||||
return errors.Wrapf(h.adminControl(id, session), "%s failed", header.Event)
|
return errors.Wrapf(h.adminControl(id, session), "%s failed", header.Event)
|
||||||
case event.ADMIN_RELEASE:
|
case event.ADMIN_RELEASE:
|
||||||
|
@ -12,6 +12,18 @@ func (h *MessageHandler) SessionCreated(id string, session types.Session) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// notify all about what is locked
|
||||||
|
for resource, id := range h.locked {
|
||||||
|
if err := session.Send(message.AdminLock{
|
||||||
|
Event: event.ADMIN_LOCK,
|
||||||
|
ID: id,
|
||||||
|
Resource: resource,
|
||||||
|
}); err != nil {
|
||||||
|
h.logger.Warn().Str("id", id).Err(err).Msgf("sending event %s has failed", event.ADMIN_LOCK)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if session.Admin() {
|
if session.Admin() {
|
||||||
// send screen configurations if admin
|
// send screen configurations if admin
|
||||||
if err := h.screenConfigurations(id, session); err != nil {
|
if err := h.screenConfigurations(id, session); err != nil {
|
||||||
@ -22,17 +34,6 @@ func (h *MessageHandler) SessionCreated(id string, session types.Session) error
|
|||||||
if err := h.boradcastStatus(session); err != nil {
|
if err := h.boradcastStatus(session); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// if locked, notify admin about that
|
|
||||||
if h.locked {
|
|
||||||
if err := session.Send(message.Admin{
|
|
||||||
Event: event.ADMIN_LOCK,
|
|
||||||
ID: id,
|
|
||||||
}); err != nil {
|
|
||||||
h.logger.Warn().Str("id", id).Err(err).Msgf("sending event %s has failed", event.ADMIN_LOCK)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -39,7 +39,7 @@ func New(sessions types.SessionManager, remote types.RemoteManager, broadcast ty
|
|||||||
sessions: sessions,
|
sessions: sessions,
|
||||||
webrtc: webrtc,
|
webrtc: webrtc,
|
||||||
banned: make(map[string]bool),
|
banned: make(map[string]bool),
|
||||||
locked: false,
|
locked: make(map[string]string),
|
||||||
},
|
},
|
||||||
conns: 0,
|
conns: 0,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user