class ZMSImpl implements Authorizer, KeyStore, ZMSHandler {

    public Domain postUserDomain(ResourceContext ctx, String name, String auditRef, UserDomain detail) {

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

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

        validateRequest(ctx.request(), caller);
        validate(detail, TYPE_USER_DOMAIN, caller);
        validate(name, TYPE_SIMPLE_NAME, caller);

        // 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)

        name = name.toLowerCase();
        setRequestDomain(ctx, name);
        AthenzObject.USER_DOMAIN.convertToLowerCase(detail);

        if (detail.getName().indexOf('_') != -1 && !isSysAdminUser(((RsrcCtxWrapper) ctx).principal())) {
            throw ZMSUtils.requestError("Domain name cannot contain underscores", caller);
        }

        // verify that request is properly authenticated for this request

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

        if (!name.equals(detail.getName())) {
            throw ZMSUtils.forbiddenError("postUserDomain: Request and detail domain names do not match", caller);
        }

        // we're dealing with user's top level domain so the parent is going
        // to be the home domain and the admin of the domain is the user

        final String userDomainAdmin = userDomainPrefix + principal.getName();
        validateRoleMemberPrincipal(userDomainAdmin, Principal.Type.USER.getValue(), null, null, null, true, caller);

        List<String> adminUsers = new ArrayList<>();
        adminUsers.add(userDomainAdmin);

        List<String> solutionTemplates = null;
        DomainTemplateList templates = detail.getTemplates();
        if (templates != null) {
            solutionTemplates = templates.getTemplateNames();
            validateSolutionTemplates(solutionTemplates, caller);
        }

        Domain subDomain = new Domain()
                .setName(homeDomain + "." + getUserDomainName(detail.getName()))
                .setAuditEnabled(detail.getAuditEnabled())
                .setDescription(detail.getDescription())
                .setOrg(detail.getOrg())
                .setId(UUID.fromCurrentTime())
                .setAccount(detail.getAccount())
                .setModified(Timestamp.fromCurrentTime())
                .setApplicationId(detail.getApplicationId())
                .setMemberExpiryDays(detail.getMemberExpiryDays())
                .setServiceExpiryDays(detail.getServiceExpiryDays())
                .setGroupExpiryDays(detail.getGroupExpiryDays())
                .setTokenExpiryMins(detail.getTokenExpiryMins())
                .setServiceCertExpiryMins(detail.getServiceCertExpiryMins())
                .setRoleCertExpiryMins(detail.getRoleCertExpiryMins())
                .setSignAlgorithm(detail.getSignAlgorithm());

        // before processing validate the fields

        validateDomainValues(subDomain);

        return createSubDomain(ctx, subDomain, adminUsers, solutionTemplates, auditRef, caller);
    }

    public  ZMSImpl();

}