Source: core/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/>.
 */

'use strict';

const UserRole = require('./user_role');
const GitUserCredential = require('./git_user_credential');

/** A user
 */
class User
{
	/** constructor
	 * 
	 * @param {string} name - user's name
	 * @param {string} password - user's password
	 * @param {string} first_name - user's first name
	 * @param {string} last_name - user's last name
	 * @param {string} email - user's email
	 * @param {string} phone - user's phone number
	 * @param {Array.<UserRole>} [roles] - user's roles
	 * @param {Array.<GitUserCredential>} [git_user_credentials] - Git user's credentials
	 */
	constructor(name, password, first_name, last_name, email, phone, roles, git_user_credentials)
	{
		this.name = name;
		this.password = password;
		this.first_name = first_name;
		this.last_name = last_name;
		this.email = email;
		this.phone = phone;
		if(Array.isArray(roles))
		{
			this.roles = [];
			roles.forEach((role) =>
			{
				this.grant(role.db, role.role);
			});
		}
		if(Array.isArray(git_user_credentials))
		{
			this.git_user_credentials = [];
			git_user_credentials.forEach((git_user_credential) =>
			{
				this.git_user_credentials.push(GitUserCredential.from(git_user_credential));
			});
		}
	}
	
	/** Build a User instance from an object, convenient for transportation with a transport protocol, that looks like a user
	 * 
	 * @param {Object} obj - an object
	 * @return {User} an instance of User
	 */
	static from(obj)
	{
		return new User(
			obj.name,
			obj.password,
			obj.first_name,
			obj.last_name,
			obj.email,
			obj.phone,
			obj.roles,
			obj.git_user_credentials
		);
	}
	
	/** Grant a role in a database
	 * 
	 * @param {string} db - database name
	 * @param {string} role - role name
	 */
	grant(db, role)
	{
		if(this.roles === undefined)
		{
			this.roles = [];
		}
		if(!this.has_role(db, role))
		{
			this.roles.push(new UserRole(db, role));
		}
	}
	
	/** Grant admin role */
	grant_admin_role()
	{
		this.grant('admin', 'root');
	}
	
	/** Test for admin role */
	is_admin()
	{
		return this.has_role('admin', 'root');
	}
	
	/** Grant user role
	 * 
	 * @param {string} db - database name
	 */
	grant_user_role(db)
	{
		this.grant(db, 'User'); 
	}
	
	/** Revoke a role in a database
	 * 
	 * @param {string} [db] - database name
	 * @param {string} [role] - role name
	 */
	revoke(db, role)
	{
		if(this.roles !== undefined)
		{
			if((db !== undefined) && (role !== undefined))
			{
				this.roles = this.roles.filter((user_role) => (user_role.db != db) || (user_role.role != role));
			}
			else if(db !== undefined)
			{
				this.roles = this.roles.filter((user_role) => (user_role.db != db));
			}
			else if(role !== undefined)
			{
				this.roles = this.roles.filter((user_role) => (user_role.role != role));
			}
			else
			{
				this.roles = undefined;
			}
		}
	}
	
	/** Revoke admin role */
	revoke_admin_role()
	{
		this.revoke('admin', 'root');
	}
	
	/** Grant user role
	 * 
	 * @param {string} db - database name
	 */
	revoke_user_role(db)
	{
		this.revoke(db, 'User'); 
	}

	/** Check if user has a particular role in a database
	 * 
	 * @param {string} db - database name
	 * @param {string} [role] - role name
	 * @return {boolean} whether user has a role in database
	 */
	has_role(db, role)
	{
		return (this.roles !== undefined) && (this.roles.find((user_role) => (user_role.db == db) && ((role === undefined) || (user_role.role == role))) !== undefined);
	}
	
	/** Get databases names where user has a role
	 * 
	 * @return {Array.<string>} an array of database names
	 */
	get_db_names()
	{
		var db_names = this.roles.map(user_role => user_role.db)
		let lookup = {};
		return db_names.filter(db => !lookup[db] && (lookup[db] = true));
	}
	
	/** Find Git user's credential bu Git remote URL
	 * 
	 * @param {string} git_remote_url - Git remote URL
	 * @return {GitUserCredential} a GitUserCredential instance
	 */
	find_git_user_credential(git_remote_url)
	{
		return this.git_user_credentials && this.git_user_credentials.find((git_user_credential) => git_user_credential.git_remote_url == git_remote_url);
	}
}

module.exports = User;