1

How can I have a Foxx service use base collections for auth operations? For example I want the User management tutorial at https://docs.arangodb.com/3.3/Manual/Foxx/Users.html to use collections "users" and "sessions" instead of "test_users" and "test_sessions", where "test" is the name of my mountpoint.

I want to run multiple services all working off the same base collections. But if I go with whats given in the tutorials, I end up with auth collections and routes which are specific to a service, which doesnt males much sense to me.

My setup.js is;

'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
});

and my index.js is;

'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 db = require('@arangodb').db;

const auth = createAuth();
const router = createRouter();
const users = db._collection('users');
const sessions = sessionsMiddleware({
storage: module.context.collection('sessions'),
transport: 'cookie'
});

module.context.use(sessions);
module.context.use(router);

// continued
router.post('/signup', function (req, res) {
    const user = {};
    try {
      user.authData = auth.create(req.body.password);
      user.username = req.body.username;
      user.perms = [];
      const meta = users.save(user);
      Object.assign(user, meta);
    } catch (e) {
      // Failed to save the user
      // We'll assume the uniqueness constraint has been violated
      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.');

I tried using const users = db._collection('users'); instead of const users = module.context.collection('users'); but that throws swagger api errors.

Rishav Sharan
  • 2,763
  • 8
  • 39
  • 55

1 Answers1

2

to achieve that you need to change the assignment of collection names from module.context.collectionName('nameOfCollection') to 'nameOfCollection' in all files, because module.context.collectionName prefixes string with name of service

so

setup.js

const sessions = 'sessions';
const users = 'users';

index.js

const users = db._collection('users');
const sessions = sessionsMiddleware({
    storage: 'sessions',
    transport: 'cookie'
});

however, that approach is antipattern for case when more services need access to same underlying collections (for example teardown of one service can delete those collections for other services).

for that case you should utilize dependencies, only your auth service should have access to its own collections and other services should have auth service as dependency and access auth data through auth service.

auth service needs to have

in manifest.json

"provides": {
    "myauth": "1.0.0"
}

in index.js or what file you pointing as main in manifest.json

module.exports = {
    isAuthorized (id) {
        return false; // your code for validating if user is authorized
    }
};

consuming service needs to have

in manifest.json

"dependencies": {
    "myauth": {
        "name": "myauth",
        "version": "^1.0.0",
        "description": "Auth service.",
        "required": true
    }
}

and then you can register it and call it

const myauth = module.context.dependencies.myauth;
if (myauth.isAuthorized()) {
    // your code
} else {
    res.throw(401);
}

for further steps in terms of authorization of requests check how to use Middleware and Session middleware

god speed

sevcik.tk
  • 514
  • 4
  • 7
  • I am very interested in the dependency-provider architecture that you recommend. Is there any repo or doc that i can read up which illustrates this in more details? – Rishav Sharan Oct 22 '18 at 07:51
  • link to doc already in answer, here in plain form https://docs.arangodb.com/3.3/Manual/Foxx/Dependencies.html – sevcik.tk Oct 22 '18 at 14:38