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


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

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


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

@ -124,7 +124,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent
) {
return template(
'<div expr0="expr0" class="field-error"></div>',
'<div expr2="expr2" class="field-error"></div>',
[
{
'type': bindingTypes.IF,
@ -135,11 +135,11 @@ __webpack_require__.r(__webpack_exports__);
return _scope.state.errors.length > 0;
},
'redundantAttribute': 'expr0',
'selector': '[expr0]',
'redundantAttribute': 'expr2',
'selector': '[expr2]',
'template': template(
'<ul><li expr1="expr1"></li></ul>',
'<ul><li expr3="expr3"></li></ul>',
[
{
'type': bindingTypes.EACH,
@ -170,8 +170,8 @@ __webpack_require__.r(__webpack_exports__);
]
),
'redundantAttribute': 'expr1',
'selector': '[expr1]',
'redundantAttribute': 'expr3',
'selector': '[expr3]',
'itemName': 'error',
'indexName': null,
@ -215,7 +215,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent
) {
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,
@ -226,8 +226,8 @@ __webpack_require__.r(__webpack_exports__);
return _scope.props.loading;
},
'redundantAttribute': 'expr32',
'selector': '[expr32]',
'redundantAttribute': 'expr36',
'selector': '[expr36]',
'template': template(
'<span></span><span></span><span></span>',
@ -316,18 +316,18 @@ __webpack_require__.r(__webpack_exports__);
getComponent
) {
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,
'attributes': [],
'name': 'title',
'redundantAttribute': 'expr33',
'selector': '[expr33]'
'redundantAttribute': 'expr32',
'selector': '[expr32]'
},
{
'redundantAttribute': 'expr34',
'selector': '[expr34]',
'redundantAttribute': 'expr33',
'selector': '[expr33]',
'expressions': [
{
@ -347,8 +347,8 @@ __webpack_require__.r(__webpack_exports__);
]
},
{
'redundantAttribute': 'expr35',
'selector': '[expr35]',
'redundantAttribute': 'expr34',
'selector': '[expr34]',
'expressions': [
{
@ -364,8 +364,8 @@ __webpack_require__.r(__webpack_exports__);
]
},
{
'redundantAttribute': 'expr36',
'selector': '[expr36]',
'redundantAttribute': 'expr35',
'selector': '[expr35]',
'expressions': [
{
@ -471,11 +471,11 @@ __webpack_require__.r(__webpack_exports__);
getComponent
) {
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': [
{
@ -494,8 +494,8 @@ __webpack_require__.r(__webpack_exports__);
'type': bindingTypes.SLOT,
'attributes': [],
'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
* @return {[type]}
*
@ -567,7 +567,7 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('app-modal')
const customEvent = new CustomEvent('open', {
'detail': {
'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) => {
// removing from buckets
@ -593,7 +593,7 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('app-modal')
*
*/
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.update()
})
@ -917,7 +917,7 @@ riot__WEBPACK_IMPORTED_MODULE_4__.mount('app-loading')
handleSubmit(event, data) {
let method = 'post'
let url = '/api/users'
let url = '/api/users/v1'
// user is set and has id, send as put with id
if (this.state.user && this.state.user._id) {
@ -934,6 +934,8 @@ riot__WEBPACK_IMPORTED_MODULE_4__.mount('app-loading')
data: data
}).then((response) => {
console.log(response)
this.state.user = response.data.data
// 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
* @return {[type]}
*
@ -126,7 +126,7 @@
const customEvent = new CustomEvent('open', {
'detail': {
'confirm': () => {
axios.delete('/api/users/' + user._id)
axios.delete('/api/users/v1/' + user._id)
.then((response) => {
// removing from buckets
@ -152,7 +152,7 @@
*
*/
fetch() {
axios.get('/api/users').then((response) => {
axios.get('/api/users/v1').then((response) => {
this.state.users = response.data.data
this.update()
})


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

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


+ 3
- 3
server.ts View File

@ -43,11 +43,11 @@ app.set('view engine', 'html')
app.use('*', session)
app.use('/', home)
app.use('/buckets', buckets)
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/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 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()
// check for id and load user
router.param('id', usersMiddleware)
/**
* 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
*
@ -39,23 +59,24 @@ router.post('/', async function(request, response)
const body = request.body
const userRepository = new UserRepository()
// @TODO check for permission of current user
let user
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) {
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({
data: user
})
@ -67,42 +88,30 @@ router.post('/', async function(request, response)
* @param request
* @param response
* @return
*
*/
router.put('/:id', async function(request, response)
router.put('/:id', async function(request, response, next)
{
const body = request.body
const userRepository = new UserRepository()
// @TODO check for permission of current 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, {
email: [ isEmail, maxLength(255), required ],
password: [ maxLength(64) ]
email: [ isEmail, required ],
password: [ maxLength(64) ],
displayname: [ maxLength(128) ]
})
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({
data: user
})
@ -116,26 +125,17 @@ router.put('/:id', async function(request, response)
* @return
*
*/
router.delete('/:id', async function(request, response)
router.delete('/:id', function(request, response)
{
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

+ 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 (user && user.password !== 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