-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--         http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.


local log = require 'mc.logging'

local ACCOUNT_PATH = '/bmc/kepler/AccountService/Accounts/'
local ACCOUNT_INTF = 'bmc.kepler.AccountService.ManagerAccount'

local M = {}

local ROLE_ID_TO_NAME = {
    ['0'] = 'NoAccess',
    ['2'] = 'CommonUser',
    ['3'] = 'Operator',
    ['4'] = 'Administrator',
    ['5'] = 'CustomRole1',
    ['6'] = 'CustomRole2',
    ['7'] = 'CustomRole3',
    ['8'] = 'CustomRole4'
}

local ROLE_NAME_TO_ID = {
    ['noaccess'] = '0',
    ['commonuser'] = '2',
    ['operator'] = '3',
    ['administrator'] = '4',
    ['customrole1'] = '5',
    ['customrole2'] = '6',
    ['customrole3'] = '7',
    ['customrole4'] = '8'
}

local PRIV_NAME_TO_ID = {
    ['UserMgmt'] = 0,
    ['BasicSetting'] = 1,
    ['KVMMgmt'] = 2,
    ['VMMMgmt'] = 3,
    ['SecurityMgmt'] = 4,
    ['PowerMgmt'] = 5,
    ['DiagnoseMgmt'] = 6,
    ['ReadOnly'] = 7,
    ['ConfigureSelf'] = 8
}

local REDFISH_ROLE_MAP = {
    ['ReadOnly'] = 'Login',
    ['UserMgmt'] = 'ConfigureUsers',
    ['BasicSetting'] = 'ConfigureComponents',
    ['ConfigureSelf'] = 'ConfigureSelf'
}

local OEM_ROLE_MAP = {
    ['KVMMgmt'] = 'OemKvm',
    ['VMMMgmt'] = 'OemVmm',
    ['SecurityMgmt'] = 'OemSecurityMgmt',
    ['PowerMgmt'] = 'OemPowerControl',
    ['DiagnoseMgmt'] = 'OemDiagnosis'
}

local function has_usermgmt_priv(privs)
    for _, v in ipairs(privs) do
        if v == 'UserMgmt' then
            return true
        end
    end

    return false
end

function M.get_role_members(Context)
    local privs = Context.Privilege
    local account_obj = mdb.get_object(bus, ACCOUNT_PATH .. Context.AccountId, ACCOUNT_INTF)
    local login_user_role = { ROLE_ID_TO_NAME[tostring(account_obj.RoleId)] }

    local roles = {}
    local path = '/bmc/kepler/AccountService/Roles'
    local interface = 'bmc.kepler.AccountService.Role'
    local ok, objs = pcall(function ()
        return mdb.get_sub_objects(bus, path, interface)
    end)
    if not ok then
        log:error('get role objects failed')
        return roles
    end

    local is_get_all = has_usermgmt_priv(privs)
    for _, v in pairs(objs) do
        local role_path = v['path']
        local _, i = role_path:find(path .. '/')
        local role = ROLE_ID_TO_NAME[role_path:sub(i + 1)]
        if is_get_all then
            roles[#roles + 1] = '/redfish/v1/AccountService/Roles/' .. role
        else
            for _, user_role in ipairs(login_user_role) do
                if user_role == role then
                    roles[#roles + 1] = '/redfish/v1/AccountService/Roles/' .. role
                end
            end
        end
    end

    return roles
end

function M.get_role_member_id(member_id)
    local role_id = ROLE_NAME_TO_ID[string.lower(member_id)]
    if not role_id then
        return
    end
    return ROLE_ID_TO_NAME[role_id]
end

function M.get_role_id(role_name)
    return ROLE_NAME_TO_ID[string.lower(role_name)]
end

function M.is_predefined_role(member_id)
    local role_id = tonumber(ROLE_NAME_TO_ID[string.lower(member_id)])
    return (role_id <= 4) -- 小于等于4的为预制角色
end

local function get_privilege_info(member_id, role_map)
    local role_id = ROLE_NAME_TO_ID[string.lower(member_id)]
    local obj = mdb.get_object(bus, '/bmc/kepler/AccountService/Roles/' .. role_id, 'bmc.kepler.AccountService.Role')
    if not obj then
        return
    end

    local ret = {}
    for _, v in ipairs(obj['RolePrivilege']) do
        if role_map[v] then
            ret[#ret + 1] = role_map[v]
        end
    end
    return ret
end

function M.get_assigned_privileges(member_id)
    return get_privilege_info(member_id, REDFISH_ROLE_MAP)
end

function M.get_oem_privileges(member_id)
    return get_privilege_info(member_id, OEM_ROLE_MAP)
end

-- redfish定义权限
function M.enable_assigned_privileges(privs_tab, priv)
    local assigned_setting = {PRIV_NAME_TO_ID[priv], false}
    for _, v in ipairs(privs_tab) do
        if v == REDFISH_ROLE_MAP[priv] then
            assigned_setting[2] = true
            return assigned_setting
        end
    end
    return assigned_setting
end

-- 华为服务器定义权限
function M.enable_oem_privileges(privs_tab, priv)
    local oem_setting = {PRIV_NAME_TO_ID[priv], false}
    for _, v in ipairs(privs_tab) do
        if v == OEM_ROLE_MAP[priv] then
            oem_setting[2] = true
            return oem_setting
        end
    end
    return oem_setting
end

return M

