UNPKG

5.56 kBJavaScriptView Raw
1/**
2* vim:set sw=2 ts=2 sts=2 ft=javascript expandtab:
3*
4* # Common for Models
5*
6* ## License
7*
8* Licensed to the Apache Software Foundation (ASF) under one
9* or more contributor license agreements. See the NOTICE file
10* distributed with this work for additional information
11* regarding copyright ownership. The ASF licenses this file
12* to you under the Apache License, Version 2.0 (the
13* "License"); you may not use this file except in compliance
14* with the License. You may obtain a copy of the License at
15*
16* http://www.apache.org/licenses/LICENSE-2.0
17*
18* Unless required by applicable law or agreed to in writing,
19* software distributed under the License is distributed on an
20* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21* KIND, either express or implied. See the License for the
22* specific language governing permissions and limitations
23* under the License.
24*/
25
26module.exports = (function() {
27 'use strict';
28
29 // Dependencies
30 var ld = require('lodash');
31 var crypto = require('crypto');
32 var storage = require('../storage.js');
33
34 /**
35 * ## Description
36 *
37 * This module regroups shared functions for several models.
38 */
39
40 var common = {};
41
42 /**
43 * ### hashPassword
44 *
45 * `hashPassword` is an asynchronous function that use `crypto.randomBytes` to
46 * generate a strong `salt` if needed and return a `sha512` `hash` composed of
47 * the `salt` and the given `password`. It takes
48 *
49 * - an optional `salt` string
50 * - the mandatory `password` string
51 * - a `callback` function which returns an object with `hash`ed password and
52 * the `salt`.
53 */
54
55 common.hashPassword = function (salt, password, callback) {
56 crypto.randomBytes(40, function (ex, buf) {
57 if (ex) { return callback(ex); }
58 salt = salt || buf.toString('hex');
59 var sha512 = crypto.createHash('sha512');
60 sha512.update(salt);
61 callback(null, {
62 salt: salt,
63 hash: sha512.update(password).digest('hex')
64 });
65 });
66 };
67
68 /**
69 * ### addSetInit
70 *
71 * This function throws errors for common parameters missing or mistyped.
72 * It takes three arguments :
73 *
74 * - a `params` JS object
75 * - a `callback` function
76 * - a n optional `strFields` array, with fields of the `params` objects that
77 * must be not empty strings with at most 100 characters (ueberdb limit for
78 * SQL backends)
79 */
80
81 common.addSetInit = function (params, callback, strFields) {
82 if (!ld.isObject(params)) {
83 throw new TypeError('BACKEND.ERROR.TYPE.PARAMS_REQUIRED');
84 }
85 if (!ld.isFunction(callback)) {
86 throw new TypeError('BACKEND.ERROR.TYPE.CALLBACK_FN');
87 }
88 if (!ld.isUndefined(params._id)) {
89 if (!ld.isString(params._id) || (ld.isEmpty(params._id))) {
90 throw new TypeError('BACKEND.ERROR.TYPE.ID_STR');
91 }
92 }
93 if (strFields) {
94 var isFS = function (s) { return (ld.isString(s) && !ld.isEmpty(s)); };
95 ld.forEach(strFields, function (s) {
96 if (!isFS(params[s])) {
97 throw new TypeError('BACKEND.ERROR.TYPE.PARAM_STR');
98 }
99 if (s.length > 100) {
100 throw new TypeError('BACKEND.ERROR.TYPE.STR_100');
101 }
102 });
103 }
104 };
105
106 /**
107 * ### checkExistence
108 *
109 * `checkExistence` is an asynchronous function that takes
110 *
111 * - a database `key`
112 * - a `callback` function, returnning an *Error* or a boolean for existence
113 */
114
115 common.checkExistence = function (key, callback) {
116 storage.db.get(key, function(err, res) {
117 if (err) { return callback(err); }
118 return callback(null, !!res);
119 });
120 };
121
122 /**
123 * ### checkMultiExist
124 *
125 * `checkMultiExist` is an asynchronous function that uses
126 * `common.checkExistence` to check multiple keys.
127 * It takes :
128 *
129 * - an array of `keys`
130 * - a `callback` function, returning an Error or *null* and a boolean for
131 * existence.
132 *
133 * At the first not found record, callback will be called.
134 * FIXME: TCO ?
135 */
136
137 common.checkMultiExist = function (keys, callback) {
138 var done = function (err, res) {
139 if (keys.length) {
140 if (err) { return callback(err); }
141 if (!res) { return callback(null, res); }
142 common.checkExistence(keys.pop(), done);
143 } else {
144 return callback(null, res);
145 }
146 };
147 done(null, true);
148 };
149
150 /**
151 * ### getDel
152 *
153 * Model common reading
154 *
155 * This function takes mandatory arguments
156 *
157 * - a `del` boolean, to add a second step, removal, in the case of *true*
158 * - a `PREFIX`, used to compute real key
159 * - a `key`, the unique identifier of the object
160 * - a `callback` function, that returns an error if there is a problem or if
161 * the key is not found. In the other case, it returns *null* if `del` or
162 * *null* plus the model object.
163 */
164
165 common.getDel = function (del, PREFIX, key, callback) {
166 if (!ld.isString(key)) {
167 throw new TypeError('BACKEND.ERROR.TYPE.KEY_STR');
168 }
169 if (!ld.isFunction(callback)) {
170 throw new TypeError('BACKEND.ERROR.TYPE.CALLBACK_FN');
171 }
172 key = PREFIX + key;
173 storage.db.get(key, function (err, obj) {
174 if (err) { return callback(err); }
175 if (ld.isUndefined(obj) || ld.isNull(obj)) {
176 return callback(new Error('BACKEND.ERROR.CONFIGURATION.KEY_NOT_FOUND'));
177 }
178 if (!del) {
179 return callback(null, obj);
180 } else {
181 storage.db.remove(key, function (err) {
182 if (err) { return callback(err); }
183 return callback(null, obj);
184 });
185 }
186 });
187 };
188
189 return common;
190
191}).call(this);