API Module

License

Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Description

This module holds all public functions, used for the API of mypads. Please refer to binded function when no details are given.

External dependencies

ld = require 'lodash'
passport = require 'passport'

Local dependencies

conf = require './configuration.js'
user = require './model/user.js'
group = require './model/group.js'
pad = require './model/pad.js'
auth = require './auth.js'

module.exports = do ->

  api = {}
  api.initialRoute = '/mypads/api/'

init is the first function that takes an Express app as argument. It initializes all API requirements, particularly mypads routes.

  api.init = (app) ->
    auth.init app
    authAPI app
    configurationAPI app
    userAPI app
    groupAPI app
    padAPI app

Internal functions helpers

These functions are not private like with closures, for testing purposes, but they are expected be used only internally by other MyPads functions.

  fn = {}

get internal takes a mandatory module argument to call its get method. Otherwise, it will use req.params.key to get the database record.

  fn.get = (module, req, res) ->
    try
      module.get req.params.key, (err, val) ->
        return res.send 404, error: err.message, key: req.params.key if err
        res.send key: req.params.key, value: val
    catch e
      res.send 400, error: e.message

set internal takes :

  fn.set = (setFn, key, value, req, res) ->
    try
      setFn (err, data) ->
        return res.send 400, { error: err.message } if err
        res.send success: true, key: key or data._id, value: data or value
    catch e
      res.send 400, error: e.message

del internal takes four arguments :

  fn.del = (delFn, req, res) ->
    key = req.params.key
    delFn key, (err) ->
      return res.send 404, { error: err.message } if err
      res.send success: true, key: key

ensureAuthentificated internal is an Express middleware takes req, res and next. It returns error or lets the next middleware go.

  fn.ensureAuthentificated = (req, res, next) ->
    if not req.isAuthenticated() and not req.session.login
      res.send 401, error: 'you must be authenticated'
    else
      next()

Authentificaton API

  authAPI = (app) ->
    authRoute = "#{api.initialRoute}auth"

POST method : login, method returning user object minus password if auth is a success, plus fixes a login session.

Sample URL: http://etherpad.ndd/mypads/api/auth/login

    app.post "#{authRoute}/login", (req, res, next) ->
      passport.authenticate('local', (err, user, info) ->
        return res.send 400, { error: err.message } if err
        return res.send 400, { error: info.message } if not user
        req.login user, (err) ->
          req.session.login = user.login
          return res.send 400, { error: err } if err
          res.send 200, success: true, user: ld.omit(user, 'password')
      )(req, res, next)

GET method : logout, method that destroy current req.session and logout from passport.

Sample URL: http://etherpad.ndd/mypads/api/auth/logout

    app.get "#{authRoute}/logout", (req, res) ->
      if req.isAuthenticated() or req.session.login
        req.logout()
        req.session.destroy()
        res.send 200, success: true
      else
        res.send 400, error: 'not authenticated'

Configuration API

All methods needs fn.ensureAuthentificated

  configurationAPI = (app) ->
    confRoute = "#{api.initialRoute}configuration"

GET method : get all configuration

Sample URL: http://etherpad.ndd/mypads/api/configuration

    app.get confRoute, fn.ensureAuthentificated, (req, res) ->
      conf.all (err, value) ->
        return res.send 400, { error: err } if err
        res.send value: value

GET method : configuration.get key

Sample URL: http://etherpad.ndd/mypads/api/configuration/something

    app.get "#{confRoute}/:key", fn.ensureAuthentificated, (req, res) ->
      conf.get req.params.key, (err, value) ->
        return res.send 404, { error: err.message, key: req.params.key } if err
        res.send key: req.params.key, value: value

POST/PUT methods : configuration.set key and value on initial

Sample URL for POST: http://etherpad.ndd/mypads/api/configuration for PUT http://etherpad.ndd/mypads/api/configuration/something

    _set = (req, res) ->
      key = if req.method is 'POST' then req.body.key else req.params.key
      value = req.body.value
      setFn = ld.partial conf.set, key, value
      fn.set setFn, key, value, req, res

    app.post confRoute, fn.ensureAuthentificated, _set
    app.put "#{confRoute}/:key", fn.ensureAuthentificated, _set

DELETE method : configuration.del key

Sample URL: http://etherpad.ndd/mypads/api/configuration/something

    app.delete "#{confRoute}/:key", fn.ensureAuthentificated,
      ld.partial(fn.del, conf.del)

User API

All methods needs fn.ensureAuthentificated

  userAPI = (app) ->
    userRoute = "#{api.initialRoute}user"

GET method : user.get login (key)

Sample URL: http://etherpad.ndd/mypads/api/user/someone

    app.get "#{userRoute}/:key", fn.ensureAuthentificated,
      ld.partial(fn.get, user)

set for POST and PUT, see below

    _set = (req, res) ->
      value = req.body
      if req.method is 'POST'
        key = req.body.login
      else
        key = req.params.key
        value.login = key
        value._id = user.ids[key]
      setFn = ld.partial user.set, value
      fn.set setFn, key, value, req, res

POST method : user.set with user value for user creation

Sample URL: http://etherpad.ndd/mypads/api/user

    app.post userRoute, fn.ensureAuthentificated, _set

PUT method : user.set with user key/login plus value for existing user

Sample URL: http://etherpad.ndd/mypads/api/user/someone

    app.put "#{userRoute}/:key", fn.ensureAuthentificated, _set

DELETE method : user.del with user key/login

Sample URL: http://etherpad.ndd/mypads/api/user/someone

    app.delete "#{userRoute}/:key", fn.ensureAuthentificated,
      ld.partial(fn.del, user.del)

Group API

All methods needs fn.ensureAuthentificated

  groupAPI = (app) ->
    groupRoute = "#{api.initialRoute}group"

GET method : group.get unique id

Sample URL: http://etherpad.ndd/mypads/api/group/xxxx

    app.get "#{groupRoute}/:key", fn.ensureAuthentificated,
      ld.partial(fn.get, group)

set for POST and PUT, see below

    _set = (req, res) ->
      setFn = ld.partial group.set, req.body
      fn.set setFn, req.body._id, req.body, req, res

POST method : group.set with user value for group creation

Sample URL: http://etherpad.ndd/mypads/api/group

    app.post groupRoute, fn.ensureAuthentificated, _set

PUT method : group.set with group id plus value for existing group

Sample URL: http://etherpad.ndd/mypads/api/group/xxx

    app.put "#{groupRoute}/:key", fn.ensureAuthentificated, _set

DELETE method : group.del with group id

Sample URL: http://etherpad.ndd/mypads/api/group/xxxx

    app.delete "#{groupRoute}/:key", fn.ensureAuthentificated,
      ld.partial(fn.del, group.del)

Pad API

All methods needs fn.ensureAuthentificated

  padAPI = (app) ->
    padRoute = "#{api.initialRoute}pad"

GET method : pad.get unique id

Sample URL: http://etherpad.ndd/mypads/api/pad/xxxx

    app.get "#{padRoute}/:key", fn.ensureAuthentificated,
      ld.partial(fn.get, pad)

set for POST and PUT, see below

    _set = (req, res) ->
      setFn = ld.partial pad.set, req.body
      fn.set setFn, req.body._id, req.body, req, res

POST method : pad.set with user value for pad creation

Sample URL: http://etherpad.ndd/mypads/api/pad

    app.post padRoute, fn.ensureAuthentificated, _set

PUT method : pad.set with group id plus value for existing pad

Sample URL: http://etherpad.ndd/mypads/api/pad/xxx

    app.put "#{padRoute}/:key", fn.ensureAuthentificated, _set

DELETE method : pad.del with pad id

Sample URL: http://etherpad.ndd/mypads/api/pad/xxxx

    app.delete "#{padRoute}/:key", fn.ensureAuthentificated,
      ld.partial(fn.del, pad.del)

  return api