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