diff --git a/public/js/bucket-single.js b/public/js/bucket-single.js
index 6dfa499..6202e9e 100644
--- a/public/js/bucket-single.js
+++ b/public/js/bucket-single.js
@@ -124,7 +124,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent
) {
return template(
- '
',
+ '',
[
{
'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(
- '',
+ '',
[
{
'type': bindingTypes.EACH,
@@ -170,8 +170,8 @@ __webpack_require__.r(__webpack_exports__);
]
),
- 'redundantAttribute': 'expr1',
- 'selector': '[expr1]',
+ 'redundantAttribute': 'expr3',
+ 'selector': '[expr3]',
'itemName': 'error',
'indexName': null,
diff --git a/public/js/create-bucket.js b/public/js/create-bucket.js
index f1c7276..240d618 100644
--- a/public/js/create-bucket.js
+++ b/public/js/create-bucket.js
@@ -124,7 +124,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent
) {
return template(
- '',
+ '',
[
{
'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(
- '',
+ '',
[
{
'type': bindingTypes.EACH,
@@ -170,8 +170,8 @@ __webpack_require__.r(__webpack_exports__);
]
),
- 'redundantAttribute': 'expr1',
- 'selector': '[expr1]',
+ 'redundantAttribute': 'expr3',
+ 'selector': '[expr3]',
'itemName': 'error',
'indexName': null,
diff --git a/public/js/users.js b/public/js/users.js
index 36584f5..1c850ce 100644
--- a/public/js/users.js
+++ b/public/js/users.js
@@ -124,7 +124,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent
) {
return template(
- '',
+ '',
[
{
'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(
- '',
+ '',
[
{
'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(
- '',
+ '',
[
{
'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(
'',
@@ -316,18 +316,18 @@ __webpack_require__.r(__webpack_exports__);
getComponent
) {
return template(
- '',
+ '',
[
{
'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(
- '',
+ '',
[
{
- '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
diff --git a/resources/js/components/users.riot b/resources/js/components/users.riot
index 24ecc78..bacfdc6 100644
--- a/resources/js/components/users.riot
+++ b/resources/js/components/users.riot
@@ -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()
})
diff --git a/resources/js/components/users/form.riot b/resources/js/components/users/form.riot
index 678271f..1c25655 100644
--- a/resources/js/components/users/form.riot
+++ b/resources/js/components/users/form.riot
@@ -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()
})
},
diff --git a/server.ts b/server.ts
index be24fe2..ad17609 100644
--- a/server.ts
+++ b/server.ts
@@ -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)
diff --git a/src/http/api/user.ts b/src/http/api/user.ts
deleted file mode 100644
index 3e8975e..0000000
--- a/src/http/api/user.ts
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/src/http/api/users.ts b/src/http/api/users.ts
index 521909a..d0ee128 100644
--- a/src/http/api/users.ts
+++ b/src/http/api/users.ts
@@ -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
\ No newline at end of file
diff --git a/src/middleware/users.ts b/src/middleware/users.ts
new file mode 100644
index 0000000..01ac836
--- /dev/null
+++ b/src/middleware/users.ts
@@ -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
\ No newline at end of file
diff --git a/src/repositories/user.ts b/src/repositories/user.ts
index 3e8ffb9..c7225ad 100644
--- a/src/repositories/user.ts
+++ b/src/repositories/user.ts
@@ -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)
}
}