mirror of
https://github.com/BobbyWibowo/lolisafe.git
synced 2025-01-18 17:21:33 +00:00
Added feature to create new user from Manage Users
New admins-only API route: /api/users/create Restored checkboxes and bulk buttons in Manage Users Currently useless, as bulk operators are still WIP Added filter input in Manage Users, currently WIP Rebuilt client-side assets and bumped v1 version string
This commit is contained in:
parent
7389ac6c07
commit
1c260c87b0
@ -146,6 +146,72 @@ self.assertPermission = (user, target) => {
|
||||
throw new Error('Root user may not be tampered with.')
|
||||
}
|
||||
|
||||
self.createUser = async (req, res, next) => {
|
||||
const user = await utils.authorize(req, res)
|
||||
if (!user) return
|
||||
|
||||
const isadmin = perms.is(user, 'admin')
|
||||
if (!isadmin)
|
||||
return res.status(403).end()
|
||||
|
||||
const username = typeof req.body.username === 'string'
|
||||
? req.body.username.trim()
|
||||
: ''
|
||||
if (username.length < self.user.min || username.length > self.user.max)
|
||||
return res.json({ success: false, description: `Username must have ${self.user.min}-${self.user.max} characters.` })
|
||||
|
||||
let password = typeof req.body.password === 'string'
|
||||
? req.body.password.trim()
|
||||
: ''
|
||||
if (password.length) {
|
||||
if (password.length < self.pass.min || password.length > self.pass.max)
|
||||
return res.json({ success: false, description: `Password must have ${self.pass.min}-${self.pass.max} characters.` })
|
||||
} else {
|
||||
password = randomstring.generate(self.pass.rand)
|
||||
}
|
||||
|
||||
let group = req.body.group
|
||||
let permission
|
||||
if (group !== undefined) {
|
||||
permission = perms.permissions[group]
|
||||
if (typeof permission !== 'number' || permission < 0) {
|
||||
group = 'user'
|
||||
permission = perms.permissions.user
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const user = await db.table('users')
|
||||
.where('username', username)
|
||||
.first()
|
||||
|
||||
if (user)
|
||||
return res.json({ success: false, description: 'Username already exists.' })
|
||||
|
||||
const hash = await bcrypt.hash(password, saltRounds)
|
||||
|
||||
const token = await tokens.generateUniqueToken()
|
||||
if (!token)
|
||||
return res.json({ success: false, description: 'Sorry, we could not allocate a unique token. Try again?' })
|
||||
|
||||
await db.table('users')
|
||||
.insert({
|
||||
username,
|
||||
password: hash,
|
||||
token,
|
||||
enabled: 1,
|
||||
permission
|
||||
})
|
||||
utils.invalidateStatsCache('users')
|
||||
tokens.onHold.delete(token)
|
||||
|
||||
return res.json({ success: true, username, password, group })
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
return res.status(500).json({ success: false, description: 'An unexpected error occurred. Try again?' })
|
||||
}
|
||||
}
|
||||
|
||||
self.editUser = async (req, res, next) => {
|
||||
const user = await utils.authorize(req, res)
|
||||
if (!user) return
|
||||
|
2
dist/css/style.css
vendored
2
dist/css/style.css
vendored
@ -1,2 +1,2 @@
|
||||
html{background-color:#000;overflow-y:auto}body{color:#eff0f1;-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}@-webkit-keyframes fadeInOpacity{0%{opacity:0}to{opacity:1}}@keyframes fadeInOpacity{0%{opacity:0}to{opacity:1}}a{color:#209cee}a:hover{color:#67c3ff}hr{background-color:#585858}.message-body code,code{background-color:#000;border-radius:5px}.subtitle,.subtitle strong{color:#bdc3c7}.subtitle.is-brighter,.subtitle.is-brighter strong,.title{color:#eff0f1}.input,.select select,.textarea{color:#eff0f1;border-color:#585858;background-color:#000}.input::-moz-placeholder,.textarea::-moz-placeholder{color:#bdc3c7}.input::-webkit-input-placeholder,.textarea::-webkit-input-placeholder{color:#bdc3c7}.input:-moz-placeholder,.textarea:-moz-placeholder{color:#bdc3c7}.input:-ms-input-placeholder,.textarea:-ms-input-placeholder{color:#bdc3c7}.input.is-active,.input.is-focused,.input:active,.input:focus,.input:not([disabled]):hover,.select fieldset:not([disabled]) select:hover,.select select:not([disabled]):hover,.textarea.is-active,.textarea.is-focused,.textarea:active,.textarea:focus,.textarea:not([disabled]):hover,fieldset:not([disabled]) .input:hover,fieldset:not([disabled]) .select select:hover,fieldset:not([disabled]) .textarea:hover{border-color:#209cee}.input[disabled],.select fieldset[disabled] select,.select select[disabled],.textarea[disabled],fieldset[disabled] .input,fieldset[disabled] .select select,fieldset[disabled] .textarea{border-color:#585858;background-color:#2f2f2f}.label{color:#eff0f1;font-weight:400}.help{color:#bdc3c7}.progress{background-color:#585858}.button.is-info.is-hovered [class*=" icon-"]:before,.button.is-info.is-hovered [class^=icon-]:before,.button.is-info:hover [class*=" icon-"]:before,.button.is-info:hover [class^=icon-]:before{fill:#fff}.checkbox:hover,.radio:hover{color:#7f8c8d}.select:not(.is-multiple):not(.is-loading):after,.select:not(.is-multiple):not(.is-loading):hover:after{border-color:#eff0f1}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#585858}.message{background-color:#2f2f2f}.message-body{color:#eff0f1;border:0}.section.has-extra-bottom-padding{padding-bottom:6.5rem}a.floating-home-button{display:flex;position:fixed;right:1.5rem;bottom:1.5rem;border-radius:100%;background-color:#209cee;color:#fff;width:3.5rem;height:3.5rem;justify-content:center;align-items:center;transition:background-color .25s}a.floating-home-button:hover{background-color:#67c3ff;color:#fff}a.floating-home-button>.icon{margin-top:-2px}.hero.is-fullheight>.hero-body{min-height:100vh;height:100%}.hero.is-fullheight>.hero-body>.container{width:100%}
|
||||
html{background-color:#000;overflow-y:auto}body{color:#eff0f1;-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}@-webkit-keyframes fadeInOpacity{0%{opacity:0}to{opacity:1}}@keyframes fadeInOpacity{0%{opacity:0}to{opacity:1}}a{color:#209cee}a:hover{color:#67c3ff}hr{background-color:#585858}.message-body code,code{background-color:#000;border-radius:5px;font-size:1em}.subtitle,.subtitle strong{color:#bdc3c7}.subtitle.is-brighter,.subtitle.is-brighter strong,.title{color:#eff0f1}.input,.select select,.textarea{color:#eff0f1;border-color:#585858;background-color:#000}.input::-moz-placeholder,.textarea::-moz-placeholder{color:#bdc3c7}.input::-webkit-input-placeholder,.textarea::-webkit-input-placeholder{color:#bdc3c7}.input:-moz-placeholder,.textarea:-moz-placeholder{color:#bdc3c7}.input:-ms-input-placeholder,.textarea:-ms-input-placeholder{color:#bdc3c7}.input.is-active,.input.is-focused,.input:active,.input:focus,.input:not([disabled]):hover,.select fieldset:not([disabled]) select:hover,.select select:not([disabled]):hover,.textarea.is-active,.textarea.is-focused,.textarea:active,.textarea:focus,.textarea:not([disabled]):hover,fieldset:not([disabled]) .input:hover,fieldset:not([disabled]) .select select:hover,fieldset:not([disabled]) .textarea:hover{border-color:#209cee}.input[disabled],.select fieldset[disabled] select,.select select[disabled],.textarea[disabled],fieldset[disabled] .input,fieldset[disabled] .select select,fieldset[disabled] .textarea{border-color:#585858;background-color:#2f2f2f}.label{color:#eff0f1;font-weight:400}.help{color:#bdc3c7}.progress{background-color:#585858}.button.is-info.is-hovered [class*=" icon-"]:before,.button.is-info.is-hovered [class^=icon-]:before,.button.is-info:hover [class*=" icon-"]:before,.button.is-info:hover [class^=icon-]:before{fill:#fff}.checkbox:hover,.radio:hover{color:#7f8c8d}.select:not(.is-multiple):not(.is-loading):after,.select:not(.is-multiple):not(.is-loading):hover:after{border-color:#eff0f1}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#585858}.message{background-color:#2f2f2f}.message-body{color:#eff0f1;border:0}.section.has-extra-bottom-padding{padding-bottom:6.5rem}a.floating-home-button{display:flex;position:fixed;right:1.5rem;bottom:1.5rem;border-radius:100%;background-color:#209cee;color:#fff;width:3.5rem;height:3.5rem;justify-content:center;align-items:center;transition:background-color .25s}a.floating-home-button:hover{background-color:#67c3ff;color:#fff}a.floating-home-button>.icon{margin-top:-2px}.hero.is-fullheight>.hero-body{min-height:100vh;height:100%}.hero.is-fullheight>.hero-body>.container{width:100%}
|
||||
/*# sourceMappingURL=style.css.map */
|
||||
|
2
dist/css/style.css.map
vendored
2
dist/css/style.css.map
vendored
@ -1 +1 @@
|
||||
{"version":3,"sources":["css/style.css"],"names":[],"mappings":"AAAA,KACE,qBAAsB,CACtB,eACF,CAEA,KACE,aAAc,CACd,mCAA4B,CAA5B,2BACF,CAEA,iCACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,yBACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,EACE,aACF,CAEA,QACE,aACF,CAEA,GACE,wBACF,CAEA,wBAEE,qBAAsB,CACtB,iBACF,CAMA,2BACE,aACF,CAEA,0DAGE,aACF,CAEA,gCAGE,aAAc,CACd,oBAAqB,CACrB,qBACF,CAEA,qDAEE,aACF,CAEA,uEAEE,aACF,CAEA,mDAEE,aACF,CAEA,6DAEE,aACF,CAYA,qZAQE,oBACF,CAEA,yLAOE,oBAAqB,CACrB,wBACF,CAEA,OACE,aAAc,CACd,eACF,CAEA,MACE,aACF,CAEA,UACE,wBACF,CAEA,gMAIE,SACF,CAEA,6BAEE,aACF,CAMA,wGACE,oBACF,CAEA,uEAEE,oBACF,CAEA,SACE,wBACF,CAEA,cACE,aAAc,CACd,QACF,CAGA,kCACE,qBACF,CAEA,uBACE,YAAa,CACb,cAAe,CACf,YAAa,CACb,aAAc,CACd,kBAAmB,CACnB,wBAAyB,CACzB,UAAY,CACZ,YAAa,CACb,aAAc,CACd,sBAAuB,CACvB,kBAAmB,CACnB,gCACF,CAEA,6BACE,wBAAyB,CACzB,UACF,CAEA,6BACE,eACF,CAGA,+BACE,gBAAiB,CACjB,WACF,CAGA,0CACE,UACF","file":"style.css","sourcesContent":["html {\n background-color: #000;\n overflow-y: auto\n}\n\nbody {\n color: #eff0f1;\n animation: fadeInOpacity 0.5s\n}\n\n@-webkit-keyframes fadeInOpacity {\n 0% {\n opacity: 0\n }\n\n 100% {\n opacity: 1\n }\n}\n\n@keyframes fadeInOpacity {\n 0% {\n opacity: 0\n }\n\n 100% {\n opacity: 1\n }\n}\n\na {\n color: #209cee\n}\n\na:hover {\n color: #67c3ff\n}\n\nhr {\n background-color: #585858\n}\n\ncode,\n.message-body code {\n background-color: #000;\n border-radius: 5px\n}\n\n.subtitle {\n color: #bdc3c7\n}\n\n.subtitle strong {\n color: #bdc3c7\n}\n\n.title,\n.subtitle.is-brighter,\n.subtitle.is-brighter strong {\n color: #eff0f1\n}\n\n.input,\n.select select,\n.textarea {\n color: #eff0f1;\n border-color: #585858;\n background-color: #000\n}\n\n.input::-moz-placeholder,\n.textarea::-moz-placeholder {\n color: #bdc3c7\n}\n\n.input::-webkit-input-placeholder,\n.textarea::-webkit-input-placeholder {\n color: #bdc3c7\n}\n\n.input:-moz-placeholder,\n.textarea:-moz-placeholder {\n color: #bdc3c7\n}\n\n.input:-ms-input-placeholder,\n.textarea:-ms-input-placeholder {\n color: #bdc3c7\n}\n\n.input:not([disabled]):hover,\n.select fieldset:not([disabled]) select:hover,\n.select select:not([disabled]):hover,\n.textarea:not([disabled]):hover,\nfieldset:not([disabled]) .input:hover,\nfieldset:not([disabled]) .select select:hover,\nfieldset:not([disabled]) .textarea:hover {\n border-color: #209cee\n}\n\n.input.is-active,\n.input.is-focused,\n.input:active,\n.input:focus,\n.textarea.is-active,\n.textarea.is-focused,\n.textarea:active,\n.textarea:focus {\n border-color: #209cee\n}\n\n.input[disabled],\n.select fieldset[disabled] select,\n.select select[disabled],\n.textarea[disabled],\nfieldset[disabled] .input,\nfieldset[disabled] .select select,\nfieldset[disabled] .textarea {\n border-color: #585858;\n background-color: #2f2f2f\n}\n\n.label {\n color: #eff0f1;\n font-weight: normal\n}\n\n.help {\n color: #bdc3c7\n}\n\n.progress {\n background-color: #585858\n}\n\n.button.is-info.is-hovered [class^=\"icon-\"]::before,\n.button.is-info.is-hovered [class*=\" icon-\"]::before,\n.button.is-info:hover [class^=\"icon-\"]::before,\n.button.is-info:hover [class*=\" icon-\"]::before {\n fill: #fff\n}\n\n.checkbox:hover,\n.radio:hover {\n color: #7f8c8d\n}\n\n.select:not(.is-multiple):not(.is-loading)::after {\n border-color: #eff0f1\n}\n\n.select:not(.is-multiple):not(.is-loading):hover::after {\n border-color: #eff0f1\n}\n\n.select select[disabled]:hover,\nfieldset[disabled] .select select:hover {\n border-color: #585858\n}\n\n.message {\n background-color: #2f2f2f\n}\n\n.message-body {\n color: #eff0f1;\n border: 0\n}\n\n/* floating button's bottom offset + height + bottom offset */\n.section.has-extra-bottom-padding {\n padding-bottom: 6.5rem\n}\n\na.floating-home-button {\n display: flex;\n position: fixed;\n right: 1.5rem;\n bottom: 1.5rem;\n border-radius: 100%;\n background-color: #209cee;\n color: white;\n width: 3.5rem;\n height: 3.5rem;\n justify-content: center;\n align-items: center;\n transition: background-color 0.25s\n}\n\na.floating-home-button:hover {\n background-color: #67c3ff;\n color: white\n}\n\na.floating-home-button > .icon {\n margin-top: -2px\n}\n\n/* https://github.com/philipwalton/flexbugs#flexbug-3 */\n.hero.is-fullheight > .hero-body {\n min-height: 100vh;\n height: 100%\n}\n\n/* https://github.com/philipwalton/flexbugs#flexbug-2 */\n.hero.is-fullheight > .hero-body > .container {\n width: 100%\n}\n"]}
|
||||
{"version":3,"sources":["css/style.css"],"names":[],"mappings":"AAAA,KACE,qBAAsB,CACtB,eACF,CAEA,KACE,aAAc,CACd,mCAA4B,CAA5B,2BACF,CAEA,iCACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,yBACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,EACE,aACF,CAEA,QACE,aACF,CAEA,GACE,wBACF,CAEA,wBAEE,qBAAsB,CACtB,iBAAkB,CAClB,aACF,CAMA,2BACE,aACF,CAEA,0DAGE,aACF,CAEA,gCAGE,aAAc,CACd,oBAAqB,CACrB,qBACF,CAEA,qDAEE,aACF,CAEA,uEAEE,aACF,CAEA,mDAEE,aACF,CAEA,6DAEE,aACF,CAYA,qZAQE,oBACF,CAEA,yLAOE,oBAAqB,CACrB,wBACF,CAEA,OACE,aAAc,CACd,eACF,CAEA,MACE,aACF,CAEA,UACE,wBACF,CAEA,gMAIE,SACF,CAEA,6BAEE,aACF,CAMA,wGACE,oBACF,CAEA,uEAEE,oBACF,CAEA,SACE,wBACF,CAEA,cACE,aAAc,CACd,QACF,CAGA,kCACE,qBACF,CAEA,uBACE,YAAa,CACb,cAAe,CACf,YAAa,CACb,aAAc,CACd,kBAAmB,CACnB,wBAAyB,CACzB,UAAY,CACZ,YAAa,CACb,aAAc,CACd,sBAAuB,CACvB,kBAAmB,CACnB,gCACF,CAEA,6BACE,wBAAyB,CACzB,UACF,CAEA,6BACE,eACF,CAGA,+BACE,gBAAiB,CACjB,WACF,CAGA,0CACE,UACF","file":"style.css","sourcesContent":["html {\n background-color: #000;\n overflow-y: auto\n}\n\nbody {\n color: #eff0f1;\n animation: fadeInOpacity 0.5s\n}\n\n@-webkit-keyframes fadeInOpacity {\n 0% {\n opacity: 0\n }\n\n 100% {\n opacity: 1\n }\n}\n\n@keyframes fadeInOpacity {\n 0% {\n opacity: 0\n }\n\n 100% {\n opacity: 1\n }\n}\n\na {\n color: #209cee\n}\n\na:hover {\n color: #67c3ff\n}\n\nhr {\n background-color: #585858\n}\n\ncode,\n.message-body code {\n background-color: #000;\n border-radius: 5px;\n font-size: 1em\n}\n\n.subtitle {\n color: #bdc3c7\n}\n\n.subtitle strong {\n color: #bdc3c7\n}\n\n.title,\n.subtitle.is-brighter,\n.subtitle.is-brighter strong {\n color: #eff0f1\n}\n\n.input,\n.select select,\n.textarea {\n color: #eff0f1;\n border-color: #585858;\n background-color: #000\n}\n\n.input::-moz-placeholder,\n.textarea::-moz-placeholder {\n color: #bdc3c7\n}\n\n.input::-webkit-input-placeholder,\n.textarea::-webkit-input-placeholder {\n color: #bdc3c7\n}\n\n.input:-moz-placeholder,\n.textarea:-moz-placeholder {\n color: #bdc3c7\n}\n\n.input:-ms-input-placeholder,\n.textarea:-ms-input-placeholder {\n color: #bdc3c7\n}\n\n.input:not([disabled]):hover,\n.select fieldset:not([disabled]) select:hover,\n.select select:not([disabled]):hover,\n.textarea:not([disabled]):hover,\nfieldset:not([disabled]) .input:hover,\nfieldset:not([disabled]) .select select:hover,\nfieldset:not([disabled]) .textarea:hover {\n border-color: #209cee\n}\n\n.input.is-active,\n.input.is-focused,\n.input:active,\n.input:focus,\n.textarea.is-active,\n.textarea.is-focused,\n.textarea:active,\n.textarea:focus {\n border-color: #209cee\n}\n\n.input[disabled],\n.select fieldset[disabled] select,\n.select select[disabled],\n.textarea[disabled],\nfieldset[disabled] .input,\nfieldset[disabled] .select select,\nfieldset[disabled] .textarea {\n border-color: #585858;\n background-color: #2f2f2f\n}\n\n.label {\n color: #eff0f1;\n font-weight: normal\n}\n\n.help {\n color: #bdc3c7\n}\n\n.progress {\n background-color: #585858\n}\n\n.button.is-info.is-hovered [class^=\"icon-\"]::before,\n.button.is-info.is-hovered [class*=\" icon-\"]::before,\n.button.is-info:hover [class^=\"icon-\"]::before,\n.button.is-info:hover [class*=\" icon-\"]::before {\n fill: #fff\n}\n\n.checkbox:hover,\n.radio:hover {\n color: #7f8c8d\n}\n\n.select:not(.is-multiple):not(.is-loading)::after {\n border-color: #eff0f1\n}\n\n.select:not(.is-multiple):not(.is-loading):hover::after {\n border-color: #eff0f1\n}\n\n.select select[disabled]:hover,\nfieldset[disabled] .select select:hover {\n border-color: #585858\n}\n\n.message {\n background-color: #2f2f2f\n}\n\n.message-body {\n color: #eff0f1;\n border: 0\n}\n\n/* floating button's bottom offset + height + bottom offset */\n.section.has-extra-bottom-padding {\n padding-bottom: 6.5rem\n}\n\na.floating-home-button {\n display: flex;\n position: fixed;\n right: 1.5rem;\n bottom: 1.5rem;\n border-radius: 100%;\n background-color: #209cee;\n color: white;\n width: 3.5rem;\n height: 3.5rem;\n justify-content: center;\n align-items: center;\n transition: background-color 0.25s\n}\n\na.floating-home-button:hover {\n background-color: #67c3ff;\n color: white\n}\n\na.floating-home-button > .icon {\n margin-top: -2px\n}\n\n/* https://github.com/philipwalton/flexbugs#flexbug-3 */\n.hero.is-fullheight > .hero-body {\n min-height: 100vh;\n height: 100%\n}\n\n/* https://github.com/philipwalton/flexbugs#flexbug-2 */\n.hero.is-fullheight > .hero-body > .container {\n width: 100%\n}\n"]}
|
2
dist/js/dashboard.js
vendored
2
dist/js/dashboard.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/dashboard.js.map
vendored
2
dist/js/dashboard.js.map
vendored
File diff suppressed because one or more lines are too long
@ -47,6 +47,7 @@ routes.get('/filelength/config', (req, res, next) => authController.getFileLengt
|
||||
routes.post('/filelength/change', (req, res, next) => authController.changeFileLength(req, res, next))
|
||||
routes.get('/users', (req, res, next) => authController.listUsers(req, res, next))
|
||||
routes.get('/users/:page', (req, res, next) => authController.listUsers(req, res, next))
|
||||
routes.post('/users/create', (req, res, next) => authController.createUser(req, res, next))
|
||||
routes.post('/users/edit', (req, res, next) => authController.editUser(req, res, next))
|
||||
routes.post('/users/disable', (req, res, next) => authController.disableUser(req, res, next))
|
||||
routes.post('/users/delete', (req, res, next) => authController.deleteUser(req, res, next))
|
||||
|
@ -43,7 +43,8 @@ hr {
|
||||
code,
|
||||
.message-body code {
|
||||
background-color: #000;
|
||||
border-radius: 5px
|
||||
border-radius: 5px;
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
|
@ -45,6 +45,7 @@ const page = {
|
||||
},
|
||||
// config of users view
|
||||
users: {
|
||||
filters: null, // users' filters
|
||||
pageNum: null
|
||||
}
|
||||
},
|
||||
@ -325,14 +326,16 @@ page.domClick = event => {
|
||||
return page.deleteAlbum(id)
|
||||
case 'get-new-token':
|
||||
return page.getNewToken(element)
|
||||
case 'create-user':
|
||||
return page.createUser()
|
||||
case 'edit-user':
|
||||
return page.editUser(id)
|
||||
case 'disable-user':
|
||||
return page.disableUser(id)
|
||||
case 'delete-user':
|
||||
return page.deleteUser(id)
|
||||
case 'filters-help':
|
||||
return page.filtersHelp(element)
|
||||
case 'user-filters-help':
|
||||
return page.userFiltersHelp(element)
|
||||
case 'filter-uploads':
|
||||
return page.filterUploads(element)
|
||||
case 'view-user-uploads':
|
||||
@ -464,7 +467,7 @@ page.getUploads = (params = {}) => {
|
||||
<input id="filters" class="input is-small" type="text" placeholder="Filters" value="${params.filters || ''}">
|
||||
</div>
|
||||
<div class="control">
|
||||
<button type="button" class="button is-small is-primary is-outlined" title="Help?" data-action="filters-help">
|
||||
<button type="button" class="button is-small is-primary is-outlined" title="Help?" data-action="user-filters-help">
|
||||
<span class="icon">
|
||||
<i class="icon-help-circled"></i>
|
||||
</span>
|
||||
@ -943,7 +946,7 @@ page.clearSelection = () => {
|
||||
})
|
||||
}
|
||||
|
||||
page.filtersHelp = element => {
|
||||
page.userFiltersHelp = element => {
|
||||
const content = document.createElement('div')
|
||||
content.style = 'text-align: left'
|
||||
content.innerHTML = `
|
||||
@ -1798,9 +1801,34 @@ page.getUsers = (params = {}) => {
|
||||
|
||||
const pagination = page.paginate(response.data.count, 25, params.pageNum)
|
||||
|
||||
const filter = `
|
||||
<div class="column">
|
||||
<form class="prevent-default">
|
||||
<div class="field has-addons">
|
||||
<div class="control is-expanded">
|
||||
<input id="filters" class="input is-small" type="text" placeholder="Filters (WIP)" value="${params.filters || ''}" disabled>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button type="button" class="button is-small is-primary is-outlined" title="Help? (WIP)" data-action="upload-filters-help" disabled>
|
||||
<span class="icon">
|
||||
<i class="icon-help-circled"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button type="submit" class="button is-small is-info is-outlined" title="Filter users (WIP)" data-action="filter-users" disabled>
|
||||
<span class="icon">
|
||||
<i class="icon-filter"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
`
|
||||
const extraControls = `
|
||||
<div class="columns">
|
||||
<div class="column is-hidden-mobile"></div>
|
||||
${filter}
|
||||
<div class="column is-one-quarter">
|
||||
<form class="prevent-default">
|
||||
<div class="field has-addons">
|
||||
@ -1821,21 +1849,27 @@ page.getUsers = (params = {}) => {
|
||||
`
|
||||
|
||||
const controls = `
|
||||
<div class="columns is-hidden">
|
||||
<div class="column is-hidden-mobile"></div>
|
||||
<div class="columns">
|
||||
<div class="column has-text-left">
|
||||
<a class="button is-small is-primary is-outlined" title="Create user (WIP)" data-action="create-user">
|
||||
<span class="icon">
|
||||
<i class="icon-plus"></i>
|
||||
</span>
|
||||
<span>Create user</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="column has-text-right">
|
||||
<a class="button is-small is-info" title="Clear selection" data-action="clear-selection">
|
||||
<a class="button is-small is-info is-outlined" title="Clear selection" data-action="clear-selection">
|
||||
<span class="icon">
|
||||
<i class="icon-cancel"></i>
|
||||
</span>
|
||||
</a>
|
||||
<a class="button is-small is-warning" title="Bulk disable (WIP)" data-action="bulk-disable-users" disabled>
|
||||
<a class="button is-small is-warning is-outlined" title="Bulk disable (WIP)" data-action="bulk-disable-users" disabled>
|
||||
<span class="icon">
|
||||
<i class="icon-hammer"></i>
|
||||
</span>
|
||||
<span>Bulk disable</span>
|
||||
</a>
|
||||
<a class="button is-small is-danger" title="Bulk delete (WIP)" data-action="bulk-delete-users" disabled>
|
||||
<a class="button is-small is-danger is-outlined" title="Bulk delete (WIP)" data-action="bulk-delete-users" disabled>
|
||||
<span class="icon">
|
||||
<i class="icon-trash"></i>
|
||||
</span>
|
||||
@ -1856,7 +1890,7 @@ page.getUsers = (params = {}) => {
|
||||
<table class="table is-narrow is-fullwidth is-hoverable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="is-hidden"><input id="selectAll" class="checkbox" type="checkbox" title="Select all" data-action="select-all"></th>
|
||||
<th><input id="selectAll" class="checkbox" type="checkbox" title="Select all" data-action="select-all"></th>
|
||||
<th>ID</th>
|
||||
<th>Username</th>
|
||||
<th>Uploads</th>
|
||||
@ -1898,7 +1932,7 @@ page.getUsers = (params = {}) => {
|
||||
const tr = document.createElement('tr')
|
||||
tr.dataset.id = user.id
|
||||
tr.innerHTML = `
|
||||
<td class="controls is-hidden"><input type="checkbox" class="checkbox" title="Select" data-action="select"${selected ? ' checked' : ''}></td>
|
||||
<td class="controls"><input type="checkbox" class="checkbox" title="Select" data-index="${i}" data-action="select"${selected ? ' checked' : ''}></td>
|
||||
<th>${user.id}</th>
|
||||
<th${enabled ? '' : ' class="is-linethrough"'}>${user.username}</td>
|
||||
<th>${user.uploads}</th>
|
||||
@ -1948,6 +1982,82 @@ page.getUsers = (params = {}) => {
|
||||
})
|
||||
}
|
||||
|
||||
page.createUser = () => {
|
||||
const groupOptions = Object.keys(page.permissions).map((g, i, a) => {
|
||||
const disabled = !(a[i + 1] && page.permissions[a[i + 1]])
|
||||
return `<option value="${g}"${disabled ? ' disabled' : ''}>${g}</option>`
|
||||
}).join('\n')
|
||||
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = `
|
||||
<div class="field">
|
||||
<label class="label">Username</label>
|
||||
<div class="controls">
|
||||
<input id="swalUsername" class="input" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">Password (optional)</label>
|
||||
<div class="controls">
|
||||
<input id="swalPassword" class="input" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">User group</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select id="swalGroup">
|
||||
${groupOptions}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
||||
swal({
|
||||
title: 'Create new user',
|
||||
icon: 'info',
|
||||
content: div,
|
||||
buttons: {
|
||||
cancel: true,
|
||||
confirm: {
|
||||
closeModal: false
|
||||
}
|
||||
}
|
||||
}).then(proceed => {
|
||||
if (!proceed) return
|
||||
|
||||
axios.post('api/users/create', {
|
||||
username: document.querySelector('#swalUsername').value,
|
||||
password: document.querySelector('#swalPassword').value,
|
||||
group: document.querySelector('#swalGroup').value
|
||||
}).then(response => {
|
||||
if (!response) return
|
||||
|
||||
if (response.data.success === false)
|
||||
if (response.data.description === 'No token provided') {
|
||||
return page.verifyToken(page.token)
|
||||
} else {
|
||||
return swal('An error occurred!', response.data.description, 'error')
|
||||
}
|
||||
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = `
|
||||
<p>Username: <b>${response.data.username}</b></p>
|
||||
<p>Password: <code>${response.data.password}</code></p>
|
||||
<p>User group: <b>${response.data.group}</b></p>
|
||||
`
|
||||
swal({
|
||||
title: 'Created a new user!',
|
||||
icon: 'success',
|
||||
content: div
|
||||
})
|
||||
|
||||
page.getUsers(page.views.users)
|
||||
}).catch(page.onAxiosError)
|
||||
})
|
||||
}
|
||||
|
||||
page.editUser = id => {
|
||||
const user = page.cache.users[id]
|
||||
if (!user) return
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"1": "1586680111",
|
||||
"1": "1587108179",
|
||||
"2": "1581416390",
|
||||
"3": "1581416390",
|
||||
"4": "1581416390",
|
||||
|
Loading…
Reference in New Issue
Block a user