Merge branch 'prod' into develop

This commit is contained in:
Settel 2023-02-02 15:01:16 +01:00
commit 1876484590
101 changed files with 223 additions and 281 deletions

View File

@ -0,0 +1,33 @@
<template>
<div class="copyright-notice__version" @click="openInfoModal">
v{{ config.version }}, © 2021-2023, Settel
</div>
<InfoModal v-if="showInfoModal" @close="closeInfoModal" />
</template>
<script setup lang="ts">
import { useRuntimeConfig } from '#app'
import { ref } from 'vue'
const config = useRuntimeConfig()
const showInfoModal = ref(false)
const openInfoModal = () => { showInfoModal.value = true }
const closeInfoModal = () => { showInfoModal.value = false }
</script>
<style lang="scss">
.copyright-notice {
&__version {
position: absolute;
right: 1em;
bottom: 0;
color: #606060;
cursor: pointer;
&:hover {
color: #c0c0c0;
}
}
}
</style>

View File

@ -22,7 +22,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, watch } from 'vue' import { onMounted, ref } from 'vue'
import { PlayerEdit } from '@/composables/engine.d' import { PlayerEdit } from '@/composables/engine.d'
import type { Button } from '@/components/admin/PlayerModal' import type { Button } from '@/components/admin/PlayerModal'

View File

@ -6,7 +6,7 @@ import { useRoundStore } from '@/stores/RoundStore'
import useI18n from './useI18n' import useI18n from './useI18n'
import { $fetch } from 'ohmyfetch' import { $fetch } from 'ohmyfetch'
export type AllowRole = '' | 'player' | 'gamemaster' | 'admin' export type AllowRole = '' | 'player' | 'gamemaster' | 'admin' | 'setup'
export type AllowRoles = Array<AllowRole> export type AllowRoles = Array<AllowRole>
export interface useAuth { export interface useAuth {
@ -25,8 +25,17 @@ export default (): useAuth => {
user.setUserInfo(userInfo) user.setUserInfo(userInfo)
useI18n({}).setLang(userInfo.lang) useI18n({}).setLang(userInfo.lang)
if (allowRoles.indexOf(userInfo.role) >= 0 ) { if (allowRoles.indexOf(userInfo.role) >= 0 ) {
// user is authenticated and authorized, let the user in
return return
} }
// game is not initialized yet, needs setup
if (userInfo.role === 'setup') {
document.location.pathname = '/setup'
return
}
// user is authenticated but not authorized for this page
if (user.isAdmin) { if (user.isAdmin) {
document.location.pathname = '/admin' document.location.pathname = '/admin'
// can't use navigateTo() for it fails with DOMException if two consecutive redirects happen (at least in docker container) // can't use navigateTo() for it fails with DOMException if two consecutive redirects happen (at least in docker container)
@ -35,6 +44,7 @@ export default (): useAuth => {
document.location.pathname = '/play' document.location.pathname = '/play'
} }
} catch (e) { } catch (e) {
// user is not authenticated
if (allowRoles.indexOf('') == -1 ) { if (allowRoles.indexOf('') == -1 ) {
document.location.pathname = '/' document.location.pathname = '/'
} }

View File

@ -12,34 +12,26 @@
</div> </div>
<div class="page-index__space" /> <div class="page-index__space" />
</div> </div>
<div class="page-index__copyright-notice" @click="openInfoModal"> <CopyrightNotice />
v{{ config.version }}, © 2021-2022, Settel
</div>
<InfoModal v-if="showInfoModal" @close="closeInfoModal" />
<CreateTeamDialog v-if="showCreateTeamDialog" @close="closeCreateTeamDialog" /> <CreateTeamDialog v-if="showCreateTeamDialog" @close="closeCreateTeamDialog" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useRuntimeConfig, navigateTo } from '#app'
import { ref } from 'vue' import { ref } from 'vue'
import useAuth from '@/composables/useAuth' import useAuth from '@/composables/useAuth'
import useI18n from '@/composables/useI18n' import useI18n from '@/composables/useI18n'
import CopyrightNotice from '../components/CopyrightNotice.vue';
const { $t } = useI18n({ const { $t } = useI18n({
'create-team': { en: 'Create Team ...', de: 'Team erstellen ...' }, 'create-team': { en: 'Create Team ...', de: 'Team erstellen ...' },
}) })
const config = useRuntimeConfig()
await useAuth().authenticateAndLoadUserInfo(['']) await useAuth().authenticateAndLoadUserInfo([''])
const showCreateTeamDialog = ref(false) const showCreateTeamDialog = ref(false)
const showInfoModal = ref(false)
const createTeam = () => { showCreateTeamDialog.value = true } const createTeam = () => { showCreateTeamDialog.value = true }
const closeCreateTeamDialog = () => { showCreateTeamDialog.value = false } const closeCreateTeamDialog = () => { showCreateTeamDialog.value = false }
const openInfoModal = () => { showInfoModal.value = true }
const closeInfoModal = () => { showInfoModal.value = false }
</script> </script>
<style lang="scss"> <style lang="scss">
@ -92,17 +84,5 @@ body {
&__space { &__space {
flex-grow: 1; flex-grow: 1;
} }
&__copyright-notice {
position: absolute;
right: 1em;
bottom: 0;
color: #606060;
cursor: pointer;
&:hover {
color: #c0c0c0;
}
}
} }
</style> </style>

View File

@ -0,0 +1,79 @@
<template>
<div>
<TitleBox />
<div class="page-setup__action-box">
<div class="page-setup__description">
<p>{{ $t('description-1') }}</p>
<p>{{ $t('description-2') }}</p>
</div>
<div class="page-setup__button">
<Button @click="createAdminAccount">{{ $t('create admin user') }}</Button>
<ModalDialog v-if="showAdminAccountCreatedDialog" :no-close-button="true" @close="showAdminAccountCreatedDialog = false">
<div class="create-team-dialog__auth-message">{{ $t('pin') }}</div>
<div class="create-team-dialog__pin">{{ authcode }}</div>
<div class="create-team-dialog__auth-message">{{ $t('remember-and-log-in') }}</div>
</ModalDialog>
</div>
</div>
<CopyrightNotice />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import useAuth from '@/composables/useAuth'
import useI18n from '@/composables/useI18n'
const { $t } = useI18n({
'create admin user': { en: 'create admin user', de: 'Admin-Benutzer anlegen' },
'description-1': {
en: 'Congratulation!',
de: 'Herzlichen Glückwunsch! '
},
'description-2': {
en: 'You\'ve successfully installed Know Your Teammates.',
de: 'Know Your Teammates wurde erfolgreich installiert.'
},
})
await useAuth().authenticateAndLoadUserInfo(['setup'])
const showAdminAccountCreatedDialog = ref(false)
const authcode = ref('000000')
const createAdminAccount = () => {
authcode.value = ''
for (var i = 0; i < 6; i++) {
authcode.value += '' + Math.floor(Math.floor(Math.random() * 10000) / 100) % 10
}
showAdminAccountCreatedDialog.value = true
}
</script>
<style lang="scss">
@import '~/assets/css/components';
.page-setup {
&__action-box {
display: flex;
flex-direction: column;
width: 340px;
margin: 0 auto;
@media (max-width: $phone-max-width) {
margin: 32px 0 0 0;
}
}
&__description {
font-size: 24px;
color: #ffffff;
text-align: center;
}
&__button {
display: flex;
margin: 32px auto;
}
}
</style>

View File

@ -3,7 +3,7 @@ import { defineStore } from 'pinia'
export type Userinfo = { export type Userinfo = {
id: string id: string
name: string name: string
role: '' | 'player' | 'gamemaster' | 'admin' role: '' | 'player' | 'gamemaster' | 'admin' | 'setup'
game: string game: string
lang: 'de' | 'en' lang: 'de' | 'en'
isCameo: string isCameo: string

View File

@ -1 +0,0 @@
{"name":"Massive Demo","lang":"de","created":1651603106}

View File

@ -1,4 +0,0 @@
{
"quote": "12.2",
"source": "9c5a22d3-1e82-4bad-95a4-c9efb169ede0"
}

View File

@ -1,4 +0,0 @@
{
"quote": "1.1",
"source": "4b1c22b8-6fa1-4c9d-98d7-cbf498035074"
}

View File

@ -1,4 +0,0 @@
{
"quote": "11.2",
"source": "cede08c4-768a-4792-b92f-8df162a07307"
}

View File

@ -1,4 +0,0 @@
{
"quote": "4.1",
"source": "b190ebb1-86c0-4308-a6b6-bf34237c10f8"
}

View File

@ -1,4 +0,0 @@
{
"quote": "Admin #1",
"source": "f30802dc-1c18-4169-99fe-04d1d8e7bd9e"
}

View File

@ -1,4 +0,0 @@
{
"quote": "7.2",
"source": "3945635e-c65a-4fb7-a46c-675ec53abebe"
}

View File

@ -1,4 +0,0 @@
{
"quote": "16.1",
"source": "49295e5b-0d0a-44ea-9bff-e74acaaa6dcf"
}

View File

@ -1,4 +0,0 @@
{
"quote": "3.2",
"source": "4fa78612-accd-491d-93e6-cca251ac0e5a"
}

View File

@ -1,4 +0,0 @@
{
"quote": "5.1",
"source": "3c60f533-676b-4464-8542-1f3e6fc49d13"
}

View File

@ -1,4 +0,0 @@
{
"quote": "Admin #2",
"source": "f30802dc-1c18-4169-99fe-04d1d8e7bd9e"
}

View File

@ -1,4 +0,0 @@
{
"quote": "2.2",
"source": "da6fdb50-8773-40ce-889f-c6f565ca35e3"
}

View File

@ -1,4 +0,0 @@
{
"quote": "6.1",
"source": "38f508e0-b808-4d28-be5b-d2f5cb54fd69"
}

View File

@ -1,4 +0,0 @@
{
"quote": "4.2",
"source": "b190ebb1-86c0-4308-a6b6-bf34237c10f8"
}

View File

@ -1,4 +0,0 @@
{
"quote": "13.1",
"source": "233dd18b-cb0d-4f77-b0ee-248dc7fec65d"
}

View File

@ -1,4 +0,0 @@
{
"quote": "9.2",
"source": "f99ee1de-af5c-4d7e-a1f4-622ad0cd40ac"
}

View File

@ -1,4 +0,0 @@
{
"quote": "12.1",
"source": "9c5a22d3-1e82-4bad-95a4-c9efb169ede0"
}

View File

@ -1,4 +0,0 @@
{
"quote": "5.2",
"source": "3c60f533-676b-4464-8542-1f3e6fc49d13"
}

View File

@ -1,4 +0,0 @@
{
"quote": "9.1",
"source": "f99ee1de-af5c-4d7e-a1f4-622ad0cd40ac"
}

View File

@ -1,4 +0,0 @@
{
"quote": "8.2",
"source": "81cf1907-8566-4b03-a433-3f6ea9bf8c85"
}

View File

@ -1,4 +0,0 @@
{
"quote": "15.1",
"source": "4706f51a-c014-4e0a-99f7-866e98b19986"
}

View File

@ -1,4 +0,0 @@
{
"quote": "1.2",
"source": "4b1c22b8-6fa1-4c9d-98d7-cbf498035074"
}

View File

@ -1,4 +0,0 @@
{
"quote": "11.1",
"source": "cede08c4-768a-4792-b92f-8df162a07307"
}

View File

@ -1,4 +0,0 @@
{
"quote": "10.2",
"source": "8f688b3b-6e2f-4bf2-bdfa-03762f2c7b72"
}

View File

@ -1,4 +0,0 @@
{
"quote": "6.2",
"source": "38f508e0-b808-4d28-be5b-d2f5cb54fd69"
}

View File

@ -1,4 +0,0 @@
{
"quote": "13.2",
"source": "233dd18b-cb0d-4f77-b0ee-248dc7fec65d"
}

View File

@ -1,4 +0,0 @@
{
"quote": "8.1",
"source": "81cf1907-8566-4b03-a433-3f6ea9bf8c85"
}

View File

@ -1,4 +0,0 @@
{
"quote": "10.1",
"source": "8f688b3b-6e2f-4bf2-bdfa-03762f2c7b72"
}

View File

@ -1,4 +0,0 @@
{
"quote": "16.2",
"source": "49295e5b-0d0a-44ea-9bff-e74acaaa6dcf"
}

View File

@ -1,4 +0,0 @@
{
"quote": "14.2",
"source": "51c4c7cb-8382-4bef-ad2d-c457c5af12f2"
}

View File

@ -1,4 +0,0 @@
{
"quote": "2.1",
"source": "da6fdb50-8773-40ce-889f-c6f565ca35e3"
}

View File

@ -1,4 +0,0 @@
{
"quote": "14.1",
"source": "51c4c7cb-8382-4bef-ad2d-c457c5af12f2"
}

View File

@ -1,4 +0,0 @@
{
"quote": "3.1",
"source": "4fa78612-accd-491d-93e6-cca251ac0e5a"
}

View File

@ -1,4 +0,0 @@
{
"quote": "7.1",
"source": "3945635e-c65a-4fb7-a46c-675ec53abebe"
}

View File

@ -1,4 +0,0 @@
{
"quote": "15.2",
"source": "4706f51a-c014-4e0a-99f7-866e98b19986"
}

View File

@ -1 +0,0 @@
{"name":"Bumsquatsch","lang":"de","created":1670881903}

View File

@ -1,5 +0,0 @@
{
"quote": "Extra Bumsquatsch vom Oberadmin",
"source": "6ef8620b-2b5e-4749-821e-b0722b8d8117",
"created": 1670882004
}

View File

@ -1,5 +0,0 @@
{
"quote": "Bumsquatsch #2",
"source": "c5e0cbf4-1556-4488-93de-9367f84e5ce8",
"created": 1670881947
}

View File

@ -1,5 +0,0 @@
{
"quote": "Bumsquatsch #1",
"source": "c5e0cbf4-1556-4488-93de-9367f84e5ce8",
"created": 1670881943
}

View File

@ -1 +0,0 @@
{"name":"Team Hogwards","lang":"en","created":1650831066}

View File

@ -1,4 +0,0 @@
{
"quote": "I'm friends with spiders.",
"source": "23c93faa-ac5b-4e37-bf32-4276aba682bb"
}

View File

@ -1,4 +0,0 @@
{
"quote": "My first magic wand - an exclusive model from designer Thoronus Karpes — was a gift from my father.",
"source": "15c03b7c-729f-4202-a880-3bcc7214dad9"
}

View File

@ -1,4 +0,0 @@
{
"quote": "My stupid brothers frequently test their latest invention on me.",
"source": "bff68447-513c-4fa3-9224-fc59d83da81a"
}

View File

@ -1,4 +0,0 @@
{
"quote": "Since first grade, I've been best in all subjects and courses without a single miss.",
"source": "99e1aa2e-6e37-43c7-809c-28f093e2ae81"
}

View File

@ -1,4 +0,0 @@
{
"quote": "My private collection has 4031 different potions.",
"source": "35ee06ca-82c7-4f23-9bb9-bd0943848b07"
}

View File

@ -1 +0,0 @@
{"name":"Team Hogwards","lang":"de","created":1649841591}

View File

@ -1,4 +0,0 @@
{
"quote": "Ich bin seit der ersten Klasse in allen Fächern Klassenbeste:r.",
"source": "de69fa89-2b55-4c78-8718-9084458ceada"
}

View File

@ -1,4 +0,0 @@
{
"quote": "Meine Privatsammlung umfasst 4031 verschiedene Zaubertränke.",
"source": "c885c77f-bbc8-4547-a3b4-baac5a58e76e"
}

View File

@ -1,4 +0,0 @@
{
"quote": "Meinen ersten Zauberstab — ein exklusives Modell von Edeldesigner Thoronus Karpes — hat mir mein Vater geschenkt.",
"source": "cf230e60-9e1e-4158-93eb-ca184e15a6af"
}

View File

@ -1,4 +0,0 @@
{
"quote": "Ich bin mit Spinnen befreundet.",
"source": "47ff4d04-b403-468f-b152-72226762e373"
}

View File

@ -1,4 +0,0 @@
{
"quote": "Meine blöden Brüder testen ständig ihre neusten Erfindungen an mir.",
"source": "fae6e837-d603-436d-ba0c-df6a850350c0"
}

View File

@ -1 +0,0 @@
{"authcode":"","name":"Draco","role":"player","game":"663576f0-1378-496b-a970-578bdcb222af","created":1650831166,"lastLoggedIn":0}

View File

@ -1 +0,0 @@
{"authcode":"805088","name":"Player #13","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603645,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"","name":"Hagrid","role":"player","game":"663576f0-1378-496b-a970-578bdcb222af","created":1650831162,"lastLoggedIn":0}

View File

@ -1 +0,0 @@
{"authcode":"","name":"Snape","role":"player","game":"663576f0-1378-496b-a970-578bdcb222af","created":1650831158,"lastLoggedIn":0}

View File

@ -1 +0,0 @@
{"authcode":"406234","name":"Player #06","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603311,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"098577","name":"Player #07","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603340,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"044843","name":"Player #05","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603278,"lastLoggedIn":1651603989}

View File

@ -1,5 +0,0 @@
{
"authcode": "646162",
"name": "Settel (Admin)",
"role": "admin"
}

View File

@ -1 +0,0 @@
{"authcode":"606242","name":"Player #15","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603679,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"","name":"Hagrid","role":"player","game":"e24444aa-8a18-48aa-a36d-8f84620726f8","created":1649841804}

View File

@ -1 +0,0 @@
{"authcode":"920510","name":"Player #16","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603703,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"350736","name":"Player #01","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603175,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"160658","name":"Player #03","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603237,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"529733","name":"Player #14","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603656,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"171903","name":"Admin von Bumsquatsch","role":"gamemaster","game":"652e36de-99c4-4365-b557-8fd189a396ab","created":1670881903,"lastLoggedIn":1670881992}

View File

@ -1 +0,0 @@
{"authcode":"776678","name":"Player #08","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603395,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"837254","name":"Player #10","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603471,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"","name":"Hermine","role":"player","game":"663576f0-1378-496b-a970-578bdcb222af","created":1650831149,"lastLoggedIn":0}

View File

@ -1 +0,0 @@
{"authcode":"370173","name":"Player #12","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603619,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"934289","name":"Harry","role":"player","game":"e24444aa-8a18-48aa-a36d-8f84620726f8","created":1649841804}

View File

@ -1 +0,0 @@
{"authcode":"001002","name":"Dumbledore","role":"gamemaster","game":"e24444aa-8a18-48aa-a36d-8f84620726f8","created":1649841804,"lastLoggedIn":1649841540}

View File

@ -1 +0,0 @@
{"authcode":"576653","name":"Player #04","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603258,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"","name":"Ron","role":"player","game":"663576f0-1378-496b-a970-578bdcb222af","created":1650831153,"lastLoggedIn":0}

View File

@ -1 +0,0 @@
{"authcode":"000000","name":"Harald von Bumsquatsch","role":"player","game":"652e36de-99c4-4365-b557-8fd189a396ab","created":1670881923,"lastLoggedIn":1670881950}

View File

@ -1 +0,0 @@
{"authcode":"","name":"Snape","role":"player","game":"e24444aa-8a18-48aa-a36d-8f84620726f8","created":1649841804}

View File

@ -1 +0,0 @@
{"authcode":"019048","name":"Player #11","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603541,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"","name":"Draco","role":"player","game":"e24444aa-8a18-48aa-a36d-8f84620726f8","created":1649841804}

View File

@ -1 +0,0 @@
{"authcode":"123456","name":"Harry","role":"player","game":"663576f0-1378-496b-a970-578bdcb222af","created":1650831122,"lastLoggedIn":1661949675}

View File

@ -1 +0,0 @@
{"authcode":"256473","name":"Player #02","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603188,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"","name":"Hermine","role":"player","game":"e24444aa-8a18-48aa-a36d-8f84620726f8","created":1649841804}

View File

@ -1 +0,0 @@
{"authcode":"002002","name":"Dumbledore","role":"gamemaster","game":"663576f0-1378-496b-a970-578bdcb222af","created":1650831066,"lastLoggedIn":1661965111}

View File

@ -1 +0,0 @@
{"authcode":"631854","name":"Admin","role":"gamemaster","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603106,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"494434","name":"Player #09","role":"player","game":"64efba47-87dc-4c19-851c-aa68c9f0e2c1","created":1651603452,"lastLoggedIn":1651603989}

View File

@ -1 +0,0 @@
{"authcode":"","name":"Ron","role":"player","game":"e24444aa-8a18-48aa-a36d-8f84620726f8","created":1649841804}

View File

@ -0,0 +1,8 @@
package application
func (app *Application) IsInitialized() bool {
app.mu.Lock()
defer app.mu.Unlock()
return len(app.users) > 0
}

View File

@ -1,6 +1,7 @@
package application package application
import ( import (
"errors"
"os" "os"
"path" "path"
@ -11,9 +12,16 @@ func (app *Application) loadGames() error {
dirName := path.Join(app.config.DataDir, "games") dirName := path.Join(app.config.DataDir, "games")
files, err := os.ReadDir(dirName) files, err := os.ReadDir(dirName)
if err != nil { if err != nil {
if !errors.Is(err, os.ErrNotExist) {
return err return err
} }
if err = os.Mkdir(dirName, 0777); err != nil {
return err
}
return nil
}
for _, file := range files { for _, file := range files {
id := file.Name() id := file.Name()
gameDirName := path.Join(dirName, id) gameDirName := path.Join(dirName, id)

View File

@ -1,6 +1,7 @@
package application package application
import ( import (
"errors"
"os" "os"
"path" "path"
@ -11,9 +12,16 @@ func (app *Application) loadUsers() error {
dirName := path.Join(app.config.DataDir, "users") dirName := path.Join(app.config.DataDir, "users")
files, err := os.ReadDir(dirName) files, err := os.ReadDir(dirName)
if err != nil { if err != nil {
if !errors.Is(err, os.ErrNotExist) {
return err return err
} }
if err = os.Mkdir(dirName, 0777); err != nil {
return err
}
return nil
}
app.mu.Lock() app.mu.Lock()
defer app.mu.Unlock() defer app.mu.Unlock()

View File

@ -17,3 +17,7 @@ type Application struct {
playerATime map[string]time.Time playerATime map[string]time.Time
debounceMap map[string]bool debounceMap map[string]bool
} }
type ServerInfo struct {
IsInitialized bool `json:"isInitialized"`
}

View File

@ -8,24 +8,26 @@ import (
type ApplicationConfig struct { type ApplicationConfig struct {
DataDir string DataDir string
BindString string
} }
func NewApplicationConfig() ApplicationConfig { func NewApplicationConfig() ApplicationConfig {
flagVerbosePtr := flag.Bool("v", false, "log debug messages, too")
flagVerbose := flag.Bool("v", false, "log debug messages, too") flagQuietPtr := flag.Bool("q", false, "be quiet; warning and error messages only")
flagQuiet := flag.Bool("q", false, "be quiet; warning and error messages only") bindStringPtr := flag.String("b", "localhost:32039", "interface and port to bind to")
flag.Parse() flag.Parse()
log.SetLoglevel(log.LOG_INFO) log.SetLoglevel(log.LOG_INFO)
if *flagVerbose { if *flagVerbosePtr {
log.SetLoglevel(log.LOG_DEBUG) log.SetLoglevel(log.LOG_DEBUG)
} }
if *flagQuiet { if *flagQuietPtr {
log.SetLoglevel(log.LOG_WARN) log.SetLoglevel(log.LOG_WARN)
} }
return ApplicationConfig{ return ApplicationConfig{
DataDir: "data/", DataDir: "data/",
BindString: *bindStringPtr,
} }
} }

View File

@ -2,6 +2,8 @@ package handler
import ( import (
"net/http" "net/http"
"strings"
"sirlab.de/go/knowyt/application" "sirlab.de/go/knowyt/application"
"sirlab.de/go/knowyt/user" "sirlab.de/go/knowyt/user"
) )
@ -11,21 +13,32 @@ type PrivateHandlerFunc func(*user.User, http.ResponseWriter, *http.Request)
type AuthMux struct { type AuthMux struct {
mux *http.ServeMux mux *http.ServeMux
Port int bindInterfaceAndPort string
app *application.Application app *application.Application
} }
func NewAuthMux(app *application.Application) *AuthMux { func NewAuthMux(app *application.Application) *AuthMux {
bindString := app.GetConfig().BindString
if !strings.Contains(bindString, ":") {
bindString = bindString + ":32039"
}
mux := AuthMux{ mux := AuthMux{
app: app, app: app,
mux: http.NewServeMux(), mux: http.NewServeMux(),
Port: 32039, bindInterfaceAndPort: bindString,
} }
http.Handle("/", mux.mux) http.Handle("/", mux.mux)
return &mux return &mux
} }
func (authMux *AuthMux) GetBindString() string {
if authMux.bindInterfaceAndPort[0] == ':' {
return "*" + authMux.bindInterfaceAndPort
}
return authMux.bindInterfaceAndPort
}
func (authMux *AuthMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (authMux *AuthMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
authMux.mux.ServeHTTP(w, r) authMux.mux.ServeHTTP(w, r)
} }
@ -39,5 +52,5 @@ func (authMux *AuthMux) PublicHandle(pattern string, handler http.Handler) {
} }
func (authMux *AuthMux) ListenAndServe() { func (authMux *AuthMux) ListenAndServe() {
http.ListenAndServe(":32039", nil) http.ListenAndServe(authMux.bindInterfaceAndPort, nil)
} }

View File

@ -0,0 +1,25 @@
package handler
import (
"encoding/json"
"fmt"
"net/http"
"sirlab.de/go/knowyt/user"
)
func (authMux *AuthMux) CheckSetup(w http.ResponseWriter, r *http.Request) {
if !authMux.app.IsInitialized() {
usrSetup := UserInfoJson{
Name: "setup",
Role: user.ROLE_SETUP,
}
w.Header().Add("Content-Type", "application/json")
jsonString, _ := json.Marshal(usrSetup)
fmt.Fprintf(w, "%s", string(jsonString))
return
}
authMux.accessDenied(w, r)
}

View File

@ -8,16 +8,20 @@ import (
"sirlab.de/go/knowyt/user" "sirlab.de/go/knowyt/user"
) )
func (authMux *AuthMux) PrivateHandleFunc(pattern string, handlerFunc PrivateHandlerFunc) { func (authMux *AuthMux) PrivateOrPublicHandleFunc(pattern string, privateHandlerFunc PrivateHandlerFunc, publicHandlerFunc HandlerFunc) {
authMux.mux.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) { authMux.mux.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
usr, err := authMux.getUserFromSession(r) usr, err := authMux.getUserFromSession(r)
if err != nil { if err != nil {
authMux.accessDenied(w, r) // could not authenticate
return publicHandlerFunc(w, r)
} else {
privateHandlerFunc(usr, w, r)
}
})
} }
handlerFunc(usr, w, r) func (authMux *AuthMux) PrivateHandleFunc(pattern string, handlerFunc PrivateHandlerFunc) {
}) authMux.PrivateOrPublicHandleFunc(pattern, handlerFunc, authMux.accessDenied)
} }
func (authMux *AuthMux) accessDenied(w http.ResponseWriter, r *http.Request) { func (authMux *AuthMux) accessDenied(w http.ResponseWriter, r *http.Request) {

View File

@ -22,8 +22,8 @@ func main() {
mux.PublicHandleFunc("/api/login", mux.Login) mux.PublicHandleFunc("/api/login", mux.Login)
mux.PublicHandleFunc("/api/logout", mux.Logout) mux.PublicHandleFunc("/api/logout", mux.Logout)
mux.PublicHandleFunc("/api/createGame", app.CreateGame) mux.PublicHandleFunc("/api/createGame", app.CreateGame)
mux.PrivateOrPublicHandleFunc("/api/userinfo", mux.GetUserInfo, mux.CheckSetup)
mux.PrivateHandleFunc("/api/cameo", mux.Cameo) mux.PrivateHandleFunc("/api/cameo", mux.Cameo)
mux.PrivateHandleFunc("/api/userinfo", mux.GetUserInfo)
mux.PrivateHandleFunc("/api/gameinfo", app.GetGameInfo) mux.PrivateHandleFunc("/api/gameinfo", app.GetGameInfo)
mux.PrivateHandleFunc("/api/games", app.GetGames) mux.PrivateHandleFunc("/api/games", app.GetGames)
mux.PrivateHandleFunc("/api/setGameName", app.SetGameName) mux.PrivateHandleFunc("/api/setGameName", app.SetGameName)
@ -47,6 +47,6 @@ func main() {
mux.PublicHandleFunc("/", handler.FileHandler) mux.PublicHandleFunc("/", handler.FileHandler)
// start listening // start listening
log.Info("Listening at http://localhost:%d/\n", mux.Port) log.Info("Listening at http://%s/\n", mux.GetBindString())
mux.ListenAndServe() mux.ListenAndServe()
} }

Some files were not shown because too many files have changed in this diff Show More