class ZMSImpl implements Authorizer, KeyStore, ZMSHandler {

    @Override
    public void putRole(ResourceContext ctx, String domainName, String roleName, String auditRef, Role role) {

        final String caller = ctx.getApiName();
        logPrincipal(ctx);

        if (readOnlyMode) {
            throw ZMSUtils.requestError(SERVER_READ_ONLY_MESSAGE, caller);
        }

        validateRequest(ctx.request(), caller);

        validate(domainName, TYPE_DOMAIN_NAME, caller);
        validate(roleName, TYPE_ENTITY_NAME, caller);
        validate(role, TYPE_ROLE, caller);
        validateRoleValues(role);

        // for consistent handling of all requests, we're going to convert
        // all incoming object values into lower case (e.g. domain, role,
        // policy, service, etc name)

        domainName = domainName.toLowerCase();
        setRequestDomain(ctx, domainName);
        roleName = roleName.toLowerCase();
        AthenzObject.ROLE.convertToLowerCase(role);

        // verify the role name in the URI and request are consistent

        if (!isConsistentRoleName(domainName, roleName, role)) {
            throw ZMSUtils.requestError("putRole: Inconsistent role names - expected: "
                    + ZMSUtils.roleResourceName(domainName, roleName) + ", actual: "
                    + role.getName(), caller);
        }

        // validate the user authority settings if they're provided

        validateUserAuthorityAttributes(role.getUserAuthorityFilter(), role.getUserAuthorityExpiration(), caller);

        // verify that request is properly authenticated for this request

        verifyAuthorizedServiceOperation(((RsrcCtxWrapper) ctx).principal().getAuthorizedService(), caller);

        Domain domain = dbService.getDomain(domainName, false);
        if (domain == null) {
            throw ZMSUtils.notFoundError("No such domain: " + domainName, caller);
        }

        // validate role and trust settings are as expected

        validateRoleStructure(role, domainName, caller);

        // normalize and remove duplicate members

        normalizeRoleMembers(role);

        // check to see if we need to validate user and service members
        // and possibly user authority filter restrictions. For the
        // admin role we're not going to allow any group members to
        // enforce least privilege access where specific users must
        // be specified as members.

        boolean disallowGroups = ADMIN_ROLE_NAME.equals(roleName);
        validateRoleMemberPrincipals(role, domain.getUserAuthorityFilter(), disallowGroups, caller);

        // if the role is review enabled then it cannot contain
        // role members as we want review and audit enabled roles
        // to be enabled as such and then add individual members

        if (role.getReviewEnabled() == Boolean.TRUE && !role.getRoleMembers().isEmpty()) {
            throw ZMSUtils.requestError("Set review enabled flag using role meta api", caller);
        }

        // update role expiry based on our configurations

        updateRoleMemberExpiration(
                domain.getMemberExpiryDays(),
                role.getMemberExpiryDays(),
                domain.getServiceExpiryDays(),
                role.getServiceExpiryDays(),
                domain.getGroupExpiryDays(),
                role.getGroupExpiryDays(),
                role.getRoleMembers());

        // update role expiry based on user authority expiry
        // if configured

        updateRoleMemberUserAuthorityExpiry(role, caller);

        // update role review based on our configurations

        updateRoleMemberReviewReminder(role.getMemberReviewDays(), role.getServiceReviewDays(), role.getRoleMembers());

        // process our request

        dbService.executePutRole(ctx, domainName, roleName, role, auditRef, caller);
    }

    public  ZMSImpl();

}