Register users from admin page

This commit is contained in:
Kevin Thomas
2021-11-05 23:04:34 -07:00
parent f2d1b80673
commit 69a467b13b
11 changed files with 245 additions and 69 deletions

View File

@@ -15,7 +15,7 @@ module.exports = function () {
db.run(`CREATE TABLE IF NOT EXISTS profiles ( db.run(`CREATE TABLE IF NOT EXISTS profiles (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT UNIQUE, name TEXT,
user INTEGER, user INTEGER,
timer_enabled INTEGER, timer_enabled INTEGER,
duration INTEGER, duration INTEGER,
@@ -31,7 +31,8 @@ module.exports = function () {
tremolo_enabled INTEGER, tremolo_enabled INTEGER,
tremolo_frequency REAL, tremolo_frequency REAL,
tremolo_depth REAL, tremolo_depth REAL,
FOREIGN KEY(user) REFERENCES users(id))` FOREIGN KEY(user) REFERENCES users(id),
UNIQUE(user,name))`
) )
db.run(`CREATE TABLE IF NOT EXISTS samples ( db.run(`CREATE TABLE IF NOT EXISTS samples (

View File

@@ -185,6 +185,7 @@ router.post('/profiles/default', (req, res) => {
], ],
function (err) { function (err) {
if (err) { if (err) {
console.log('ERROR: ', err)
return res.sendStatus(500) return res.sendStatus(500)
} else { } else {
return res.json({ id: this.lastID }) return res.json({ id: this.lastID })

View File

@@ -29,10 +29,6 @@ router.get('/users/current', (req, res) => {
}) })
router.get('/users', (req, res) => { router.get('/users', (req, res) => {
if (!req.user) {
return res.sendStatus(401)
}
const users = [] const users = []
db.all('SELECT id, username, name, is_admin as isAdmin, can_upload as canUpload FROM users', (err, rows) => { db.all('SELECT id, username, name, is_admin as isAdmin, can_upload as canUpload FROM users', (err, rows) => {
@@ -57,42 +53,94 @@ router.get('/users', (req, res) => {
}) })
router.post('/users', (req, res) => { router.post('/users', (req, res) => {
const salt = crypto.randomBytes(16) db.serialize(() => {
crypto.pbkdf2(req.body.password, salt, 10000, 32, 'sha256', (err, hashedPassword) => { db.get('SELECT COUNT(*) as count FROM users', (err, row) => {
if (err) {
return res.sendStatus(500)
}
db.run(`INSERT INTO users (username, hashed_password, salt, name, is_admin, dark_mode, can_upload)
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
req.body.username,
hashedPassword,
salt,
req.body.name,
req.body.isAdmin,
req.body.darkMode,
req.body.canUpload
], function (err) {
if (err) { if (err) {
if (err.code === 'SQLITE_CONSTRAINT') { return res.sendStatus(500)
return res.sendStatus(409)
} else {
return res.sendStatus(500)
}
} }
const user = { if (row.count !== 0) {
id: this.lastID.toString(), if (!req.user) {
username: req.body.username, return res.sendStatus(401)
displayName: req.body.name
}
req.login(user, (err) => {
if (err) {
return res.sendStatus(500)
} else {
return res.sendStatus(200)
} }
})
db.get('SELECT is_admin as isAdmin FROM users WHERE id = ?', [req.user.id], (err, row) => {
if (err) {
return res.sendStatus(500)
}
if (row.isAdmin !== 1) {
return res.sendStatus(401)
}
const salt = crypto.randomBytes(16)
crypto.pbkdf2(req.body.password, salt, 10000, 32, 'sha256', (err, hashedPassword) => {
if (err) {
return res.sendStatus(500)
}
db.run(`INSERT INTO users (username, hashed_password, salt, name, is_admin, dark_mode, can_upload)
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
req.body.username,
hashedPassword,
salt,
req.body.name,
req.body.isAdmin,
req.body.darkMode,
req.body.canUpload
], (err) => {
if (err) {
if (err.code === 'SQLITE_CONSTRAINT') {
return res.sendStatus(409)
} else {
return res.sendStatus(500)
}
}
return res.sendStatus(200)
})
})
})
} else {
const salt = crypto.randomBytes(16)
crypto.pbkdf2(req.body.password, salt, 10000, 32, 'sha256', (err, hashedPassword) => {
if (err) {
return res.sendStatus(500)
}
db.run(`INSERT INTO users (username, hashed_password, salt, name, is_admin, dark_mode, can_upload)
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
req.body.username,
hashedPassword,
salt,
req.body.name,
req.body.isAdmin,
req.body.darkMode,
req.body.canUpload
], function (err) {
if (err) {
if (err.code === 'SQLITE_CONSTRAINT') {
return res.sendStatus(409)
} else {
return res.sendStatus(500)
}
}
const user = {
id: this.lastID.toString(),
username: req.body.username,
displayName: req.body.name
}
req.login(user, (err) => {
if (err) {
return res.sendStatus(500)
} else {
return res.sendStatus(200)
}
})
})
})
}
}) })
}) })
}) })

View File

@@ -1,6 +1,6 @@
<template> <template>
<v-container> <v-container>
<v-row class="text-center"> <v-row>
<v-col class="mb-5"> <v-col class="mb-5">
<h1 class="display-2 font-weight-bold mb-3"> <h1 class="display-2 font-weight-bold mb-3">
Admin Dashboard Admin Dashboard
@@ -8,13 +8,84 @@
</v-col> </v-col>
</v-row> </v-row>
<v-row class="text-center"> <v-dialog
<v-col class="mb-5"> v-model="addUserDialog"
<h2 class="headline font-weight-bold"> max-width="600px"
Users >
</h2> <template v-slot:activator="{ on, attrs }">
</v-col> <v-btn
</v-row> v-bind="attrs"
v-on="on"
@click="addUserDialog = true"
>
Add User
</v-btn>
</template>
<v-form
v-model="isUserValid"
>
<v-card>
<v-card-title>
<span class="text-h5">Add User</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12">
<v-text-field
v-model="name"
:rules="[rules.required]"
label="Name"
required
/>
<v-text-field
v-model="username"
:rules="[rules.required]"
label="Username"
required
/>
<v-text-field
v-model="password"
type="password"
:rules="[rules.required]"
label="Password"
required
/>
<v-switch
v-model="isAdmin"
:label="`${isAdmin ? 'Admin' : 'Not Admin'}`"
/>
<v-switch
v-model="canUpload"
:label="`${canUpload ? 'Can Upload Samples' : 'Cannot Upload Samples'}`"
/>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
text
@click="addUserDialog = false"
>
Close
</v-btn>
<v-btn
text
:disabled="!isUserValid"
@click="addUser"
>
Register
</v-btn>
</v-card-actions>
</v-card>
</v-form>
</v-dialog>
<v-divider
class="my-7"
/>
<v-col cols="12"> <v-col cols="12">
<v-row <v-row
@@ -22,24 +93,16 @@
:key="user.username" :key="user.username"
> >
<v-container> <v-container>
<v-row <v-row>
justify="center"
>
ID: {{ user.id }} ID: {{ user.id }}
</v-row> </v-row>
<v-row <v-row>
justify="center"
>
Username: {{ user.username }} Username: {{ user.username }}
</v-row> </v-row>
<v-row <v-row>
justify="center"
>
Name: {{ user.name }} Name: {{ user.name }}
</v-row> </v-row>
<v-row <v-row>
justify="center"
>
<v-switch <v-switch
v-model="user.isAdmin" v-model="user.isAdmin"
:label="`${user.isAdmin ? 'Admin' : 'Not Admin'}`" :label="`${user.isAdmin ? 'Admin' : 'Not Admin'}`"
@@ -47,9 +110,7 @@
@change="updateUserAdmin(user.id, user.isAdmin); snackbar = true" @change="updateUserAdmin(user.id, user.isAdmin); snackbar = true"
/> />
</v-row> </v-row>
<v-row <v-row>
justify="center"
>
<v-switch <v-switch
v-model="user.canUpload" v-model="user.canUpload"
:label="`${user.canUpload ? 'Can Upload Samples' : 'Cannot Upload Samples'}`" :label="`${user.canUpload ? 'Can Upload Samples' : 'Cannot Upload Samples'}`"
@@ -57,9 +118,7 @@
@change="updateUserUpload(user.id, user.canUpload); snackbar = true" @change="updateUserUpload(user.id, user.canUpload); snackbar = true"
/> />
</v-row> </v-row>
<v-row <v-row>
justify="center"
>
<v-btn <v-btn
:disabled="user.id === currentUser.id" :disabled="user.id === currentUser.id"
@click="deleteUser(user.id)" @click="deleteUser(user.id)"

View File

@@ -7,7 +7,7 @@
dense dense
> >
<v-app-bar-nav-icon <v-app-bar-nav-icon
@click="drawyer = true" @click="getCurrentUser"
/> />
</v-app-bar> </v-app-bar>
<v-navigation-drawer <v-navigation-drawer

View File

@@ -42,6 +42,24 @@
> >
Login Login
</v-btn> </v-btn>
<v-snackbar
v-model="snackbar"
color="error"
timeout="3000"
>
{{ snackbarText }}
<template v-slot:action="{ attrs }">
<v-btn
text
v-bind="attrs"
@click="snackbar = false"
>
Close
</v-btn>
</template>
</v-snackbar>
</v-container> </v-container>
</v-form> </v-form>
</template> </template>

View File

@@ -5,7 +5,17 @@ export default {
currentUser: {}, currentUser: {},
users: [], users: [],
snackbar: false, snackbar: false,
updateText: '' updateText: '',
addUserDialog: false,
isUserValid: false,
name: '',
username: '',
password: '',
isAdmin: false,
canUpload: false,
rules: {
required: v => !!v || 'Required'
}
}), }),
created () { created () {
this.getCurrentUser() this.getCurrentUser()
@@ -72,6 +82,27 @@ export default {
.catch((error) => { .catch((error) => {
console.error(error.response) console.error(error.response)
}) })
},
addUser () {
this.$http.post('/users', {
name: this.name,
username: this.username,
password: this.password,
isAdmin: this.isAdmin,
darkMode: 0,
canUpload: this.canUpload
})
.then(response => {
if (response.status === 200) {
this.addUserDialog = false
this.updateText = 'User Registered'
this.snackbar = true
this.getUsers()
}
})
.catch((error) => {
console.error(error.response)
})
} }
} }
} }

View File

@@ -5,9 +5,6 @@ export default {
drawyer: false, drawyer: false,
isAdmin: false isAdmin: false
}), }),
created () {
this.getCurrentUser()
},
methods: { methods: {
home () { home () {
this.$router.push('/') this.$router.push('/')
@@ -27,6 +24,7 @@ export default {
}) })
}, },
getCurrentUser () { getCurrentUser () {
this.drawyer = true
this.$http.get('/users/current') this.$http.get('/users/current')
.then(response => { .then(response => {
if (response.status === 200) { if (response.status === 200) {

View File

@@ -3,6 +3,8 @@ export default {
valid: false, valid: false,
username: '', username: '',
password: '', password: '',
snackbar: false,
snackbarText: '',
usernameRules: [ usernameRules: [
v => !!v || 'Username is required' v => !!v || 'Username is required'
], ],
@@ -22,6 +24,10 @@ export default {
} }
}) })
.catch((error) => { .catch((error) => {
if (error.response.status === 401) {
this.snackbar = true
this.snackbarText = 'Login Failed: Unauthorized'
}
console.error(error.response) console.error(error.response)
}) })
} }

View File

@@ -378,6 +378,7 @@ export default {
.then(response => { .then(response => {
if (response.status === 200) { if (response.status === 200) {
this.canUpload = response.data.user.canUpload this.canUpload = response.data.user.canUpload
this.$vuetify.theme.dark = response.data.user.darkMode
} }
}) })
.catch((error) => { .catch((error) => {

View File

@@ -67,6 +67,19 @@ router.beforeEach((to, from, next) => {
console.error(error.response) console.error(error.response)
next('/') next('/')
}) })
} else if (to.name === 'Register') {
instance.get('/users')
.then(response => {
if (response.data.users.length !== 0) {
next('/')
} else {
next()
}
})
.catch((error) => {
console.error(error.response)
next('/')
})
} else { } else {
next() next()
} }