Open eliasmalik opened 7 years ago
@eliascodes are there already some ideas/plan on how to split the application?
Some thoughts:
Abase will consist on a single plugin which itself is composed of several other plugins, which have isolated functionality.
Ideally, what is currently in the "pages" field would be minimised, and most of the information necessary to render a view would be inferred from the user model.
In addition, we would define a default user model, so that the user would need minimum configuration.
TBD
var path = require('path');
var Abase = require('abase');
var schemaPath = path.join(__dirname, 'schema.json');
var dbConnection = process.env.DATABASE_URL;
server.register({
register: abase, options: { schemaPath: schemaPath, dbConnection: dbConnection }
}, function (err) {
if (err) {
throw err;
}
// ...
});
var fs = require('fs');
var abaseDb = require ('abase-db');
var abaseRoutes = require ('abase-routes');
var abaseValidation = require('abase-validation');
var abaseRender = require('abase-render');
var abasePermissions = require('abase-permissions');
var schemaParser = require('./parser.js');
exports.register = function (server, options, next) {
fs.readFile(options.schemaPath, 'utf8', function (readErr, result) {
if (readErr) {
next(readErr);
}
// Does some (potentially arbitrary) processing of the schema and
// attaches it to the server settings object
server.settings.app.abase = schemaParser(result);
// Registers all child plugins
server.register([
{ register: abaseDb, options: options },
{ register: abaseRoutes, options: options },
{ register: abaseValidation, options: options }
{ register: abaseRender, options: options }
{ register: abasePermissions, options: options }
], next);
});
}
var pg = require('pg');
var db = require('./db.js');
exports.register = function (server, options, next) {
var connection = db.parse(options.dbConnection);
var client = new pg.Client(connection);
// initialise (or migrate) DB
db.init(client, server.settings.app.abase, function (dbError) {
client.end();
if (dbError) {
next(dbError);
}
// Attach db helper functions to the reply object
// should we use server.decorate instead?
server.ext('onPreHandler', function (request, reply) {
reply.abase = { db: db };
reply.continue();
});
next();
});
}
exports.register = function (server, options, next) {
server.dependency(
['abase-validation', 'abase-render', 'abase-permissions'],
function (_server, _next) {
var schema = _server.settings.app.abase;
server.route({
method: 'GET',
path: '/user/details',
handler: { // abase-render provides an object handler definition interface
form: {
email: { label: 'Email:' },
username: { label: 'Username' }
}
},
config: {
auth: {
access: { // abase-permissions decorates server with abasePermissions
scope: _server.abasePermissions(schema, ['email', 'username']);
}
},
// abase-validation decorates server with abaseValidate
validation: _server.abaseValidate(schema, ['email', 'username']);
}
});
_next();
}
);
next();
}
Permissions can be handled two ways I think: as above, the /user/details
route would be restricted to users who have permissions to see the email
and username
fields, as defined in the JSON config. The other way is to not restrict views, but instead restrict the fields that are rendered on the view as a function of request scope.
Thoughts welcome.
From @nelsonic
This issue is to discuss migrating the architecture of the app away from a monolith and towards something more modular (probably with a hierarchy of components).