UNPKG

4.67 kBJavaScriptView Raw
1'use strict';
2
3var normalize = require('../normalize');
4
5/**
6 * Access users based request information.
7 *
8 * @constructor
9 * @param {Registry} api Reference to the wrapping registry.
10 * @api private
11 */
12function Users(api) {
13 this.api = api;
14 this.send = api.send.bind(api);
15 this.view = api.view.bind(api);
16}
17
18/**
19 * Add a user as maintainer of a package.
20 *
21 * @param {String} name The user's name who needs to own the package.
22 * @param {String} pkg The module it should become an owner off.
23 * @param {Function} fn The callback.
24 * @returns {Assign}
25 * @api public
26 */
27Users.prototype.add = function add(name, pkg, fn) {
28 return this.send(name, {
29 method: 'PUT',
30 json: {}
31 }, fn);
32};
33
34/**
35 * Create a new npm account.
36 *
37 * @param {String} username The desired user name.
38 * @param {String} email Accounts email.
39 * @param {String} password Account password.
40 * @param {Function} fn Callback.
41 * @api public
42 */
43Users.prototype.create = function create(username, email, password, fn) {
44 password = (password || '').toString().trim();
45 username = (username || '').toString().trim();
46 email = (email || '').toString().trim();
47
48 //
49 // @TODO this will break our Assign return flow, making chaining impossible.
50 //
51 if (!password) return fn(new Error('Missing password'));
52 if (!~password.indexOf(':')) return fn(new Error('Password cannot contain a `:`'));
53 if (!email) return fn(new Error('Missing email'));
54 if (!~email.indexOf('@')) return fn(new Error('Invalid email address'));
55 if (!username) return fn(new Error('Missing username'));
56
57 return this.send('/-/user/org.couchdb.user:'+ encodeURIComponent(username), {
58 method: 'PUT',
59 json: {
60 _id: 'org.couchdb.user:'+ username
61 , date: (new Date()).toISOString()
62 , email: email
63 , name: username
64 , password: password
65 , roles: []
66 , type: 'user'
67 }
68 }, fn);
69};
70
71/**
72 * Update the user.
73 *
74 * @param {String} username The user's name.
75 * @param {Object} fields The fields we want to add.
76 * @param {Function} fn
77 */
78Users.prototype.update = function update(username, fields, fn) {
79 username = '/-/user/org.couchdb.user:'+ encodeURIComponent(username);
80
81 var users = this;
82
83 /**
84 * Small helper function to handle revisions in CouchDB.
85 *
86 * @param {Error} err An optional error object.
87 * @param {String} _rev The current rev in the CouchDB.
88 * @param {Object} data Optional data.
89 * @api private
90 */
91 function rev(err, _rev, data) {
92 if (err) return fn(err);
93
94 return users.send(username +'/-rev/'+ _rev, {
95 method: 'PUT',
96 json: users.api.merge(data || {}, fields)
97 }, fn);
98 }
99
100 if ('_rev' in fields) return rev(undefined, fields._rev);
101 return this.send(username, rev);
102};
103
104/**
105 * List all packages for the given name.
106 *
107 * @param {String} name The user's name who's packages we want to list.
108 * @param {Function} fn The callback.
109 * @returns {Assign}
110 * @api public
111 */
112Users.prototype.list = function list(name, fn) {
113 return this.view('browseAuthors', {
114 key: name
115 }, fn).map(this.api.map.simple);
116};
117
118/**
119 * List all packages that the user has starred.
120 *
121 * @param {String} name The user's name
122 * @param {Function} fn The callback.
123 * @returns {Assign}
124 * @api public
125 */
126Users.prototype.starred = function starred(name, fn) {
127 return this.view('browseStarUser', {
128 key: name
129 }, fn).map(this.api.map.simple);
130};
131
132/**
133 * Get profile information.
134 *
135 * @param {String} username The user's name.
136 * @param {Function} fn The callback.
137 * @returns {Assign}
138 * @api public
139 */
140Users.prototype.get = function get(username, fn) {
141 username = '/-/user/org.couchdb.user:'+ encodeURIComponent(username);
142
143 return this.send(name, fn).map(normalize.users);
144};
145
146/**
147 * Sync ownership of npm modules with another account. This is useful if you
148 * have one base owner of modules like a corporate account and you want to
149 * on-board a new user.
150 *
151 * @param {String} source The user's packages that needs to be synced.
152 * @param {String} target The user who needs to have ownership.
153 * @param {Object} options Configuration of the sync process.
154 * @api public
155 */
156Users.prototype.sync = function sync(source, target, options, fn) {
157 if ('function' === typeof options) {
158 fn = options;
159 options = null;
160 }
161
162 options = options || {};
163 options.add = 'add' in options ? options.add : true;
164 options.packages = 'packages' in options ? options.packages : false;
165
166 var user = this;
167
168 this.list(source, function (err, packages) {
169 user.api.async.each(packages, function (name, next) {
170 user.add(target, name, next);
171 }, fn);
172 });
173};
174
175//
176// Expose module.
177//
178module.exports = Users;