Browse Source

middleware for user

master
HerrHase 3 years ago
parent
commit
b4d7997516
10 changed files with 156 additions and 249 deletions
  1. +6
    -6
      public/js/bucket-single.js
  2. +6
    -6
      public/js/create-bucket.js
  3. +29
    -27
      public/js/users.js
  4. +3
    -3
      resources/js/components/users.riot
  5. +6
    -3
      resources/js/components/users/form.riot
  6. +3
    -3
      server.ts
  7. +0
    -149
      src/http/api/user.ts
  8. +49
    -49
      src/http/api/users.ts
  9. +51
    -0
      src/middleware/users.ts
  10. +3
    -3
      src/repositories/user.ts

+ 6
- 6
public/js/bucket-single.js View File

@ -124,7 +124,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<div expr0="expr0" class="field-error"></div>',
'<div expr2="expr2" class="field-error"></div>',
[ [
{ {
'type': bindingTypes.IF, 'type': bindingTypes.IF,
@ -135,11 +135,11 @@ __webpack_require__.r(__webpack_exports__);
return _scope.state.errors.length > 0; return _scope.state.errors.length > 0;
}, },
'redundantAttribute': 'expr0',
'selector': '[expr0]',
'redundantAttribute': 'expr2',
'selector': '[expr2]',
'template': template( 'template': template(
'<ul><li expr1="expr1"></li></ul>',
'<ul><li expr3="expr3"></li></ul>',
[ [
{ {
'type': bindingTypes.EACH, 'type': bindingTypes.EACH,
@ -170,8 +170,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
), ),
'redundantAttribute': 'expr1',
'selector': '[expr1]',
'redundantAttribute': 'expr3',
'selector': '[expr3]',
'itemName': 'error', 'itemName': 'error',
'indexName': null, 'indexName': null,


+ 6
- 6
public/js/create-bucket.js View File

@ -124,7 +124,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<div expr0="expr0" class="field-error"></div>',
'<div expr2="expr2" class="field-error"></div>',
[ [
{ {
'type': bindingTypes.IF, 'type': bindingTypes.IF,
@ -135,11 +135,11 @@ __webpack_require__.r(__webpack_exports__);
return _scope.state.errors.length > 0; return _scope.state.errors.length > 0;
}, },
'redundantAttribute': 'expr0',
'selector': '[expr0]',
'redundantAttribute': 'expr2',
'selector': '[expr2]',
'template': template( 'template': template(
'<ul><li expr1="expr1"></li></ul>',
'<ul><li expr3="expr3"></li></ul>',
[ [
{ {
'type': bindingTypes.EACH, 'type': bindingTypes.EACH,
@ -170,8 +170,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
), ),
'redundantAttribute': 'expr1',
'selector': '[expr1]',
'redundantAttribute': 'expr3',
'selector': '[expr3]',
'itemName': 'error', 'itemName': 'error',
'indexName': null, 'indexName': null,


+ 29
- 27
public/js/users.js View File

@ -124,7 +124,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<div expr0="expr0" class="field-error"></div>',
'<div expr2="expr2" class="field-error"></div>',
[ [
{ {
'type': bindingTypes.IF, 'type': bindingTypes.IF,
@ -135,11 +135,11 @@ __webpack_require__.r(__webpack_exports__);
return _scope.state.errors.length > 0; return _scope.state.errors.length > 0;
}, },
'redundantAttribute': 'expr0',
'selector': '[expr0]',
'redundantAttribute': 'expr2',
'selector': '[expr2]',
'template': template( 'template': template(
'<ul><li expr1="expr1"></li></ul>',
'<ul><li expr3="expr3"></li></ul>',
[ [
{ {
'type': bindingTypes.EACH, 'type': bindingTypes.EACH,
@ -170,8 +170,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
), ),
'redundantAttribute': 'expr1',
'selector': '[expr1]',
'redundantAttribute': 'expr3',
'selector': '[expr3]',
'itemName': 'error', 'itemName': 'error',
'indexName': null, 'indexName': null,
@ -215,7 +215,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<div class="loading-wrapper"><div expr32="expr32" class="loading"></div></div>',
'<div class="loading-wrapper"><div expr36="expr36" class="loading"></div></div>',
[ [
{ {
'type': bindingTypes.IF, 'type': bindingTypes.IF,
@ -226,8 +226,8 @@ __webpack_require__.r(__webpack_exports__);
return _scope.props.loading; return _scope.props.loading;
}, },
'redundantAttribute': 'expr32',
'selector': '[expr32]',
'redundantAttribute': 'expr36',
'selector': '[expr36]',
'template': template( 'template': template(
'<span></span><span></span><span></span>', '<span></span><span></span><span></span>',
@ -316,18 +316,18 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<div class="modal"><div class="modal__inner"><div class="modal__title center"><slot expr33="expr33" name="title"></slot></div><div expr34="expr34" class="modal__body"> </div><div class="modal__footer"><button expr35="expr35" class="button button--outline button--danger">\n Confirm\n </button><button expr36="expr36" class="button button--outline float-right">\n Reject\n </button></div></div></div>',
'<div class="modal"><div class="modal__inner"><div class="modal__title center"><slot expr32="expr32" name="title"></slot></div><div expr33="expr33" class="modal__body"> </div><div class="modal__footer"><button expr34="expr34" class="button button--outline button--danger">\n Confirm\n </button><button expr35="expr35" class="button button--outline float-right">\n Reject\n </button></div></div></div>',
[ [
{ {
'type': bindingTypes.SLOT, 'type': bindingTypes.SLOT,
'attributes': [], 'attributes': [],
'name': 'title', 'name': 'title',
'redundantAttribute': 'expr33',
'selector': '[expr33]'
'redundantAttribute': 'expr32',
'selector': '[expr32]'
}, },
{ {
'redundantAttribute': 'expr34',
'selector': '[expr34]',
'redundantAttribute': 'expr33',
'selector': '[expr33]',
'expressions': [ 'expressions': [
{ {
@ -347,8 +347,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
}, },
{ {
'redundantAttribute': 'expr35',
'selector': '[expr35]',
'redundantAttribute': 'expr34',
'selector': '[expr34]',
'expressions': [ 'expressions': [
{ {
@ -364,8 +364,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
}, },
{ {
'redundantAttribute': 'expr36',
'selector': '[expr36]',
'redundantAttribute': 'expr35',
'selector': '[expr35]',
'expressions': [ 'expressions': [
{ {
@ -471,11 +471,11 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<button expr2="expr2" class="button m-bottom-0" type="button"><slot expr3="expr3"></slot></button>',
'<button expr0="expr0" class="button m-bottom-0" type="button"><slot expr1="expr1"></slot></button>',
[ [
{ {
'redundantAttribute': 'expr2',
'selector': '[expr2]',
'redundantAttribute': 'expr0',
'selector': '[expr0]',
'expressions': [ 'expressions': [
{ {
@ -494,8 +494,8 @@ __webpack_require__.r(__webpack_exports__);
'type': bindingTypes.SLOT, 'type': bindingTypes.SLOT,
'attributes': [], 'attributes': [],
'name': 'default', 'name': 'default',
'redundantAttribute': 'expr3',
'selector': '[expr3]'
'redundantAttribute': 'expr1',
'selector': '[expr1]'
} }
] ]
); );
@ -547,7 +547,7 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('app-modal')
/** /**
* *
* @param {[type]} event
* @param {[type]} event
* @param {[type]} user * @param {[type]} user
* @return {[type]} * @return {[type]}
* *
@ -567,7 +567,7 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('app-modal')
const customEvent = new CustomEvent('open', { const customEvent = new CustomEvent('open', {
'detail': { 'detail': {
'confirm': () => { 'confirm': () => {
axios__WEBPACK_IMPORTED_MODULE_0___default().delete('/api/users/' + user._id)
axios__WEBPACK_IMPORTED_MODULE_0___default().delete('/api/users/v1/' + user._id)
.then((response) => { .then((response) => {
// removing from buckets // removing from buckets
@ -593,7 +593,7 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('app-modal')
* *
*/ */
fetch() { fetch() {
axios__WEBPACK_IMPORTED_MODULE_0___default().get('/api/users').then((response) => {
axios__WEBPACK_IMPORTED_MODULE_0___default().get('/api/users/v1').then((response) => {
this.state.users = response.data.data this.state.users = response.data.data
this.update() this.update()
}) })
@ -917,7 +917,7 @@ riot__WEBPACK_IMPORTED_MODULE_4__.mount('app-loading')
handleSubmit(event, data) { handleSubmit(event, data) {
let method = 'post' let method = 'post'
let url = '/api/users'
let url = '/api/users/v1'
// user is set and has id, send as put with id // user is set and has id, send as put with id
if (this.state.user && this.state.user._id) { if (this.state.user && this.state.user._id) {
@ -934,6 +934,8 @@ riot__WEBPACK_IMPORTED_MODULE_4__.mount('app-loading')
data: data data: data
}).then((response) => { }).then((response) => {
console.log(response)
this.state.user = response.data.data this.state.user = response.data.data
// check if submit has close-attribute // check if submit has close-attribute


+ 3
- 3
resources/js/components/users.riot View File

@ -106,7 +106,7 @@
/** /**
* *
* @param {[type]} event
* @param {[type]} event
* @param {[type]} user * @param {[type]} user
* @return {[type]} * @return {[type]}
* *
@ -126,7 +126,7 @@
const customEvent = new CustomEvent('open', { const customEvent = new CustomEvent('open', {
'detail': { 'detail': {
'confirm': () => { 'confirm': () => {
axios.delete('/api/users/' + user._id)
axios.delete('/api/users/v1/' + user._id)
.then((response) => { .then((response) => {
// removing from buckets // removing from buckets
@ -152,7 +152,7 @@
* *
*/ */
fetch() { fetch() {
axios.get('/api/users').then((response) => {
axios.get('/api/users/v1').then((response) => {
this.state.users = response.data.data this.state.users = response.data.data
this.update() this.update()
}) })


+ 6
- 3
resources/js/components/users/form.riot View File

@ -171,7 +171,7 @@
handleSubmit(event, data) { handleSubmit(event, data) {
let method = 'post' let method = 'post'
let url = '/api/users'
let url = '/api/users/v1'
// user is set and has id, send as put with id // user is set and has id, send as put with id
if (this.state.user && this.state.user._id) { if (this.state.user && this.state.user._id) {
@ -188,14 +188,17 @@
data: data data: data
}).then((response) => { }).then((response) => {
this.state.user = response.data.data
this.state.loading = false
if (response.status === 201) {
this.state.user = response.data.data
}
// check if submit has close-attribute // check if submit has close-attribute
if (event.submitter.attributes.close) { if (event.submitter.attributes.close) {
this.$('#sidebar-user-form-close').click() this.$('#sidebar-user-form-close').click()
} }
this.state.loading = false
this.update() this.update()
}) })
}, },


+ 3
- 3
server.ts View File

@ -43,11 +43,11 @@ app.set('view engine', 'html')
app.use('*', session) app.use('*', session)
app.use('/', home) app.use('/', home)
app.use('/buckets', buckets) app.use('/buckets', buckets)
app.use('/users', users) app.use('/users', users)
app.use('/api/users', usersApi)
// routes: api
app.use('/api/users/v1', usersApi)
//app.use('/api/bucket', bucketApi) //app.use('/api/bucket', bucketApi)
//app.use('/api/note', noteApi) //app.use('/api/note', noteApi)


+ 0
- 149
src/http/api/user.ts View File

@ -1,149 +0,0 @@
import { v4 } from "https://deno.land/std@0.99.0/uuid/mod.ts";
import { validate, required, isIn, maxLength } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts'
import { Database } from 'https://deno.land/x/aloedb@0.9.0/mod.ts'
import { UserSchema } from './../../stores/user.ts'
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts'
const router = Router()
/**
* get all users
*
* @param request
* @param response
* @return
*
*/
router.get('/', async function(request, response)
{
const userRepository = new UserRepository()
const users = await userRepository.db.findAll()
response.json({
data: user
})
})
/**
* create user
*
* @param request
* @param response
* @return
*
*/
router.get('/:id', async function(request, response)
{
const userRepository = new UserRepository()
const [ valid, errors ] = await validate(request.params, {
id: [ required, uuid ]
})
if (valid) {
const user = await userRepository.db.findOne({
'_id': request.params.id
})
if (!user) {
response.setStatus(404)
}
} else {
response.setStatus(405)
}
response.json({
data: user
})
})
/**
* create user
*
* @param request
* @param response
* @return
*
*/
router.post('/', async function(request, response)
{
const body = request.body
const userRepository = new UserRepository()
const [ valid, errors ] = await validate(body, {
email: [ email, required ]
})
if (valid) {
user = await userRepository.create(body)
}
response.json({
data: user
})
})
/**
*
*
* @param request
* @param response
* @return
*/
router.put('/:id', async function(request, response, next)
{
const body = request.body
const userRepository = new UserRepository()
let user = false
const [ valid, errors ] = await validate(body, {
_id: [ required, uuid, exists ],
email: [ email, required, unique ],
password: [ maxLength(64) ],
displayname: [ maxLength(128) ],
role: [ array() ]
})
if (valid) {
user = userRepository.update(body)
}
response.json({
data: user
})
})
/**
*
*
* @param request
* @param response
* @return
*
*/
router.delete('/:id', function(request, response)
{
const userRepository = new UserRepository()
let user = false
const [ valid, errors ] = await validate(request.params, {
'_id': [ required, uuid, exists ]
})
if (valid) {
user = userRepository.db.deleteOne({
'_id': request.params._id
})
}
response.json({
data: user
})
})
export default router

+ 49
- 49
src/http/api/users.ts View File

@ -1,11 +1,16 @@
import { v4 } from "https://deno.land/std@0.99.0/uuid/mod.ts";
import { validate, required, maxLength, isEmail } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts'
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts'
import UserRepository from '../../repositories/user.ts'
import { validate, required, maxLength, isEmail } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts'
import { uuid } from '../../rules/uuid.ts'
import usersMiddleware from '../../middleware/users.ts'
import UserRepository from '../../repositories/user.ts'
const router = Router() const router = Router()
// check for id and load user
router.param('id', usersMiddleware)
/** /**
* get all users * get all users
* *
@ -26,6 +31,21 @@ router.get('/', async function(request, response)
}) })
}) })
/**
* get user
*
* @param request
* @param response
* @return
*
*/
router.get('/:id', async function(request, response)
{
response.json({
data: response.locals.user
})
})
/** /**
* create user * create user
* *
@ -39,23 +59,24 @@ router.post('/', async function(request, response)
const body = request.body const body = request.body
const userRepository = new UserRepository() const userRepository = new UserRepository()
// @TODO check for permission of current user
let user let user
const [ valid, errors ] = await validate(body, { const [ valid, errors ] = await validate(body, {
email: [ isEmail, maxLength(255), required ],
password: [ required, maxLength(64) ]
email: [ isEmail, required ],
password: [ maxLength(64) ],
displayname: [ maxLength(128) ]
}) })
if (valid) { if (valid) {
user = await userRepository.create(body) user = await userRepository.create(body)
// remove password
// @TODO make sure repository can hide variables
delete user.password
} else {
response.setStatus(422)
response.json({
'errors': errors
})
} }
response.setStatus(201)
response.json({ response.json({
data: user data: user
}) })
@ -67,42 +88,30 @@ router.post('/', async function(request, response)
* @param request * @param request
* @param response * @param response
* @return * @return
*
*/ */
router.put('/:id', async function(request, response)
router.put('/:id', async function(request, response, next)
{ {
const body = request.body const body = request.body
const userRepository = new UserRepository() const userRepository = new UserRepository()
// @TODO check for permission of current user
let user let user
const [ validUser, errorsUser ] = await validate(request.params, {
'id': [ required, uuid ]
})
if (!validUser) {
response.json({
data: user
})
}
const [ valid, errors ] = await validate(body, { const [ valid, errors ] = await validate(body, {
email: [ isEmail, maxLength(255), required ],
password: [ maxLength(64) ]
email: [ isEmail, required ],
password: [ maxLength(64) ],
displayname: [ maxLength(128) ]
}) })
if (valid) { if (valid) {
body._id = request.params.id
user = await userRepository.update(body)
// remove password
// @TODO make sure repository can hide variables
delete user.password
user = await userRepository.update(response.locals.user._id, body)
} else {
response.setStatus(422)
response.json({
'errors': errors
})
} }
response.setStatus(201)
response.json({ response.json({
data: user data: user
}) })
@ -116,26 +125,17 @@ router.put('/:id', async function(request, response)
* @return * @return
* *
*/ */
router.delete('/:id', async function(request, response)
router.delete('/:id', function(request, response)
{ {
const userRepository = new UserRepository() const userRepository = new UserRepository()
// @TODO check for permission of current user
let user = false
const [ valid, errors ] = await validate(request.params, {
'id': [ required, uuid ]
// delete user
const user = userRepository.db.deleteOne({
'_id': response.locals.user._id
}) })
if (valid) {
user = userRepository.db.deleteOne({
'_id': request.params.id
})
}
response.json({
data: user
})
// send status
response.send(204)
}) })
export default router export default router

+ 51
- 0
src/middleware/users.ts View File

@ -0,0 +1,51 @@
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts'
import { validate, required } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts'
import { uuid } from '../rules/uuid.ts'
import UserRepository from '../repositories/user.ts'
const router = Router()
/**
* check every route for single bucket
*
* @param request
* @param response
* @param next
* @return
*/
async function usersMiddleware(request: any, response: any, next: any)
{
// max for id
request.params.id = request.params.id.slice(0, 128)
// only dash, numbers & letters are allowed
request.params.id = request.params.id.replace(/[^a-z0-9-]/gi, '')
const [ valid, errors ] = await validate(request.params, {
id: [ uuid ]
})
// if invalid send 404
if (!valid) {
response
.setStatus(404)
.send()
}
// getting
const userRepository = new UserRepository()
const user = await userRepository.db.findOne({ '_id': request.params.id })
// if not exists send 404
if (!user) {
response
.setStatus(404)
.send()
}
response.locals.user = user
next()
}
export default usersMiddleware

+ 3
- 3
src/repositories/user.ts View File

@ -33,16 +33,16 @@ class UserRepository
/** /**
* *
*/ */
async update(data: any)
async update(id: any, data: any)
{ {
const user = await this.db.findOne({ '_id': data._id })
const user = await this.db.findOne({ '_id': id })
// if password has changed hash password new // if password has changed hash password new
if (user && user.password !== data.password) { if (user && user.password !== data.password) {
data.password = await bcrypt.hash(data.password) data.password = await bcrypt.hash(data.password)
} }
return await this.db.updateOne({ '_id': data._id }, data)
return await this.db.updateOne({ '_id': id }, data)
} }
} }


Loading…
Cancel
Save