UNPKG

5.46 kBJavaScriptView Raw
1/**
2* vim:set sw=2 ts=2 sts=2 ft=javascript expandtab:
3*
4* # Database Module
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* ## Description
26*
27* This module consists only on a wrapper around etherpad database.
28*/
29
30module.exports = (function () {
31 'use strict';
32 // Dependencies
33 var ld = require('lodash');
34
35 var storage = {};
36
37 // Database PREFIX CONSTANTS
38 storage.DBPREFIX = { GLOBAL: 'mypads:' };
39 var DBPG = storage.DBPREFIX.GLOBAL;
40 storage.DBPREFIX.CONF = DBPG + 'conf:';
41 storage.DBPREFIX.USER = DBPG + 'user:';
42 storage.DBPREFIX.GROUP = DBPG + 'group:';
43 storage.DBPREFIX.PAD = DBPG + 'pad:';
44
45 try {
46 // Normal case : when installed as a plugin
47 storage.db = require('ep_etherpad-lite/node/db/DB').db;
48 }
49 catch (e) {
50 // Testing case : we need to mock the database connection, using ueberDB and
51 // coherent default configuration with eptherpad-lite one.
52 var ueberDB = require('ueberdb2');
53 storage.db = new ueberDB.database('dirty', { filename: './test.db' });
54 storage.db.init(function (err) { if (err) { console.error(err); } });
55 }
56
57 /**
58 * `init` function for initial configuration cache init and in memory
59 * secondary indexes. At the moment only user / logins / firstname / lastname.
60 */
61
62 storage.init = function (callback) {
63 var configuration = require('./configuration.js');
64 configuration.init(function (err) {
65 if (err) { return callback(err); }
66 var userCache = require('./model/user-cache.js');
67 userCache.init(callback);
68 });
69 };
70
71 /**
72 * ## Internal functions `fn`
73 *
74 * These functions are not private like with closures, for testing purposes,
75 * but they are expected be used only internally by other MyPads functions.
76 */
77
78 storage.fn = {};
79
80 /** ### getDelKeys
81 *
82 * `getDelKeys` is a function for multiple asynchronous gets and removes,
83 * taking :
84 *
85 * - a `del` boolean, for removals to *true*
86 * - a `keys` array, wich contains a list of keys to retrieve
87 * - a `callback` function, called if error or when finished with *null* and
88 * the `results` object, which is composed of keys and values for gets,
89 * *true* for removals
90 * FIXME: TCO ?
91 */
92
93 storage.fn.getDelKeys = function (del, keys, callback) {
94 var done;
95 var results = del ? true : {};
96 var action = del ? 'remove' : 'get';
97 var getDel = function (k) {
98 storage.db[action](k, function (err, res) {
99 if (err) { return callback(err); }
100 if (!del && !ld.isNull(res)) { results[k] = res; }
101 done();
102 });
103 };
104 done = function () {
105 if (keys.length) {
106 getDel(keys.pop());
107 } else {
108 return callback(null, results);
109 }
110 };
111 done();
112 };
113
114 /**
115 * ### getKeys
116 *
117 * `getKeys` is an helper around `storage.fn.getDelKeys` with `del` argument
118 * to *false*.
119 */
120
121 storage.fn.getKeys = ld.partial(storage.fn.getDelKeys, false);
122
123 /**
124 * ### delKeys
125 *
126 * `delKeys` is an helper around `storage.fn.getDelKeys` with `del` argument
127 * to *true*.
128 */
129
130 storage.fn.delKeys = ld.partial(storage.fn.getDelKeys, true);
131
132 /**
133 * `setKeys` is a function for multiple asynchronous sets, taking :
134 s
135 * - a `kv` object, wich contains a list a keys and values to set
136 * - a `callback` function, called if error or when finished with null
137 * FIXME: TCO ?
138 */
139
140 storage.fn.setKeys = function (kv, callback) {
141 var done;
142 var pairs = ld.pairs(kv);
143 var setK = function (k, v) { storage.db.set(k, v, done); };
144 done = function (err) {
145 if (err) { return callback(err); }
146 if (pairs.length) {
147 var pair = pairs.pop();
148 setK(pair[0], pair[1]);
149 } else {
150 return callback(null);
151 }
152 };
153 done();
154 };
155
156 /**
157 * `setKeysIfNotExists` is a function for multiple asynchronous sets if the
158 * key does not exists in database, taking :
159 s
160 * - a `kv` object, wich contains a list a keys and values to set
161 * - a `callback` function, called if error or when finished with null
162 * FIXME: TCO ?
163 */
164
165 storage.fn.setKeysIfNotExists = function (kv, callback) {
166 var done;
167 var pairs = ld.pairs(kv);
168 var setK = function (k, v) { storage.db.set(k, v, done); };
169 done = function (err) {
170 if (err) { return callback(err); }
171 if (pairs.length) {
172 var pair = pairs.pop();
173 storage.db.get(pair[0], function(err, res) {
174 if (err) { return callback(err); }
175 if (ld.isUndefined(res) || ld.isNull(res)) {
176 setK(pair[0], pair[1]);
177 } else {
178 done();
179 }
180 });
181 } else {
182 return callback(null);
183 }
184 };
185 done();
186 };
187
188 return storage;
189}).call(this);