mirror of https://gitee.com/bigwinds/arangodb
126 lines
3.4 KiB
Plaintext
126 lines
3.4 KiB
Plaintext
!CHAPTER User management
|
|
|
|
Foxx does not provide any user management out of the box but it is very easy to roll your own solution:
|
|
|
|
The [session middleware][SESSIONS] provides mechanisms for adding session logic to your service, using e.g. a collection or JSON Web Tokens to store the sessions between requests.
|
|
|
|
The [auth module][AUTH] provides utilities for basic password verification and hashing.
|
|
|
|
The following example service demonstrates how user management can be implemented using these basic building blocks.
|
|
|
|
!SECTION Setting up the collections
|
|
|
|
Let's say we want to store sessions and users in collections. We can use the setup script to make sure these collections are created before the service is mounted.
|
|
|
|
First add a setup script to your manifest if it isn't already defined:
|
|
|
|
```json
|
|
"scripts": {
|
|
"setup": "scripts/setup.js"
|
|
}
|
|
```
|
|
|
|
Then create the setup script with the following content:
|
|
|
|
```js
|
|
'use strict';
|
|
const db = require('@arangodb').db;
|
|
const sessions = module.context.collectionName('sessions');
|
|
const users = module.context.collectionName('users');
|
|
|
|
if (!db._collection(sessions)) {
|
|
db._createDocumentCollection(sessions);
|
|
}
|
|
|
|
if (!db._collection(users)) {
|
|
db._createDocumentCollection(users);
|
|
}
|
|
|
|
db._collection(users).ensureIndex({
|
|
type: 'hash',
|
|
fields: ['username'],
|
|
unique: true
|
|
});
|
|
```
|
|
|
|
!SECTION Creating the router
|
|
|
|
The following main file demonstrates basic user management:
|
|
|
|
```js
|
|
'use strict';
|
|
const joi = require('joi');
|
|
const createAuth = require('@arangodb/foxx/auth');
|
|
const createRouter = require('@arangodb/foxx/router');
|
|
const sessionsMiddleware = require('@arangodb/foxx/sessions');
|
|
|
|
const auth = createAuth();
|
|
const router = createRouter();
|
|
const users = module.context.collection('users');
|
|
const sessions = sessionsMiddleware({
|
|
storage: module.context.collection('sessions'),
|
|
transports: ['cookie']
|
|
});
|
|
module.context.use(sessions);
|
|
module.context.use(router);
|
|
|
|
router.get('/whoami', function (req, res) {
|
|
try {
|
|
const user = users.document(req.sessions.uid);
|
|
res.send({username: user.username});
|
|
} catch (e) {
|
|
res.send({username: null});
|
|
}
|
|
})
|
|
.description('Returns the currently active username.');
|
|
|
|
router.post('/login', function (req, res) {
|
|
let user = users.firstExample({
|
|
username: req.bodyParams.username
|
|
});
|
|
const valid = auth.verify(
|
|
user ? user.authData : {},
|
|
req.bodyParams.password
|
|
);
|
|
if (!valid) res.throw('unauthorized');
|
|
req.session.uid = user._key;
|
|
req.sessionStorage.save(req.session);
|
|
res.send({sucess: true});
|
|
})
|
|
.body(joi.object({
|
|
username: joi.string().required(),
|
|
password: joi.string().required()
|
|
}).required(), 'Credentials')
|
|
.description('Logs a registered user in.');
|
|
|
|
router.post('/logout', function (req, res) {
|
|
if (req.session.uid) {
|
|
req.session.uid = null;
|
|
req.sessionStorage.save(req.session);
|
|
}
|
|
res.send({success: true});
|
|
})
|
|
.description('Logs the current user out.');
|
|
|
|
router.post('/signup', function (req, res) {
|
|
const user = req.body;
|
|
try {
|
|
const meta = users.save(user);
|
|
Object.assign(user, meta);
|
|
} catch (e) {
|
|
res.throw('bad request', 'Username already taken', e);
|
|
}
|
|
req.session.uid = user._key;
|
|
req.sessionStorage.save(req.session);
|
|
res.send({success: true});
|
|
})
|
|
.body(joi.object({
|
|
username: joi.string().required(),
|
|
password: joi.string().required()
|
|
}).required(), 'Credentials')
|
|
.description('Creates a new user and logs them in.');
|
|
```
|
|
|
|
[AUTH]: ./Auth.md
|
|
[SESSIONS]: ./Sessions/README.md
|