Account creation now works
This commit is contained in:
parent
546943d762
commit
0b4b0fefb2
@ -36,13 +36,14 @@ router.post('/register', isAdmin, (req, res) => {
|
||||
});
|
||||
|
||||
// User gets if setup account exists given the query code
|
||||
router.get('/setup', (req, res) => {
|
||||
router.get('/verify-setup', (req, res) => {
|
||||
User.findOne({setupCode: req.query.code}).then(user => {
|
||||
if(user){
|
||||
res.json({status: "ok", code: req.query.code});
|
||||
} else {
|
||||
res.json({status: "err", msg: "not-exists"})
|
||||
}
|
||||
res.json({status: "err", msg: "not-exists"});
|
||||
}).catch(res.json({status: "err", msg: "internal"}));
|
||||
});
|
||||
});
|
||||
|
||||
// User posts the parameters of his new account given by admin
|
||||
@ -72,7 +73,7 @@ router.post('/setup', rateLimitMiddleware, (req, res) => {
|
||||
});
|
||||
} else {
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(user.password, salt, (err, hash) => {
|
||||
bcrypt.hash(password, salt, (err, hash) => {
|
||||
if(err) throw err;
|
||||
user.password = hash;
|
||||
user.username = username;
|
||||
|
BIN
backend/uploads/image-1727702861648
Normal file
BIN
backend/uploads/image-1727702861648
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
@ -1,112 +1,12 @@
|
||||
<script setup>
|
||||
|
||||
import { onMounted } from 'vue'
|
||||
import { RouterLink, RouterView } from 'vue-router'
|
||||
|
||||
import { GetUser, HasAdmin, UserStatus, LoadUser } from '@/services/User.js'
|
||||
import { IsAdmin } from './services/User'
|
||||
|
||||
import useEmitter from '@/services/Emitter';
|
||||
const emitter = useEmitter();
|
||||
|
||||
import { DisplayToast, SetEmitter } from './services/Dragonroll'
|
||||
import { CreateWindow } from './services/Windows';
|
||||
import { FetchResources } from './services/Resources';
|
||||
import { ImportModule } from './services/Modules';
|
||||
import { FetchPlugins } from './services/Plugins';
|
||||
|
||||
LoadUser();
|
||||
|
||||
SetEmitter(emitter);
|
||||
|
||||
async function start(){
|
||||
if(GetUser()){
|
||||
CreateWindow('main_menu');
|
||||
// DisplayToast('green', 'Logged in successfully as ' + GetUser().username + '!', 3000)
|
||||
} else {
|
||||
if(await HasAdmin()){
|
||||
CreateWindow('login');
|
||||
} else {
|
||||
CreateWindow('register');
|
||||
}
|
||||
}
|
||||
|
||||
await FetchResources();
|
||||
await FetchPlugins();
|
||||
|
||||
await ImportModule('dnd-5e')
|
||||
|
||||
DisplayToast('aqua', 'All plugins loaded successfully');
|
||||
|
||||
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
start();
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrapper" id="container">
|
||||
<RouterView />
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.web-title {
|
||||
font-size: 22px;
|
||||
font-weight: bolder;
|
||||
padding-bottom: 12px;
|
||||
color: var(--color-heading)
|
||||
}
|
||||
|
||||
.sidebar-link {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sidebar-separator {
|
||||
margin-top: 10px;
|
||||
margin-left: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.top-nav {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
a {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
display: flex;
|
||||
max-height: 100vh;
|
||||
min-height: 100vh;
|
||||
overflow-y: auto;
|
||||
|
||||
background-color: var(--color-background-soft);
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.sidebar {
|
||||
min-width: 240px;
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -8,10 +8,10 @@ const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
{path: '/', name: 'home', component: HomeView},
|
||||
|
||||
{path: '/:pathMatch(.*)*', name: "NotFound", component: NotFoundView },
|
||||
|
||||
|
||||
{path: '/setup/:setupCode', redirect: to => {
|
||||
return {path: '/', query: {setupCode: to.params.setupCode}}
|
||||
}},
|
||||
{path: '/:pathMatch(.*)*', redirect: {name: 'home'} },
|
||||
]
|
||||
})
|
||||
|
||||
|
@ -32,6 +32,7 @@ import PluginWindow from '../views/windows/settings/PluginWindow.vue';
|
||||
import FirstRegisterWindow from '../views/windows/FirstRegisterWindow.vue';
|
||||
import RegisterUserWindow from '../views/windows/settings/RegisterUserWindow.vue';
|
||||
import CopyPendingUserWindow from '../views/windows/settings/CopyPendingUserWindow.vue';
|
||||
import SetupAccountWindow from '../views/windows/SetupAccountWindow.vue';
|
||||
|
||||
let windowMap = {
|
||||
test: ExampleWindow,
|
||||
@ -41,6 +42,7 @@ let windowMap = {
|
||||
first_register: FirstRegisterWindow,
|
||||
register_user: RegisterUserWindow,
|
||||
copy_pending_user_window: CopyPendingUserWindow,
|
||||
setup_account: SetupAccountWindow,
|
||||
edit_profile: EditProfileWindow,
|
||||
settings: SettingsWindow,
|
||||
campaign_list: CampaignListWindow,
|
||||
|
@ -1,18 +1,80 @@
|
||||
<script setup>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
import { onMounted } from 'vue';
|
||||
import { RouterLink, RouterView } from 'vue-router'
|
||||
|
||||
import WindowManager from '@/views/managers/WindowManager.vue'
|
||||
import { GetUser } from '@/services/User'
|
||||
|
||||
import Api from '@/services/Api'
|
||||
import { CreateWindow } from '@/services/Windows'
|
||||
import Toast from './partials/Toast.vue';
|
||||
import { DisplayToast, SetEmitter } from '../services/Dragonroll';
|
||||
import GameManager from './managers/GameManager.vue';
|
||||
import TooltipManager from './managers/TooltipManager.vue';
|
||||
import ContextMenuManager from './managers/ContextMenuManager.vue';
|
||||
import { GetUser, HasAdmin, LoadUser } from '@/services/User.js'
|
||||
import { DisplayToast, SetEmitter } from '@/services/Dragonroll';
|
||||
import { FetchResources } from '@/services/Resources';
|
||||
import { ImportModule } from '@/services/Modules';
|
||||
import { FetchPlugins } from '@/services/Plugins';
|
||||
import useEmitter from '@/services/Emitter';
|
||||
const emitter = useEmitter();
|
||||
|
||||
import Toast from '@/views/partials/Toast.vue';
|
||||
import GameManager from '@/views/managers/GameManager.vue';
|
||||
import TooltipManager from '@/views/managers/TooltipManager.vue';
|
||||
import ContextMenuManager from '@/views/managers/ContextMenuManager.vue';
|
||||
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
LoadUser();
|
||||
|
||||
SetEmitter(emitter);
|
||||
|
||||
async function DisplayFirstWindow(){
|
||||
if(GetUser()){
|
||||
CreateWindow('main_menu');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we have a link
|
||||
if(route.query.setupCode){
|
||||
// Let's try to activate it
|
||||
Api().get('/user/verify-setup?code=' + route.query.setupCode).then(res => {
|
||||
if(res.data.code){
|
||||
// Yep exists
|
||||
CreateWindow('setup_account', {
|
||||
title: "register-account.setup.title",
|
||||
id: 'setup_account',
|
||||
setupCode: res.data.code,
|
||||
})
|
||||
return;
|
||||
}
|
||||
DisplayToast("red", t('register-account.setup.invalid-link'));
|
||||
CreateWindow('login');
|
||||
});
|
||||
} else {
|
||||
if(await HasAdmin()){
|
||||
CreateWindow('login');
|
||||
} else {
|
||||
CreateWindow('register');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function start(){
|
||||
|
||||
DisplayFirstWindow();
|
||||
|
||||
await FetchResources();
|
||||
await FetchPlugins();
|
||||
|
||||
await ImportModule('dnd-5e')
|
||||
|
||||
DisplayToast('aqua', 'All plugins loaded successfully');
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
start();
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
149
client/src/views/windows/SetupAccountWindow.vue
Normal file
149
client/src/views/windows/SetupAccountWindow.vue
Normal file
@ -0,0 +1,149 @@
|
||||
<script setup>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
import ErrorMessage from '@/views/others/ErrorMessage.vue'
|
||||
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { SetupHandle, SetSize, ResetPosition } from '@/services/Windows';
|
||||
|
||||
import Api from '@/services/Api.js'
|
||||
|
||||
import { ClearWindow, CreateWindow } from '@/services/Windows';
|
||||
import { DisplayToast } from '@/services/Dragonroll';
|
||||
|
||||
const email = ref("");
|
||||
const name = ref("");
|
||||
const username = ref("");
|
||||
const password = ref("");
|
||||
const confirmPassword = ref("");
|
||||
const errorMessage = ref("");
|
||||
|
||||
const handle = ref(null);
|
||||
|
||||
const props = defineProps(['data']);
|
||||
|
||||
const data = props.data;
|
||||
|
||||
let id = data.id;
|
||||
|
||||
onMounted(() => {
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {width: 500, height: 620});
|
||||
ResetPosition(id, "center");
|
||||
});
|
||||
|
||||
|
||||
function setup(){
|
||||
if(password.value != confirmPassword.value){
|
||||
errorMessage.value = t('general.password-mismatch');
|
||||
return;
|
||||
}
|
||||
|
||||
Api().post('/user/setup?code=' + data.setupCode,
|
||||
{
|
||||
name: name.value,
|
||||
username: username.value,
|
||||
email: email.value,
|
||||
password: password.value,
|
||||
}).then((response) => {
|
||||
|
||||
const data = response.data;
|
||||
|
||||
if(data.error){
|
||||
console.log(data);
|
||||
errorMessage.value = data.msg;
|
||||
} else {
|
||||
errorMessage.value = "";
|
||||
console.log("Logged successfully");
|
||||
DisplayToast('green', 'Account setup successfull, now log in!', 3000);
|
||||
ClearWindow(id);
|
||||
CreateWindow('login');
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="window-wrapper" :id="'window-wrapper-' + id">
|
||||
<WindowHandle :window="id" ref="handle"></WindowHandle>
|
||||
|
||||
<div class="window-content">
|
||||
<div class="document" v-html="t('register-account.setup.welcome-message')">
|
||||
</div>
|
||||
<form v-on:submit.prevent="setup">
|
||||
<div class="form-field">
|
||||
<label for="name">{{$t('general.name')}}</label>
|
||||
<input id="name-field" type="text" :placeholder="t('placeholders.name')" name="name" v-model="name" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="email">{{$t('general.email')}}</label>
|
||||
<input id="email-field" type="email" :placeholder="t('placeholders.email')" name="email" v-model="email" autocomplete="off" >
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label for="username">{{$t('general.username')}}</label>
|
||||
<input id="username-field" type="text" :placeholder="t('placeholders.username')" name="username" v-model="username" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="password">{{$t('general.password')}}</label>
|
||||
<input id="password-field" type="password" :placeholder="t('placeholders.password')" name="password" v-model="password" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="confirm-password">{{$t('general.password-confirm')}}</label>
|
||||
<input id="confirm-password-field" type="password" :placeholder="t('placeholders.password-confirm')" name="confirm-password" v-model="confirmPassword" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<button class="btn-primary sound-click confirm-form-button">{{$t('register-account.setup.confirm')}}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<ErrorMessage v-if="errorMessage">{{ errorMessage }}</ErrorMessage>
|
||||
|
||||
</div>
|
||||
<!-- <VersionRender></VersionRender> -->
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped>
|
||||
p {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.window-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.window-content {
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-bottom: 50px;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.splash-image {
|
||||
width: 450px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
</style>
|
@ -6,6 +6,7 @@ import { onMounted, ref, shallowRef, toRaw } from 'vue';
|
||||
import { SetupHandle, SetSize, ResetPosition } from '@/services/Windows';
|
||||
|
||||
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||
import { DisplayToast } from '../../../services/Dragonroll';
|
||||
|
||||
const handle = ref(null);
|
||||
|
||||
@ -16,18 +17,26 @@ let id = data.id;
|
||||
|
||||
onMounted(() => {
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {width: 500, height: 380});
|
||||
SetSize(id, {width: 300, height: 170});
|
||||
ResetPosition(id, "center");
|
||||
|
||||
});
|
||||
|
||||
function CopyLink(){
|
||||
let root = location.protocol + '//' + location.host;
|
||||
navigator.clipboard.writeText(`${root}/setup/${data.code}`)
|
||||
DisplayToast('aqua', t('settings.pending-account.copy-success'));
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="window-wrapper" :id="'window-wrapper-' + id">
|
||||
<WindowHandle :window="id" ref="handle"></WindowHandle>
|
||||
|
||||
<h1>Hola</h1>
|
||||
<div class="document centered">
|
||||
<h1>{{$t('settings.pending-account.title')}}</h1>
|
||||
<p>{{$t('settings.pending-account.content')}}</p>
|
||||
</div>
|
||||
<button v-on:click.prevent="CopyLink">{{$t('settings.pending-account.copy-link')}}</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"password-confirm": "Confirm your password",
|
||||
"password-mismatch": "Password mismatch",
|
||||
"register": "Register",
|
||||
"quantity": "Quantity",
|
||||
"weight": "Weight",
|
||||
@ -38,7 +39,14 @@
|
||||
"register-account": {
|
||||
"title": "Create new user account",
|
||||
"welcome-message": "<h1>Hola</h1>",
|
||||
"pending-account": "Pending account"
|
||||
"pending-account": "Pending account",
|
||||
"setup": {
|
||||
"title": "Setup Account",
|
||||
"invalid-link": "Invalid setup code link",
|
||||
"welcome-message": "<p>Here you can create a new user account.</p><br><p>Once you have registered a new account, you will recieve a link that you must give to the owner of the new account. From there, the owner will be able to setup his new account</p><hr>",
|
||||
"confirm": "Setup Account"
|
||||
},
|
||||
"invalid-link": "Invalid setup code link"
|
||||
},
|
||||
"main-menu": {
|
||||
"title": "Dragonroll",
|
||||
@ -65,6 +73,12 @@
|
||||
"manage-plugins-button": "Manage plugins",
|
||||
"manage-accounts": "Manage site accounts",
|
||||
"manage-plugins": "Manage plugins"
|
||||
},
|
||||
"pending-account": {
|
||||
"title": "Pending account",
|
||||
"content": "This account is pending for confirmation",
|
||||
"copy-link": "Copy link",
|
||||
"copy-success": "Copied account setup link successfully!"
|
||||
}
|
||||
},
|
||||
"campaigns": {
|
||||
|
@ -12,6 +12,7 @@
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"password-confirm": "Confirm your password",
|
||||
"password-mismatch": "Password mismatch",
|
||||
"register": "Register",
|
||||
"quantity": "Quantity",
|
||||
"weight": "Weight",
|
||||
@ -38,7 +39,13 @@
|
||||
"register-account": {
|
||||
"title": "Create new user account",
|
||||
"welcome-message": "<p>Here you can create a new user account.</p><br><p>Once you have registered a new account, you will recieve a link that you must give to the owner of the new account. From there, the owner will be able to setup his new account</p><hr>",
|
||||
"pending-account": "Pending account"
|
||||
"pending-account": "Pending account",
|
||||
"setup": {
|
||||
"title": "Setup Account",
|
||||
"invalid-link": "Invalid setup code link",
|
||||
"welcome-message": "<h1>Welcome!</h1><b>You have been invited to a Dragonroll server!</b><p>Create your account by filling the following fields:</p><hr>",
|
||||
"confirm": "Setup Account"
|
||||
}
|
||||
},
|
||||
"main-menu": {
|
||||
"title": "Dragonroll",
|
||||
@ -68,6 +75,12 @@
|
||||
"manage-plugins": {
|
||||
"title": "Manage Plugins"
|
||||
}
|
||||
},
|
||||
"pending-account": {
|
||||
"title": "Pending account",
|
||||
"content": "This account is pending for confirmation",
|
||||
"copy-link": "Copy link",
|
||||
"copy-success": "Copied account setup link successfully!"
|
||||
}
|
||||
},
|
||||
"campaigns": {
|
||||
|
@ -12,6 +12,7 @@
|
||||
"username": "Nombre de usuario",
|
||||
"password": "Contraseña",
|
||||
"password-confirm": "Confirma tu contraseña",
|
||||
"password-mismatch": "Password mismatch",
|
||||
"register": "Registrar-se",
|
||||
"quantity": "Quantity",
|
||||
"weight": "Weight",
|
||||
@ -26,7 +27,7 @@
|
||||
},
|
||||
"placeholders": {
|
||||
"name": "John Doe",
|
||||
"email": "john@doe.com",
|
||||
"email": "john{'@'}doe.com",
|
||||
"username": "Introduce tu nombre de usuario...",
|
||||
"password": "Introduce tu contraseña...",
|
||||
"password-confirm": "Vuelve a introducir tu contraseña..."
|
||||
@ -38,7 +39,14 @@
|
||||
"register-account": {
|
||||
"title": "Create new user account",
|
||||
"welcome-message": "<h1>Hola</h1>",
|
||||
"pending-account": "Pending account"
|
||||
"pending-account": "Pending account",
|
||||
"setup": {
|
||||
"title": "Setup Account",
|
||||
"invalid-link": "Invalid setup code link",
|
||||
"welcome-message": "<h1>Welcome!</h1><b>You have been invited to a Dragonroll server!</b><p>Create your account by filling the following fields:</p><hr>",
|
||||
"confirm": "Setup Account"
|
||||
},
|
||||
"invalid-link": "Invalid setup code link"
|
||||
},
|
||||
"main-menu": {
|
||||
"title": "Dragonroll",
|
||||
@ -65,6 +73,12 @@
|
||||
"manage-plugins-button": "Manage plugins",
|
||||
"manage-accounts": "Manage site accounts",
|
||||
"manage-plugins": "Manage plugins"
|
||||
},
|
||||
"pending-account": {
|
||||
"title": "Pending account",
|
||||
"content": "This account is pending for confirmation",
|
||||
"copy-link": "Copy link",
|
||||
"copy-success": "Copied account setup link successfully!"
|
||||
}
|
||||
},
|
||||
"campaigns": {
|
||||
|
Loading…
Reference in New Issue
Block a user