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 (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE,
name TEXT,
user INTEGER,
timer_enabled INTEGER,
duration INTEGER,
@@ -31,7 +31,8 @@ module.exports = function () {
tremolo_enabled INTEGER,
tremolo_frequency 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 (

View File

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

View File

@@ -29,10 +29,6 @@ router.get('/users/current', (req, res) => {
})
router.get('/users', (req, res) => {
if (!req.user) {
return res.sendStatus(401)
}
const users = []
db.all('SELECT id, username, name, is_admin as isAdmin, can_upload as canUpload FROM users', (err, rows) => {
@@ -57,6 +53,55 @@ router.get('/users', (req, res) => {
})
router.post('/users', (req, res) => {
db.serialize(() => {
db.get('SELECT COUNT(*) as count FROM users', (err, row) => {
if (err) {
return res.sendStatus(500)
}
if (row.count !== 0) {
if (!req.user) {
return res.sendStatus(401)
}
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) {
@@ -95,6 +140,9 @@ router.post('/users', (req, res) => {
})
})
})
}
})
})
})
router.patch('/users/admin/:userId', (req, res) => {

View File

@@ -1,6 +1,6 @@
<template>
<v-container>
<v-row class="text-center">
<v-row>
<v-col class="mb-5">
<h1 class="display-2 font-weight-bold mb-3">
Admin Dashboard
@@ -8,13 +8,84 @@
</v-col>
</v-row>
<v-row class="text-center">
<v-col class="mb-5">
<h2 class="headline font-weight-bold">
Users
</h2>
<v-dialog
v-model="addUserDialog"
max-width="600px"
>
<template v-slot:activator="{ on, attrs }">
<v-btn
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-row
@@ -22,24 +93,16 @@
:key="user.username"
>
<v-container>
<v-row
justify="center"
>
<v-row>
ID: {{ user.id }}
</v-row>
<v-row
justify="center"
>
<v-row>
Username: {{ user.username }}
</v-row>
<v-row
justify="center"
>
<v-row>
Name: {{ user.name }}
</v-row>
<v-row
justify="center"
>
<v-row>
<v-switch
v-model="user.isAdmin"
:label="`${user.isAdmin ? 'Admin' : 'Not Admin'}`"
@@ -47,9 +110,7 @@
@change="updateUserAdmin(user.id, user.isAdmin); snackbar = true"
/>
</v-row>
<v-row
justify="center"
>
<v-row>
<v-switch
v-model="user.canUpload"
:label="`${user.canUpload ? 'Can Upload Samples' : 'Cannot Upload Samples'}`"
@@ -57,9 +118,7 @@
@change="updateUserUpload(user.id, user.canUpload); snackbar = true"
/>
</v-row>
<v-row
justify="center"
>
<v-row>
<v-btn
:disabled="user.id === currentUser.id"
@click="deleteUser(user.id)"

View File

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

View File

@@ -42,6 +42,24 @@
>
Login
</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-form>
</template>

View File

@@ -5,7 +5,17 @@ export default {
currentUser: {},
users: [],
snackbar: false,
updateText: ''
updateText: '',
addUserDialog: false,
isUserValid: false,
name: '',
username: '',
password: '',
isAdmin: false,
canUpload: false,
rules: {
required: v => !!v || 'Required'
}
}),
created () {
this.getCurrentUser()
@@ -72,6 +82,27 @@ export default {
.catch((error) => {
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,
isAdmin: false
}),
created () {
this.getCurrentUser()
},
methods: {
home () {
this.$router.push('/')
@@ -27,6 +24,7 @@ export default {
})
},
getCurrentUser () {
this.drawyer = true
this.$http.get('/users/current')
.then(response => {
if (response.status === 200) {

View File

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

View File

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

View File

@@ -67,6 +67,19 @@ router.beforeEach((to, from, next) => {
console.error(error.response)
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 {
next()
}