Skip to content
This repository was archived by the owner on Jan 6, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
language: node_js

node_js:
- "8"
19 changes: 19 additions & 0 deletions docs/webapis.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Admin APIs

```
GET /v1/admin/users - query users
POST /v1/admin/users - create new user
GET /v1/admin/users/:id - get user info & settings
POST /v1/admin/users/:id - update user settings
POST /v1/admin/users/:id/suspend - suspend a user account
Expand Down Expand Up @@ -320,6 +321,24 @@ Response body:

Scope: `admin:users`

### POST /v1/admin/users

Create a new user as admin. Skips email verification.

Request body:

Username is the only required field.

```
{
email: String
username: String
password: String
}
```

Scope: `admin:users`

### GET /v1/admin/users/:id

Response body:
Expand Down
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ module.exports = function (config) {
// =

app.get('/v1/admin/users', cloud.api.admin.listUsers)
app.post('/v1/admin/users', cloud.api.admin.createUser)
app.get('/v1/admin/users/:id', cloud.api.admin.getUser)
app.post('/v1/admin/users/:id', cloud.api.admin.updateUser)
app.post('/v1/admin/users/:id/suspend', cloud.api.admin.suspendUser)
Expand Down
53 changes: 53 additions & 0 deletions lib/apis/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,59 @@ module.exports = class AdminAPI {
res.json(user)
}

async createUser (req, res) {
// check perms
if (!res.locals.session) throw new UnauthorizedError()
if (!res.locals.session.scopes.includes('admin:users')) throw new ForbiddenError()

// validate & sanitize input
req.checkBody('username')
.isAlphanumeric().withMessage('Can only be letters and numbers.')
.isLength({ min: 3, max: 16 }).withMessage('Must be 3 to 16 characters.')
req.checkBody('email', 'Must be a valid email').optional()
.isEmail()
.isLength({ min: 3, max: 100 })
req.checkBody('password', 'Must be 6 to 100 characters.').optional()
.isLength({ min: 6, max: 100 })
;(await req.getValidationResult()).throw()
var {username, email, password} = req.body

var release = await lock('users')
try {
// check email & username availability
let error = false
if (email && await this.usersDB.isEmailTaken(email)) {
error = {
message: 'Email is not available',
emailNotAvailable: true
}
} else if (await this.usersDB.isUsernameTaken(username)) {
error = {
message: 'Username is not available',
usernameNotAvailable: true
}
}

// render error
if (error) {
return res.status(422).json(error)
}

// create user record
var record = await this.usersDB.create({
username,
email,
password
})
} finally {
release()
}

// respond
res.status(201)
res.json({id: record.id, email: record.email})
}

async updateUser (req, res) {
// check perms
if (!res.locals.session) throw new UnauthorizedError()
Expand Down
39 changes: 39 additions & 0 deletions test/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,45 @@ test('get user', async t => {
t.is(res.body.username, testUser.username)
})

test('create new user via admin without email', async t => {
var res = await app.req.post({
uri: '/v1/admin/users',
json: {
username: 'bobita'
},
auth
})
t.is(res.statusCode, 201, '201 created user')

res = await app.req.get({
uri: '/v1/admin/users/bobita',
json: true,
auth
})
t.is(res.statusCode, 200, '200 got')
t.is(res.body.username, 'bobita', 'is created')
})

test('create new user via admin with email', async t => {
var res = await app.req.post({
uri: '/v1/admin/users',
json: {
username: 'bobitaToo',
email: '[email protected]'
},
auth
})
t.is(res.statusCode, 201, '201 created user')

res = await app.req.get({
uri: '/v1/admin/users/bobitaToo',
json: true,
auth
})
t.is(res.statusCode, 200, '200 got')
t.is(res.body.username, 'bobitaToo', 'is created')
})

test('fully update carla', async t => {
var res = await app.req.post({
uri: '/v1/admin/users/carla',
Expand Down