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 |
|
26 | module.exports = (function() {
|
27 | ;
|
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);
|