-
Notifications
You must be signed in to change notification settings - Fork 4
microcommunity
MicroCommunity is a project that aims to build an open source social networking platform, built as a modular system where developers can mix plugins supporting features such as diverse content types production, content organization and curation and collaboration styles. The goal is to make it easy for developers easily create dedicated platforms that encourage content production and knowledge exchange in small-scale communities, or MicroCommunities! We think that those communities for a majority in the online Arab community.
The current model behind MicroCommunity is about allowing you to create collections of content and users called containers. You can customize those collections by defining new content types, and assigning new membership roles to those users. The model also has the flexibility to allow you to to customize the organization, creation and appearance of those containers.
You can as well consider your website as a one global container. You can have a hybrid approach where you allow a global context next to containers which could be of several types as well.
The final goal is to allow you as a developer to easily develop social experience that exactly match the needs of your community/organization with ease and joy.
var microcommunity = require('microcommunity')
microcommunity.registerApp(__dirname)
var app = microcommunity.createApplication(__dirname)
//instance configuration
app.listen(3000) microcommunity.registerPlugin(__dirname)
//global configuration
module.exports = function(options){
var app = microcommunity.createPlugin(__dirname)
//instance configuration
return app
}Using a plugin by an application
var microcommunity = require('microcommunity')
var plugin = require('microcmmunity-plugin')
microcommunity.registerApp(__dirname)
//global configuration
module.exports = function(){
var app = microcommunity.createApplication(__dirname)
app.use(plugin({ option1 : 'value', option2 : 'value' }))
//instance configuration
return app
}You basically extend an app or a plugin by creating pages with dynamic features or Apps and extending the JSON API of your website.
On the server side, you should describe the mounting point of your app.
//main app
app.get('/', function(req, res){
res.loadPage('myapp', { message : 'Hello, World!'})
})In the views directory you should provide the server side template (here it is in jade). The template represents the server template of your app. Here you declare the main regions of your app. Your template is going to be integrated with the main layout of the website. You
You can access the passed data using the global server.data object
h1 = server.data.messageFinally you should provide the javascript app object. Here you place your logic. You should place the app module in the client/apps directory, so the system can identify it and run it in the web page once it is loaded.
define(['app'], function(App){
App.addInitializer(function(){
console.log(server.data.message)
})
return App
})Extending the JSON API of your website is so much easy thanks to the flexibility of Node and Express.
app.post('/api/request/path', function(req, res){
res.send(200, { message : 'JSON API'})
}var postSchema = new mongoose.Schema({})
microcommunity.models.define('Post', 'post', 'posts', postSchema)Calling a model and creating an instance
var Post = microcommunity.model('Post')
var new_post = new Post({ content : 'Hello, MicroCommunity!' })On the server side, you should create a new model and use the isItem plugin
var microcommunity = require('microcommunity')
, isItem = microcommunity.models.plugins.isItem
var postSchema = new mongoose.Schema({})
postSchema.plugin(isItem)
microcommunity.models.define('Post', 'post', 'posts', postSchema)Then you should register the client model Registering an item
microcommunity.items.addItem('Post', 'path/to/client/model')You should define a client model for an item. Which will have four attributes: contentView, messageTemplate, pluginView, and actions
var Post = Item.extend({
contentView : PostView,
messageTemplate : messageTemplate,
pluginView : Comments,
actions : [
{ label : 'Comment', name : 'comment' }
]
})On the server side you should use the hasWall and hasStream plugin
var hasWall = microcommunity.models.plugins.hasWall
, hasStream = microcommunity.models.plugins.hasStream
// ... schema definition
userSchema.plugin(hasWall, { displayNameAttribute : 'displayName', wallType : 'user' })
userSchema.plugin(hasStream)To load the wall or a stream of an item, use the loadItems method on the stream or wall model.
User.findById(id, function(err, user){
Wall.loadItems(user.wall, function(err, items){
res.loadPage("yourApp", {items : items})
})
})On the client side you should use the Stream App module. This can be both used with a stream or with a wall.
var options = { items : server.data.items, type : "stream" }
var Stream = streamModule(App, App.stream, options)You usually use a Publisher with a wall in order to create.
var options = {
wall : App.currentUser.get('wall'),
publishers : [PostPublisher, PhotoPublisher]
}
var Publisher = publiserhModule(App, App.publisher, options) In order to define a publisher, you should use the following interface. You should implement an exportData method, that should return an object that includes the set of item attributes after you retrieve them from the form controls.
var PostPublisher = Backbone.Marionette.ItemView.extend({
// ... other view options
exportData : function(){
return {
content : this.ui.content.val()
}
}
})
return {
objectType : 'post',
icon : 'icon-pencil',
label : 'Post',
view : PostPublisher
}Authentication is provided by default. You can check if user is logged in on server side using the ensureAuthenticated middleware. The user object is attached to the request object as req.user
app.get('/some/path', auth.ensureAuthenticated, function(req, res){
})On the client side you can use the isLoggedIn method.
if (App.isLoggedIn()) //your codeGlobal roles for your users is supported as well. You need to configure basic information in the site.json file in your app directory.
{
"rootUser" : "[email protected]",
"roles" : ["student", "teacher"],
"defaultRole" : "student"
}You can access the user role user.role. You are also provided with helper methods. On server you can use these middlewares to ensure the user has the root role, or has a specific role.
//ensure root role
app.get('/root/area', auth.ensureRoot, function(req, res){
})
//ensure teacher role
app.get('/teacher/area', auth.ensureRole('teacher'), function(req, res){
})On the client side, you have the corresponding methods.
if (App.isRootUser()) //code for root user
if (App.hasRole('teacher')) //code for teacherMicroCommunity uses an action-based authorization system. A user can be 'authorized' to perform a certain action on a certain type of object. Special information will be attached to that object that will help you implement functional security in your application, both on the server side and client side.
An example of authorizing the current user to delete an item.
var can = require('microcommunity').can
can.authorizeCollection(item, 'item', 'delete', req.user, function(err, item){
console.log(item.can.comment) //result will be true
}) You can use a middleware as well. It will return an error code if the current user does not have the sufficient privileges for the specified action. However, you should fetch that object from the database by another middleware and providing it as an attribute of the request object, with the objectType name. In this example the item should be at req.item.
app.delete('/api/items/:item/', fetchItem, can.authorizeMiddlewareAPI('item', 'delete'),function(req, res){
//request handler code
})If you send this object to the client. There is a tiny Backbone helper method that you can call:
Item.can('delete') //trueDefining the code to handle the authorization is easy. Registration is as follows:
microcommunity.can.define('item', 'delete', authorizationHandler)The handler will be passed the user how is going to be authorized, the object on which the authorization will occur and the action to be authorized, and callback to be called (which allows you to perform asynchronous authorization).
function authorizationHandler(item, user, callback){
//performing authorization
}In order to perform the actual authorization, you need to use the authorization helper attachAction. You pass the action you need to authorize or de-authorize.
var helpers = microcommuity.can.helper
function authorizationHandler(item, user, callback){
helpers.attachAction(item, 'delete', false)
callback(null, item)
}You should first define your model as a container.
var isContainer = microcommunity.models.plugins.isContainer
var groupSchema = new mongoose.Schema({ /* schema definition */ })
var containerOptions = {
containerType : 'group',
displayNameAttribute : 'displayName'
}
groupSchema.plugin(isContainer, containerOptions)
microcommunity.models.define('Group', 'group', 'containers', groupSchema)//ensure some role in the container
app.get('/some/comtainer/:container/path', auth.ensureContainerRole('role'), function(req, res){
})
//ensure member
app.get('/some/comtainer/:container/path', auth.ensureContainerMember('role'), function(req, res){
})
//ensure admin
app.get('/some/comtainer/:container/path', auth.ensureContainerAdmin('role'), function(req, res){
})On the client side:
if (App.hasContainerRole('role')) //some role in the container
if (App.isContainerMember()) //container member
if (App.isContainerAdmin()) //container adminIn order to make a user a member of a container you should create a mbmership object first, then assign the roles you want to that user.
container.newMembership(req.user)
container.addRole(req.user, 'mc:admin') //granting adminstration role
container.addRole(req.user, 'mc:member') //granting basic membership role
container.save(function(err){
})In order to make a content part of a container you only need to use the isContent plugin, and provide the container attribute to the object.