Source: stores/memory.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/*jslint plusplus: true, devel: true, nomen: true, node: true, indent: 4, maxerr: 50 */

"use strict";

var Strings     = require("../strings"),
    util        = require("../util"),
    async       = require("async");

/**
 * Constructor for Memory rule store.
 *
 * This store keeps rules in memory only.
 * Rules are not persisted across application reloads and therefore they have to be loaded early in the application start (initialization) phase.
 *
 * This is the default store for authority and it doesn’t have to be explicitly configured unless it is used in conjunction with other stores.
 *
 * @example
 *  var authority = require("authority");
 *
 *  authority.setRules([{
 *          name: "allow_managers_only",
            description: "Only managers can pass.",
            condition: { title: "Manager" }
 *      }, {
 *          name: "allow_teenagers_only",
            description: "Only users between 13 and 19 years old can pass.",
            condition: { age: { $gte: 13, $lte: 19 } }
 *      }
 *  ]);
 *
 * @class Represents a Memory rule store.
 */
function MemoryStore() {
    /**
     * The name of this store. The default value is "memory". NOTE: every store is required to have a unique name within a manager.
     */
    this.name = "memory";

    /**
     * The object that holds the references to all stored rules. NOTE: this member is not part of the Authority API and it is specific to this store only.
     */
    this.rules = {};
}

/**
 * Adds one or more rules to the store.
 *
 * @param {(object|object[])} rules - The rule or an array of rules to be added to the store.
 *
 * @param {boolean=} override - Specifies whether existing rules should be replaced by the ones provided to this method. Rules are matched by their name.
 * If this parameter is not specified or is false and there is a name conflict an error will be returned or thrown depending on the usage of the method.
 *
 * @param {function=} done - Optional callback function that will be called after the rule(s) have been added.
 * If the method is unsuccessful an error object will be passed as a single parameter to the callback.
 * If the callback is omitted and the method is unsuccessful an error will be thrown.
 *
 * @return {null}
 */
MemoryStore.prototype.setRules = function (rules, override, done) {
    var that = this;

    if (typeof override === "function") {
        done = override;
        override = null;
    }

    if (!done) {
        done = function (err) {
            if (err) {
                throw err;
            }
        };
    }

    function setRule(rule, cb) {
        if (!override && that.rules[rule.name]) {
            return cb(new Error(Strings.ERR_RULE_EXISTS));
        }

        that.rules[rule.name] = rule;
        cb();
    }

    if (Array.isArray(rules)) {
        async.each(rules, function (item, callback) {
            setRule(item, callback);
        }, done);
    } else {
        setRule(rules, done);
    }
};

/**
 * Retrieves the specified rule from the store.
 *
 * @param {string} name - The name of the rule.
 * @param {function} done - The callback that handles the result.
 * The first parameter will always be null for this store while the second parameter will contain the requested rule or null if not found.
 * @return {null}
 */
MemoryStore.prototype.getRule = function (name, done) {
    done(null, this.rules[name]);
};

/**
 * Removes the specified rules from the store.
 *
 * @param {(string|string[])} names - The name or an array of names to remove.
 * @param {function=} done - Optional callback function that will be called after the rule(s) have been deleted.
 * If the method is unsuccessful an error object will be passed as a single parameter to the callback.
 * If the callback is omitted and the method is unsuccessful an error will be thrown.
 * @return {null}
 */
MemoryStore.prototype.deleteRules = function (names, done) {
    var that = this;

    if (!done) {
        done = function (err) {
            if (err) {
                throw err;
            }
        };
    }

    function remRule(name, cb) {
        delete that.rules[name];
        cb();
    }

    if (Array.isArray(names)) {
        async.each(names, function (item, callback) {
            remRule(item, callback);
        }, done);
    } else {
        remRule(names, done);
    }
};

/**
 * Retrieves the names and descriptions of the rules present in the store and matching the specified criteria.
 *
 * All parameters are required.
 *
 * @param {number} start - The index at wich to begin retrieving names. The index of the first element is 0.
 * @param {number} count - The number of names to retrieve. `0` denotes all remaining.
 * @param {string} match - Wildcard expression to match names. `null` denotes any name. Example: `allow_*`
 * @param {function} done - The callback that handles the result.
 * The first parameter will always be null for this store while the second parameter will contain an array of matched objects `{ name: "string", description: "string" }`.
 */
MemoryStore.prototype.getRuleNames = function (start, count, match, done) {
    var keys    = Object.keys(this.rules),
        res     = [],
        that    = this,
        regex;

    if (match) {
        regex = util.regExpFromWildExp(match);
        keys = keys.filter(function (el) {
            return regex.test(el);
        });
    }

    if (start || count) {
        if (count) {
            count = start + count;
        } else {
            count = undefined;
        }
        keys = keys.splice(start, count);
    }

    keys.forEach(function (key) {
        var rule = that.rules[key];
        res.push({ name: rule.name, description: rule.description });
    });

    done(null, res);
};

/**
 * Gets the total count of rules present in the store.
 *
 * @param {function} done - The callback that handles the result.
 * The first parameter will always be null for this store while the second parameter will contain a number representing the total count of rules.
 */
MemoryStore.prototype.getRuleCount = function (done) {
    done(null, Object.keys(this.rules).length);
};

module.exports = MemoryStore;
Authority Copyright © 2013-2014 The contributors to the Authority projects.
Documentation generated by JSDoc 3.2.2 on Sat Jan 18 2014 02:44:25 GMT+0200 (EET) using the DocStrap template.