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.
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
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 :
setFn
bounded function targetted the original set
from the module
used in the case of this public APIkey
and value
that has been given to the setFn
functionreq
and res
express request and response 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 :
delFn
bounded function targetted the original del
method from the
module usedreq
and res
express parameters, with mandatory
req.params.key. 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()
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'
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)
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)
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)
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