##Description
A COMP LISH
Yes, I know, acomplish is misspelled, but it is really a combination of:
- Comp ound.js
- Pub lish
Compound + Publish = acomplish
##Goals
Goal | Status | Notes |
Provide a working example of using CompoundJS as a Blog / CMS | In Progress | Much to Do |
Provide a Role-Based Management System for Posts, Users, and Comments | Working | See "ACL - Authorization" heading. |
Provide a working example of using CompoundJS with PassportJS, and Google as a Provider | Working | Need to add more providers, and mechanism for configuring these per each environment. |
Provide a working example of using Compound with MySQL through JugglingDB | Working | |
Provide a working example of using Compound with Redis through JugglingDB | Working | |
Provide working examples of making page views with multiple models, and balancing Async with Synchronous functionality. | Working | Might need some work. |
Provide a working example of using Unit Tests and Functional Tests (through Selenium, or a plugin TBD) | In Progress | Thinking Mocha for Unit Tests. |
[Maybe] Provide a working example of using sockets (socket.io) for Realtime Web | TBD | Could be a spin-off down the line. |
[Maybe] Provide an example/workflow for dropping in Themes for your application | TBD | Would be REALLY NICE! |
Replace WYSIHTML5 with a MarkDown Text Editor? | TBD | Would be REALLY NICE! |
##Comments Working with MySQL and Redis.
For model associations, see this post, and this post. Associated/Related models cannot be accessed en masse, but only individually. If you know of an elegant solution, without adding to the controller, but allowing for multiple relations in a view, let me know.
Another way of handling this is seeing: http://book.mixu.net/ch7.html, particularly section 7.2.1 Control flow pattern #1: Series. Mikito Takada has some really insightful documentation on the asynchronous nature of Node, and how we might solve this problem (or work nicely with this feature :-)).
Update: See method getAssociated
the application_controller for a useful way or handling associations.
Again, if you know of a more elegant solution, let me know.
##Components
- Compound.JS (formally known as Railway) is built on the ExpressJS framework.
- Templates are using ejs.
- ORM is Juggling DB.
- This example is using Twitter Bootstrap throughout, but not through a plugin.
##Models
(Currently):
- Posts: { BelongsTo: [ Users ], HasMany: [ Comments ] }
- Comments: { BelongsTo: [ Posts, Users ] }
- Users: { HasMany: [ Comments, Posts ], HABTM: [ Roles (through Memberships) ] }
- Roles: { HABTM: [ Users (through Memberships) ]}
- Memberships: { BelongsTo: [ Posts, Roles ] }
Maybe more to come, including Photos, see Picsee.
##ACL - Authorization
ACL (Access Control List) is managed by a JSON file, should you provide it. Right now, ACL is configured by a JSON file, and not through a DB Resource, but that feature could come in time.
The format for your ACL file looks like:
env
settings
cachedRoles
cachedAbilities
roles
key
displayName
description
abilities
And the JSON example:
{
"development": {
"settings": {
"cacheRoles": "true",
"cacheAbilities": "true"
},
"roles": {
"admin": {
"displayName": "Admin",
"description": "Admins can do anything",
"abilities": [{
"controller": "posts",
"actions": [
"create",
"update",
"delete"
]
}]
}
}
}
}
Authorization is determined by a User's Abilities. Abilities are a combination
of a controller
and actions
on that controller. The wildcard *
adds all
actions that a controller has. Note, actions do not necessarily equal access to
a page, but to that action, which makes authorization useful for RESTful
requests as well.
You can provide as many Roles as you want, and each Role can have multiple abilities. If a User has multiple Roles with overlapping Abilities, they are combined, and the User gets the Sum of all the Abilities.
Ex.
User
Role: Commentor
Abilities:
Controller: Comments
Actions: Create, Edit
Role: Moderator
Abilities:
Controller: Comments
Actions: Delete
In the example above, the User will be able to Create, Edit, and Delete on the Comments Controller.
###ACL Usage
To use authorization
in a controller, you must load the authorization
controller first:
load('authorization');
...and then use it like:
before(use('authorize'));
You have 3 choices:
- Use
authorization
everywhere - Use
authorization
on all actions on a controller - Use
authorization
on specific actions in a controller
Everywhere:
In the application_controller
add the following line near the top:
before(use('authorize'));
All Controller Actions: In any controller, add the following line near the top**:
before(use('authorize'));
Specific Controller Actions: In any controller, add the following line near the top**:
before(use('authorize'), only: ['destroy', 'create']);
**Remember to load('authorization')
at the top of you controller to use it.
###Cached Roles / Abilities
Use the cache at your own discretion. What it basically means is that if the
cached vars (cacheRoles
, cacheAbilities
) are set to true
, then they will
not be reloaded when the page is loaded. This is great for performance, but
unless you update the session.user
object when Roles and Abilities are
added/removed, the User will keep his or her permissions until the next time
they log in. This could be a security threat for your app, YMMV.
##Install
-
Clone Repo
git clone [this repo url]
-
Install Modules
npm install -l
-
Set up confs, see the
config/acomplish/*.json
confs. -
Add your (or someone's) email address to the
settings.json
file in the config/acomplish directory. Owners override ACL, so any email addresses that you put in this array can do anything in the app, regardless of authorization. -
Create DB (See DB Setup Below)
compound db migrate
-
Run Server
node server.js
ORforever server.js
mysql> CREATE DATABASE acomplish;
mysql> GRANT ALL PRIVILEGES ON acomplish.* TO "dbuser"@"localhost" IDENTIFIED BY "dbpasswd";
mysql> FLUSH PRIVILEGES;
mysql> EXIT
Note, redis
is definitely supported, documentation needed here for
redis
support.
##Contribute
Let me know if you would like to participate, or fork/pull.
###Thanks
- Anatoliy Chakkaev, this is built on top of the CompoundJS Framework
##License The MIT License (MIT)
Copyright (c) 2013 Daniel Lochrie
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.