Skip to content
Merged
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
53 changes: 53 additions & 0 deletions available-connectors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[
{
"name": "memory",
"description": "In-memory db",
"supportedByStrongLoop": true
},
{
"name": "mysql",
"description": "MySQL",
"supportedByStrongLoop": true
},
{
"name": "postgresql",
"description": "PostgreSQL",
"supportedByStrongLoop": true
},
{
"name": "oracle",
"description": "Oracle",
"supportedByStrongLoop": true
},
{
"name": "mssql",
"description": "Microsoft SQL",
"supportedByStrongLoop": true
},
{
"name": "mongodb",
"description": "MongoDB",
"supportedByStrongLoop": true
},
{
"name": "soap",
"description": "SOAP webservices",
"supportedByStrongLoop": true
},
{
"name": "rest",
"description": "REST services",
"supportedByStrongLoop": true
},

{
"name": "neo4j",
"description": "Neo4j",
"supportedByStrongLoop": false
},
{
"name": "kafka",
"description": "Kafka",
"supportedByStrongLoop": false
}
]
20 changes: 13 additions & 7 deletions connector.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ connector.loadFromFile = function() {
}

loader = connector.loader = new EventEmitter();
var done = function(err) {
if (err)
loader.emit('error', err);
else
loader.emit('complete');
cb(err);
};

// reset the cache
var cacheKeys = Object.keys(connector.cache);
Expand All @@ -35,27 +42,25 @@ connector.loadFromFile = function() {
}, {});

ConfigFile.findComponentFiles(function(err, components) {
if(err) return cb(err);
if(err) return done(err);
var componentNames = Object.keys(components);

async.each(componentNames, function(component, cb) {
async.each(componentNames, function(component, next) {
ComponentDefinition.loadIntoCache(cache, component, components, function(err) {
if(err) {
loader.emit('error', err);
return cb(err);
return next(err);
}
// commit the cache
connector.cache = cache;
connector.loader = null;
loader.emit('complete');
if(debug.enabled) {
Object.keys(cache).forEach(function(model) {
debug('setting cache %s => %j', model, Object.keys(cache[model]));
});
}
cb();
next();
});
}, cb);
}, done);
});
}

Expand All @@ -67,6 +72,7 @@ connector.find = function(model) {
var cb = args[args.length - 1];
connector.loadFromFile(function(err) {
if(err) return cb(err);
debug('reading from cache %s => %j', model, Object.keys(connector.cache[model]));
originalFind.apply(connector, args);
});
}
Expand Down
4 changes: 2 additions & 2 deletions models.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
"foreignKey": "fromModel"
},
"accessControls": {
"embed": {"as": "array"},
"embed": {"name": "acls", "as": "array"},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to change this in 2.0. "Access Control Lists" is misleading / incorrect.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I quite like permissions, it was used by 2.0 workspace API.

Unless you have time to implement that change today, I am proposing to merge this PR and make the change later.

BTW to make the migration easy, LB 2.0 should support both old (acls) and the new property when reading config files. workspace should probably support the old name too at read-time

"type": "hasMany",
"model": "ModelAccessControl",
"foreignKey": "model"
Expand Down Expand Up @@ -172,7 +172,7 @@
},
"ModelAccessControl": {
"properties": {
"method": {"type": "string", "default": "ALL"},
"property": {"type": "string"},
"route": {"type": "string"},
"principalId": {"type": "string"},
"principalType": {"type": "string"},
Expand Down
9 changes: 7 additions & 2 deletions models/definition.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var loopback = require('loopback');
var path = require('path');
var app = require('../app');
var debug = require('debug')('workspace:definition');
var ConfigFile = app.models.ConfigFile;

/**
Expand Down Expand Up @@ -94,7 +95,7 @@ Definition.getEmbededRelations = function() {
results.push({
embed: relation.embed,
model: relation.model,
as: name,
as: relation.embed.name || name,
type: relation.type,
foreignKey: relation.foreignKey
});
Expand All @@ -113,13 +114,17 @@ Definition.addRelatedToCache = function(cache, name, fileData) {

if(Array.isArray(relatedData)) {
relatedData.forEach(function(config) {
var id = config[relation.foreignKey];
var id = config[relation.foreignKey] || config.id;
config[relation.foreignKey] = name;
debug('addRelatedToCache %s %s %j', relation.model, id, config);
Entity.addToCache(cache, id, config);
});
} else if(relatedData) {
Object.keys(relatedData).forEach(function(id) {
var config = relatedData[id];
config[Entity.dataSource.idName(Entity.modelName)] = id;
config[relation.foreignKey] = name;
debug('addRelatedToCache %s %s %j', relation.model, id, config);
Entity.addToCache(cache, id, config);
});
}
Expand Down
64 changes: 44 additions & 20 deletions models/model-access-control.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var app = require('../app');
var ACL = require('loopback').ACL;
var Role = require('loopback').Role;

/**
* Represents an Access Control configuration.
Expand All @@ -19,18 +20,19 @@ var ModelAccessControl = app.models.ModelAccessControl;
* ```js
* {
* value: 'the value', // may be string or number
* humanized: 'the humanized value'
* name: 'a short name'
* }
* ```
*/

ModelAccessControl.getAccessTypes = function(cb) {
cb(null, [
{value: ACL.READ, humanized: 'Read'},
{value: ACL.WRITE, humanized: 'Write'},
{value: ACL.EXECUTE, humanized: 'Execute'}
{ name: 'All (match all types)', value: ACL.ALL },
{ name: 'Read', value: ACL.READ },
{ name: 'Write', value: ACL.WRITE },
{ name: 'Execute', value: ACL.EXECUTE },
]);
}
};

/**
* Get the available permission types.
Expand All @@ -41,20 +43,19 @@ ModelAccessControl.getAccessTypes = function(cb) {
* ```js
* {
* value: 'the value', // may be string or number
* humanized: 'the humanized value'
* name: 'a descriptive name'
* }
* ```
*/

ModelAccessControl.getPermissionTypes = function() {
ModelAccessControl.getPermissionTypes = function(cb) {
cb(null, [
{value: ACL.DEFAULT, humanized: 'Default'},
{value: ACL.ALLOW, humanized: 'Allow'},
{value: ACL.ALARM, humanized: 'Alarm'},
{value: ACL.AUDIT, humanized: 'Audit'},
{value: ACL.DENY, humanized: 'Deny'}
{ name: 'Explicitly grant access', value: ACL.ALLOW },
{ name: 'Explicitly deny access', value: ACL.DENY },
{ name: 'Generate an alarm of the access', value: ACL.ALARM },
{ name: 'Log the access', value: ACL.AUDIT },
]);
}
};

/**
* Get the available principal types.
Expand All @@ -65,16 +66,39 @@ ModelAccessControl.getPermissionTypes = function() {
* ```js
* {
* value: 'the value', // may be string or number
* humanized: 'the humanized value'
* name: 'a descriptive name'
* }
* ```
*/

ModelAccessControl.getPrincipalTypes = function() {
ModelAccessControl.getPrincipalTypes = function(cb) {
cb(null, [
{value: ACL.USER, humanized: 'User'},
{value: ACL.APP, humanized: 'App'},
{value: ACL.ROLE, humanized: 'Role'},
{value: ACL.SCOPE, humanized: 'Scope'}
{ name: 'User', value: ACL.USER },
{ name: 'App', value: ACL.APP },
{ name: 'Role', value: ACL.ROLE },
{ name: 'Scope', value: ACL.SCOPE },
]);
}
};

/**
* Get the available built-in roles.
*
* @callback {Function} callback
* @param {Error} err
* @param {Array} types An array of objects with the following format:
* ```js
* {
* value: 'the value', // may be string or number
* name: 'a descriptive name'
* }
* ```
*/
ModelAccessControl.getBuiltinRoles = function(cb) {
cb(null, [
{ name: 'All users', value: Role.EVERYONE },
{ name: 'Any unauthenticated user', value: Role.UNAUTHENTICATED },
{ name: 'Any authenticated user', value: Role.AUTHENTICATED },
{ name: 'Any user related to the object', value: Role.RELATED },
{ name: 'The user owning the object', value: Role.OWNER },
]);
};
2 changes: 2 additions & 0 deletions models/model-definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ ModelDefinition.getConfigData = function(cache, modelDef) {
var configData = {};
var relations = this.getEmbededRelations();

configData.name = modelDef.name;

relations.forEach(function(relation) {
var relatedData = getRelated(cache, modelDef.name, relation);
configData[relation.as] = formatRelatedData(relation, relatedData);
Expand Down
15 changes: 15 additions & 0 deletions models/model-property.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,18 @@ var app = require('../app');
*/

var ModelProperty = app.models.ModelProperty;

/**
* List of built-in types that can be used for `ModelProperty.type`.
* @type {string[]}
*/
ModelProperty.availableTypes = [
'string',
'number',
'boolean',
'object',
'array',
'date',
'buffer',
'geopoint'
];
18 changes: 18 additions & 0 deletions models/workspace.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,21 @@ Workspace.createFromTemplate = function(templateName, name, cb) {
template: templateName
}, cb);
}

/**
* @typedef {{name, description,supportedByStrongLoop}} ConnectorMeta
*/

/**
* @type {Array.<ConnectorMeta>}
* @internal
*/
var staticConnectorList = require('../available-connectors');

/**
* List of connectors available on npm.
* @param {function(Error=,Array.<ConnectorMeta>=)} cb
*/
Workspace.listAvailableConnectors = function(cb) {
cb(null, staticConnectorList);
};
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"version": "3.0.0",
"main": "app.js",
"scripts": {},
"scripts": {
"test": "mocha"
},
"dependencies": {
"loopback": "1.x >=1.7.0",
"async": "^0.9.0",
Expand All @@ -21,11 +23,12 @@
},
"name": "loopback-workspace",
"devDependencies": {
"loopback-testing": "~0.1.5",
"better-stack-traces": "^1.0.1",
"chai": "~1.9.1",
"grunt": "~0.4.5",
"grunt-loopback-angular": "~1.1.0",
"grunt-docular": "~0.1.2",
"better-stack-traces": "^1.0.1"
"grunt-loopback-angular": "~1.1.0",
"loopback-testing": "^0.2.0",
"mocha": "^1.20.1"
}
}
Loading