//访问控制规则：
//针对如果是DOIP请求的调用
//仅包括Repo.doipRetrive
//Registry的publish/subscribe不做访问控制
//如果是HTTP请求的调用
//管理员具有所有权限
//一些”写入接口“添加权限检查
module DOAuth {
    function initDOAuth(req, createParam, doipFunctions) {
        Global.owner = req;
        Global.doipFunctions = doipFunctions;
        Global.accessInfo = RocksDBUtil.loadDB("accessControl", "false");
        Global.userInfo = RocksDBUtil.loadDB("authedUserInfo", "false");
        Global.nodeInfo = RocksDBUtil.loadDB("authedNodeInfo", "false");
    }
    function isOwner(req) {
        return req == Global.owner;
    }
    function doipAccessCheck(argPack) {
        print("in doipAcceccCheck, requester:" + argPack.requester);
        return hasDBSetItem(Global.accessInfo, argPack.arg.header.identifier, argPack.requester);
    }
    function checkByManager(action) {
        return Global.doipFunctions.indexOf(action) == - 1;
    }

    @Description("针对某一DO，添加用户的访问权限")
    @ArgSchema({
        "doId" : "string", "publicKey" : "string", "info": "string"
    })
    @Access({
        "ACFunction":"acceptOwner"
    })
    export function addAuthedUser(arg) {
    //把requester和 arg.doId放到accessInfo里即可。
        addDBSetItem(Global.accessInfo, arg.doId, arg.publicKey);
        if(arg.info != null) {
            Global.userInfo.put(arg.publicKey, arg.info);
        }
        return {
            "code" : 0
        };
    }

    function acceptJudgementInternal(argPack) {
        if (checkByManager(argPack.action)){
            return isOwner(argPack.requester);
        } else {
            return doipAccessCheck(argPack);
        }
    }
    function acceptJudgement(argPack) {
        if (! acceptJudgementInternal(argPack)){
            print("acceptJudgement, requester:" + argPack.requester + "false!!");
            YancloudUtil.exceptionReturn({
                "code" : 401, "msg" : "no permission: " + argPack.action
            });
        } else print("acceptJudgement, requester:" + argPack.requester + "true!!");
    }

    function acceptOwner(argPack) {
        if (argPack.requester !== Global.owner) {
            YancloudUtil.exceptionReturn({
                "code" : 401, "msg" : "no permission: " + argPack.action
            });
        }
    }

    @Description("针对某一DO，删除用户的访问权限")
    @ArgSchema({
        "doId" : "string", "publicKey" : "string"
    })
    @Access({
        "ACFunction":"acceptOwner"
    })
    export function deleteAuthedUser(arg) {
        deleteDBSetItem(Global.accessInfo, arg.doId, arg.publicKey);
        return {
            "code" : 0
        };
    }

    @Description("针对某一DO，添加节点的访问权限，所有调用进带该节点授权的用户均可访问")
    @ArgSchema({
        "doId" : "string", "publicKey" : "string", "info" : "string"
    })
    @Access({
        "ACFunction":"acceptOwner"
    })
    export function addAuthedNode(arg) {
        addDBSetItem(Global.accessInfo, arg.doId, arg.publicKey);
        if(arg.info != null) {
            Global.nodeInfo.put(arg.publicKey, arg.info);
        }
        return {
            "code" : 0
        };
    }


    @Description("针对某一DO，删除节点的访问权限")
    @ArgSchema({
        "doId" : "string", "publicKey" : "string"
    })
    @Access({
        "ACFunction":"acceptOwner"
    })
    export function deleteAuthedNode(arg) {
        deleteDBSetItem(Global.accessInfo, arg.doId, arg.publicKey);
        return {
            "code" : 0
        };
    }

    function getDBSet(db, key) {
        var saved = db.get(key);
        if (saved == null) {
            saved = "[]";
        }
        return JSON.parse(saved);
    }

    function addDBSetItem(db, key, value) {
        var savedSet = getDBSet(db, key);
        if (savedSet.indexOf(value) === -1) {
            savedSet.push(value);
            var saved = JSON.stringify(savedSet);
            db.put(key, saved);
        }
    }

    function deleteDBSetItem(db, key, value) {
        var savedSet = getDBSet(db, key);
        var index = savedSet.indexOf(value);
        if (index !== -1) {
            savedSet.splice(index, 1);
            var saved = JSON.stringify(savedSet);
            db.put(key, saved);
        }
    }

    function hasDBSetItem(db, key, value) {
        var savedSet = getDBSet(db, key);
        return savedSet.indexOf(value) !== -1;
    }
}