Source: core/create_update_user.js

/*
 * This file is part of PKM (Persistent Knowledge Monitor).
 * Copyright (c) 2020 Capgemini Group, Commissariat à l'énergie atomique et aux énergies alternatives,
 *                    OW2, Sysgo AG, Technikon, Tree Technology, Universitat Politècnica de València.
 * 
 * PKM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation.
 * 
 * PKM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with PKM.  If not, see <https://www.gnu.org/licenses/>.
 */

/**
 * Create/Update user
 * 
 * @memberof PKM
 * @instance
 * @param {User} user - user
 * @param {boolean} update - flag to enable/disable updating user's info
 * 
 * @return {Promise} a promise
 */

function create_update_user(user, update)
{
	return new Promise(function(resolve, reject)
	{
		const debug = this.debug;
		const db = this.client.db(this.config.pkm_db);

		if(update)
		{
			this.get_user(user.name).then((known_user) =>
			{
				known_user = this.grant_pkm_management_roles(known_user);
				
				// check that current user can update user:
				//   - it is not another user or,
				//   - it is an administrator
				((this.user_name == user.name) ? Promise.resolve(true) : new Promise((resolve, reject) =>
				{
					// current user is not the user being updated
					// determine whether current user is an administrator, which thus can update another user
					this.get_user(this.user_name).then((current_user) =>
					{
						resolve(current_user.is_admin());
					}).catch((err) =>
					{
						reject(this.Error(err));
					});
				})).then((can_update_user) => new Promise((resolve, reject) =>
				{
					if(can_update_user)
					{
						let cmd =
						{
							updateUser : user.name,
						};
						
						if((user.first_name !== undefined) ||
						   (user.last_name !== undefined) ||
						   (user.email !== undefined) ||
						   (user.phone !== undefined) ||
						   (user.git_user_credentials !== undefined))
						{
							const GitUserCredential = require('./git_user_credential');
							
							cmd.customData =
							{
								first_name : (user.first_name !== undefined) ? user.first_name : known_user.first_name,
								last_name : (user.last_name !== undefined) ? user.last_name : known_user.last_name,
								email : (user.email !== undefined) ? user.email : known_user.email,
								phone : (user.phone !== undefined) ? user.phone : known_user.phone
							};
							
							if((user.name == this.user_name) && (user.git_user_credentials !== undefined))
							{
								cmd.customData.git_user_credentials = user.git_user_credentials.map((git_user_credential) => git_user_credential.encrypt(this.crypt));
							}
							else if(known_user.git_user_credentials !== undefined)
							{
								cmd.customData.git_user_credentials = known_user.git_user_credentials;
							}
						}
						
						if(!(user.password === undefined))
						{
							cmd.pwd = user.password;
						}
						if((cmd.customData !== undefined) || (cmd.pwd !== undefined) || (cmd.roles !== undefined))
						{
							if(debug)
							{
								console.log('Running command ', cmd);
							}
							db.command(cmd).then(() =>
							{
								resolve();
							}).catch((err) =>
							{
								reject(this.Error(err));
							});
						}
						else
						{
							if(debug)
							{
								console.log('no custom data or password update');
							}
							resolve();
						}
					}
					else
					{
						if(debug)
						{
							console.log('current user can\'t update other user custom data or password');
						}
						resolve();
					}
				})).then(() =>
				{
					if(!(user.roles === undefined))
					{
						user = this.grant_pkm_management_roles(user);
						
						var grant_user_role_promises = [];
						user.roles.forEach((user_role) =>
						{
							if(!known_user.has_role(user_role.db, user_role.role))
							{
								if(debug)
								{
									console.log('known user (\'' + known_user.name + '\') has no role \'' + user_role.role + '\' in \'' + user_role.db + '\': requesting grant');
								}
								grant_user_role_promises.push(this.update_user_role(user_role.db, user_role.role, 'grant', user.name));
							}
						});
						
						Promise.all(grant_user_role_promises).then(() =>
						{
							let revoke_user_role_promises = [];
							known_user.roles.forEach((known_user_role) =>
							{
								if(!user.has_role(known_user_role.db, known_user_role.role))
								{
									if(debug)
									{
										console.log('user (\'' + known_user.name + '\') has no longer role \'' + known_user_role.role+ '\' in \'' + known_user_role.db + '\': requesting revocation');
									}
									revoke_user_role_promises.push(this.update_user_role(known_user_role.db, known_user_role.role, 'revoke', user.name));
								}
							});
							
							Promise.all(revoke_user_role_promises).then(() =>
							{
								resolve();
							}).catch((err) =>
							{
								reject(this.Error(err));
							});
						}).catch((err) =>
						{
							reject(this.Error(err));
						});
					}
					else
					{
						resolve();
					}
				}).catch((err) =>
				{
					reject(this.Error(err));
				});
			}).catch((err) =>
			{
				reject(this.Error(err));
			});
		}
		else
		{
			user = this.grant_pkm_management_roles(user);
			var options =
			{
				roles : user.roles,
				customData :
				{
					first_name : user.first_name,
					last_name : user.last_name,
					email : user.email,
					phone : user.phone
				}
			};
			if(user.git_user_credentials !== undefined) options.customData.git_user_credentials = user.git_user_credentials.map((git_user_credential) => git_user_credential.encrypt(this.crypt));
			if(debug)
			{
				console.log('Adding ' + user.name + '@' + this.config.pkm_db + ' with password \'' + user.password + '\', roles ', options.roles, ', custom data ', options.customData);
			}
			db.addUser(user.name, user.password, options).then(() =>
			{
				resolve();
			}).catch((err) =>
			{
				reject(this.Error(err));
			});
		}
	}.bind(this));
}

exports.create_update_user = create_update_user;