• Stars
    star
    216
  • Rank 176,952 (Top 4 %)
  • Language
    JavaScript
  • Created almost 11 years ago
  • Updated over 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Express middleware to provide schema-less REST APIs for creating a social networking website primarily using angular.js. It comes with built-in authentication, authorization and notification features.

social-cms-backend

Build Status npm version

Express middleware to provide schema-less REST APIs for creating a social networking website primarily using angular.js. It comes with built-in authentication, authorization and notification features.

Motivation

There exists several MVC framework libraries for node.js that are inspired by Rails. But they might be a bit outdated, when it comes to angular.js, client-side MVW framework. I would like to propose a maybe new style of web programming, which is the combination of a domain-specific REST API library (ready to use, no coding required) and client-side coding.

This project is to provide such a library for a web site like SNS/Twitter/Facebook in a closed/private environment.

How to install

$ npm install social-cms-backend

Examples

The followings are minimal example code that uses social-cms-backend.

Screencast

How to create a Twitter clone in 15 minutes

Screencast preview (quadruple speed):

Preview

Controllable screencast at normal speed

Notes:

  • There is a typo found after the recording. /javascript/main.js -> /javascripts/main.js
  • The resulting code is available here

How to use

Minimal configuration with local authentication

var express = require('express');
var SCB = require('social-cms-backend');
var app = express();
app.use(SCB.middleware({
  mongodb_url: 'mongodb://localhost:27017/socialcmsdb',
  passport_strategy: 'local'
}));
app.listen(3000);

Typical configuration with Facebook authentication:

var express = require('express');
var SCB = require('social-cms-backend');
var app = express();
app.use(SCB.middleware({
  mongodb_url: 'mongodb://localhost:27017/socialcmsdb',
  passport_strategy: 'facebook',
  facebook_app_id: process.env.FACEBOOK_APP_ID,
  facebook_app_secret: process.env.FACEBOOK_APP_SECRET
}));
app.listen(3000);

Notice two environment variables which have to be obtrained from https://developers.facebook.com/ and set properly. Refer Facebook Doc for more information.

Configuration with socket.io v1.0:

var http = require('http');
var express = require('express');
var socket_io = require('socket.io');
var expressSession = require('express-session');
var SCB = require('social-cms-backend');
var app = express();
var SCB_options = {
  mongodb_url: 'mongodb://localhost:27017/socialcmsdb',
  session_middleware: expressSession({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: true
  }),
  passport_strategy: 'facebook',
  facebook_app_id: process.env.FACEBOOK_APP_ID,
  facebook_app_secret: process.env.FACEBOOK_APP_SECRET
};
app.use(SCB.middleware(SCB_options));
var server = http.createServer(app);
var sio = socket_io(server);
sio.use(SCB.socket_io(SCB_options));
server.listen(3000);

Configuration for HTTP DIGEST strategy:

var SCB_options = {
  mongodb_url: 'mongodb://localhost:27017/socialcmsdb',
  passport_strategy: 'digest',
  auth_digest: {
    realm: 'my_realm'
  }
};

Configuration with BreezeJS support:

var SCB_options = {
  mongodb_url: 'mongodb://localhost:27017/socialcmsdb',
  breeze_mongo: true,
  routes: [{
    object_type: 'user',
    object_prefix: '/breeze-service/users'
  }, {
    object_type: 'post',
    object_prefix: '/breeze-service/posts'
  }, {
    object_prefix: '/breeze-service/SaveChanges'
  }]
};

Login APIs

The login API for Facebook authenticate is the following:

GET /login/facebook

Typically, the HTML would look like this:

<a href="/login/facebook">Login</a>

In the case of DIGEST authentication, the API is:

GET /login/digest

The way to create a user for DIGEST authentication is:

POST /adduser/digest
Content-Type: application/json
Content-Length: ...

{"name":"...","passhash":"...","initdata":"{...}"}

REST APIs

By default, there are 4 object types:

  • user
  • group
  • post
  • like

The following is the example of the post object endpoint.

List post objects

GET /posts?query=...

The "query" query parameter is a MongoDB query parameter object that is stringified (probably by JSON.stringify).

  • skip and limit query parameters are also supported.

Get one post object

GET /posts/123

The "123" is the _id of the post.

Save a new post

POST /posts

The body is an object (JSON format) without system preserved properties such as _id, system, created_time, owner, meta.

Update a post

PUT /posts/123

The body is a MongoDB update object (JSON format) using update operators.

Delete a post

DELETE /posts/123

Count posts

GET /posts/count?query=...

This is a special endpoint.

Get following posts

GET /posts/inbox

This is a special endpoint to only get posts that matches with predefined "following". More description follows in the next section.

Aggregate Posts

GET /posts/aggregate?pipeline=...

This is a special endpoint to use MongoDB aggregate command. The "pipeline" query parameter is a MongoDB pipeline parameter object that is stringified (probably by JSON.stringify).

User and Group

User objects can also be accessed by REST API. For example, all user list can be fetched by

GET /users

unless othrewise restricted.

To get login user information, use this special endpoint.

GET /users/myself

To create a group, save a group object like the following:

{
  members: [
    { user_id: 111 },
    { user_id: 112 },
    { user_id: 113 }
  ]
}

The user_id is the _id attribute of a user object.

You can also define nested groups like the following:

{
  members: [
    { user_id: 111 },
    { group_id: 211 },
    { group_id: 212 }
  ]
}

The group_id is the _id attribute of a group object.

Access Control

Object read permission is handled by the scope attribute. For example, if an object has the scope like this,

{
  data: { ... },
  scope: [
    { user_id: 111 },
    { group_id: 211 }
  ]
}

this object can only be accessed by the user user_id=111 and all members of the group group_id=211. Notice data attribute is just an example.

Object write permission is based on ownership, which means an object can only be updated by the user who first saved.

These access control can be customized by hasPermission SCB option.

Followings and Followers

There is a special endpoint inbox. if an object has destination property and if a user follows that destination, that object is added to the user inbox. For example, suppose a user with user_id=111 follows another user with user_id=112, a user object will be

{
  _id: 111,
  following: [{
    user_id: 112
  }]
}

and if an object has destination like the following

{
  destination: [{
    user_id: 112
  }]
}

the user with user_id=111 will see this object in one's own inbox.

A user can also follow a group, in this case the user object would look like the following.

{
  _id: 111,
  following: [{
    group_id: 211
  }]
}

There is an SCB option always_follow_myself and if it is true, it is equivalent to having a user user_id=111 object like

{
  _id: 111,
  following: [{
    user_id: 111
  }]
}

for all users.

Push by socket.io

If an object has a destination property and a user follows it, the server pushes the object to to the user by socket.io, if socket.io is configured properly (See the example in "How To Use").

For example, if a "post" object like the following is inserted;

{
  destination: [{
    group_id: 211
  }]
}

all the users who follow group_id=211 will receive the whole object as a message identified by new-post. So the clients of the users are expected to listen to it by the following.

socket.on('new-post', function(data) {
  //do something with data
});

Extension to JSON format

Sometimes, we want to encode JavaScript objects in JSON. We have a special notion for Date and RegExp like the following.

{"key1":"val1","key2":"/Date(12345)/"} //12345 is milliseconds

{"key3":"val3","key4":"/RegExp([A-Z][a-z]+)/"}

Defining Object Types

The examples above are all about the post object. You can define any objects and their routes in an SCB option.

routes: [{
  object_type: 'user',
  object_prefix: '/rest/users'
}, {
  object_type: 'group',
  object_prefix: '/rest/groups'
}, {
  object_type: 'article',
  object_prefix: '/rest/articles'
}, {
  object_type: 'comment',
  object_prefix: '/rest/comments'
}, {
  object_type: 'like',
  object_prefix: '/rest/likes'
}]

However, keeping user and group objects are always required for authentication and authorization.

If you want to create a unique index, you can define it in an SCB option.

ensure_unique_index: {
  object_type: 'like',
  object_fields: ['owner', 'article_id']
}

This will restrict one "like" at most for one article for each user.

TODOs

  • Notification: email

More Repositories

1

waku

⛩️ The minimal React framework
TypeScript
3,473
star
2

react-tracked

State usage tracking with Proxies. Optimize re-renders for useState/useReducer, React Redux, Zustand and others.
TypeScript
2,594
star
3

use-context-selector

React useContextSelector hook in userland
TypeScript
2,414
star
4

excalidraw-animate

A tool to animate Excalidraw drawings
TypeScript
1,121
star
5

react-hooks-global-state

[NOT MAINTAINED] Simple global state for React with Hooks API without Context API
TypeScript
1,104
star
6

react-hooks-worker

React custom hooks for web workers
TypeScript
696
star
7

proxy-memoize

Intuitive magical memoization library with Proxy and WeakMap
TypeScript
667
star
8

will-this-react-global-state-work-in-concurrent-rendering

Test tearing and branching in React concurrent rendering
JavaScript
541
star
9

reactive-react-redux

[NOT MAINTAINED] React Redux binding with React Hooks and Proxy
TypeScript
502
star
10

react-hooks-async

[NOT MAINTAINED] React custom hooks for async functions with abortability and composability
JavaScript
497
star
11

excalidraw-claymate

A tool based on Excalidraw to create stop motion animations and slides.
TypeScript
457
star
12

react-hooks-fetch

Minimal data fetching library with React Suspense
TypeScript
398
star
13

react-worker-components

React Worker Components simplify using Web Workers
TypeScript
315
star
14

react-suspense-fetch

[NOT MAINTAINED] A low-level library for React Suspense for Data Fetching
TypeScript
296
star
15

katachidraw

SVG based drawing tool and react-native component
TypeScript
282
star
16

redux-in-worker

Entire Redux in Web Worker
TypeScript
258
star
17

proxy-compare

Compare two objects using accessed properties with Proxy
TypeScript
252
star
18

valtio-yjs

valtio-yjs makes yjs state easy
TypeScript
177
star
19

use-reducer-async

React useReducer with async actions
TypeScript
176
star
20

connect-prerenderer

Express/connect middleware to pre-render ajax page for non-ajax browsers, especially using angular.js
JavaScript
161
star
21

typescript-expo-apollo-boilerplate

[NOT MAINTAINED] Clean boilerplate for TypeScript + Expo (React Native) + React Apollo (GraphQL)
TypeScript
145
star
22

es-beautifier

[NOT MAINTAINED] ECMAScript beautifier based on eslint
JavaScript
121
star
23

zustand-signal

Another React binding for Zustand
TypeScript
109
star
24

use-atom

Yet another implementation for Jotai atoms without side effects
TypeScript
108
star
25

create-react-signals

A factory function to create signals for React
TypeScript
107
star
26

remote-faces

A tool for Working From Home: Share your webcam images with your colleagues
JavaScript
94
star
27

react-suspense-router

[NOT MAINTAINED] React Router for React Suspense and Render-as-You-Fetch
TypeScript
88
star
28

continuation.js

A module for tail call optimization by Continuation Passing Style (CPS) transformation with trampoline technique for Node.js
JavaScript
77
star
29

rss-pipes

RSS feed aggregator by Node.js
JavaScript
74
star
30

derive-zustand

A function to create a derived Zustand store from stores
TypeScript
71
star
31

use-zustand

Another custom hook to use Zustand vanilla store
TypeScript
57
star
32

lets-compare-global-state-with-react-hooks

Comparing global state libraries with React Hooks
57
star
33

easy-livereload

Express middleware to use livereload2 easily (both server and client)
JavaScript
56
star
34

codeonmobile

A coding tool on mobile devices targeting GitHub/Codeship/Heroku
JavaScript
55
star
35

valtio-signal

Another React binding for Valtio proxy state
TypeScript
50
star
36

connect-cache-manifest

Express/connect middleware to generate HTML5 cache manifest file.
JavaScript
49
star
37

use-signals

An experimental React hook for TC39 signals
JavaScript
40
star
38

notes-app-sample

A sample HTML5 web app using social-cms-backend (the BMEAN stack)
JavaScript
33
star
39

excalidraw-gallery

A tool to display Excalidraw drawings
JavaScript
32
star
40

express-react-redux

Express middleware for React/Redux applications
JavaScript
30
star
41

svelte3-redux

[NOT MAINTAINED] Redux for Svelte 3
TypeScript
30
star
42

excalidraw-layers

A tool to view layers of Excalidraw drawings
TypeScript
26
star
43

react-suspense-worker

[NOT MAINTAINED] React Suspense for Web Worker with Comlink
TypeScript
26
star
44

react-native-dom-expo

[NOT MAINTAINED] A patch library to make Expo work with react-native-dom
JavaScript
25
star
45

react-context-global-state

[NOT MAINTAINED] Simple global state for React with Context API
JavaScript
23
star
46

gqless-hook

[NOT MAINTAINED] Yet another React hook for gqless
TypeScript
22
star
47

use-valtio

Another custom hook to use Valtio proxy state
TypeScript
21
star
48

react-hooks-render-props

[NOT MAINTAINED] A hacking custom hook to emulate render props
JavaScript
18
star
49

benchmark-octane

Octane benchmark for Node.js
JavaScript
18
star
50

recoildux

[NOT MAINTAINED] Recoil inspired implementation with Redux
TypeScript
16
star
51

react-compose-state

A helper function to attach state to stateless function components
JavaScript
16
star
52

gunosy-rss

[OBSOLETE] Gunosy RSS feed web service by Node.js
JavaScript
15
star
53

apollo-link-lazy

Apollo Link for lazy loading
JavaScript
14
star
54

react-suspense-router-demo

[NOT MAINTAINED] A demo app with react-suspense-router
TypeScript
11
star
55

react-apollo-github-api-infinite-scroll-example

React Apollo GitHub GraphQL API infinite scroll example code
JavaScript
11
star
56

twitter-clone-sample

JavaScript
7
star
57

blog

Personal blog
Less
6
star
58

waku-vercel-starter

TypeScript
5
star
59

meteor-fan

HTML
4
star
60

dai-shi

3
star
61

waku-netlify-starter

TypeScript
3
star
62

minimal-apollo-example

Minimal Apollo stack example code
JavaScript
2
star
63

react-compose-onmount

A helper function to attach onmount handler to stateless function components
JavaScript
2
star
64

GBrain

A Google AppEngine web app for sharing brains.
Java
1
star
65

meteor-blaze-showhide

Handy block helpers for show/hide functionality in Blaze
JavaScript
1
star
66

meteor-google-maps-example

JavaScript
1
star
67

meteor-blaze-google-maps

Easy Blaze template for Google Maps with reactivity
JavaScript
1
star
68

meteor-facebook-server-api

A Meteor package to provide Facebook Graph API
JavaScript
1
star