Pad Model

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.

module.exports = do ->

Dependencies

  ld = require 'lodash'
  cuid = require 'cuid'
  common = require './common.js'
  storage = require '../storage.js'
  PPREFIX = storage.DBPREFIX.PAD
  UPREFIX = storage.DBPREFIX.USER
  GPREFIX = storage.DBPREFIX.GROUP

Description

The pad module contains business logic for private pads. These belong to groups and can have their own visibility settings.

A pad can be viewed as an object like :

var pad = { _id: 'autoGeneratedUniqueString', name: 'title', group: 'idOfTheLinkedGroup', visibility: 'restricted', users: ['u1', 'u2'], password: null, readonly: true };

  pad = {}

Internal functions

These functions are not private like with closures, for testing purposes, but they are expected be used only internally by other MyPads functions. They are tested through public functions and API.

  pad.fn = {}

assignProps

assignProps takes params object and assign defaults if needed. It creates :

null fields are intented to tell MyPads that group properties should be applied here. assignProps returns the pad object.

  pad.fn.assignProps = (params) ->
    p = params
    u = name: p.name, group: p.group
    if p.visibility is 'restricted' and ld.isArray(p.users)
      u.users = ld.filter p.users, ld.isString
    else
      u.users = []
    vVal = ['restricted', 'private', 'public']
    v = p.visibility
    isValidVisib = ld.isString(v) and ld.includes(vVal, v)
    u.visibility = if isValidVisib then v else null
    u.password = if ld.isString p.password then p.password else null
    u.readonly = if ld.isBoolean p.readonly then p.readonly else null
    return u

checkSet

checkSet is an async function that ensures that all given users exist. If true, it calls fn.set, else it will return an Error. It takes :

  pad.fn.checkSet = (p, callback) ->
    keys = ld.map p.users, (v) -> UPREFIX + v
    keys.push GPREFIX + p.group
    common.checkMultiExist keys, (err, res) ->
      return callback err if err
      e = 'pad group or at least one of the users are not found'
      return callback new Error e if not res
      pad.fn.set p, callback

indexGroups

indexGroups is an asynchronous function which handles secondary indexes for group.pads after pad creation, update, removal. It takes :

  pad.fn.indexGroups = (del, pad, callback) ->
    _set = (g) ->
      storage.db.set GPREFIX + g._id, g, (err) ->
        return callback err if err
        callback null
    storage.db.get GPREFIX + pad.group, (err, g) ->
      return callback err if err
      if del
        ld.pull g.pads, pad._id
        _set g
      else
        if not ld.includes g.pads, pad._id
          g.pads.push pad._id
          _set g
        else
          callback null

set

set is internal function that sets the pad into the database.

It takes, as arguments :

  pad.fn.set = (p, callback) ->
    storage.db.set PPREFIX + p._id, p, (err) ->
      return callback err if err
      pad.fn.indexGroups false, p, (err) ->
        return callback err if err
        callback null, p

Public functions

get

This function uses common.getDel with del to false and PPREFIX fixed. It will takes mandatory key string and callback function. See common.getDel for documentation.

  pad.get = ld.partial common.getDel, false, PPREFIX

set

This function adds a new pad or updates properties of an existing one. It checks the fields, throws error if needed, sets defaults options. As arguments, it takes mandatory :

TODO: ensure user has the right to link this group (admin)

  pad.set = (params, callback) ->
    common.addSetInit params, callback, ['name', 'group']
    p = pad.fn.assignProps params
    if params._id
      p._id = params._id
      common.checkExistence PPREFIX + p._id, (err, res) ->
        return callback err if err
        return callback new Error 'pad does not exist' if not res
        pad.fn.checkSet p, callback
    else
      p._id = cuid()
      pad.fn.checkSet p, callback

del

This function uses common.getDel with del to false and PPREFIX fixed. It will takes mandatory key string and callback function. See common.getDel for documentation.

It uses the callback function to handle secondary indexes for groups.

  pad.del = (key, callback) ->
    if not ld.isFunction callback
      throw new TypeError 'callback must be a function'
    common.getDel true, PPREFIX, key, (err, p) ->
      return callback err if err
      pad.fn.indexGroups true, p, callback

Helpers functions

TODO Helper here are public functions created to facilitate interaction with the API and improve performance avoiding extra checking.

  return pad