org.tightblog.ui.restapi.UserController.java Source code

Java tutorial

Introduction

Here is the source code for org.tightblog.ui.restapi.UserController.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  The ASF licenses this file to You
 * under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 *
 * Source file modified from the original ASF source; all changes made
 * are also under Apache License.
 */
package org.tightblog.ui.restapi;

import com.fasterxml.jackson.annotation.JsonInclude;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.MessageSource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.tightblog.repository.WeblogEntryCommentRepository;
import org.tightblog.service.EmailService;
import org.tightblog.service.URLService;
import org.tightblog.service.UserManager;
import org.tightblog.domain.GlobalRole;
import org.tightblog.domain.User;
import org.tightblog.domain.UserCredentials;
import org.tightblog.domain.UserStatus;
import org.tightblog.domain.UserWeblogRole;
import org.tightblog.domain.Weblog;
import org.tightblog.domain.WeblogRole;
import org.tightblog.repository.UserCredentialsRepository;
import org.tightblog.repository.UserRepository;
import org.tightblog.repository.UserWeblogRoleRepository;
import org.tightblog.repository.WeblogRepository;
import org.tightblog.repository.WebloggerPropertiesRepository;
import org.tightblog.util.Utilities;
import org.tightblog.util.ValidationError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.tightblog.domain.WebloggerProperties;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.RollbackException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.security.Principal;
import java.time.Instant;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@RestController
public class UserController {

    private static Logger log = LoggerFactory.getLogger(UserController.class);

    private static final Pattern PWD_PATTERN = Pattern
            .compile("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,20}$");

    private WeblogRepository weblogRepository;
    private UserManager userManager;
    private UserWeblogRoleRepository userWeblogRoleRepository;
    private UserRepository userRepository;
    private UserCredentialsRepository userCredentialsRepository;
    private EmailService emailService;
    private MessageSource messages;
    private WebloggerPropertiesRepository webloggerPropertiesRepository;
    private WeblogEntryCommentRepository weblogEntryCommentRepository;
    private URLService urlService;

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    public UserController(WeblogRepository weblogRepository, UserManager userManager,
            UserWeblogRoleRepository userWeblogRoleRepository, MessageSource messageSource,
            EmailService emailService, UserRepository userRepository,
            UserCredentialsRepository userCredentialsRepository, URLService urlService,
            WeblogEntryCommentRepository weblogEntryCommentRepository,
            WebloggerPropertiesRepository webloggerPropertiesRepository) {
        this.weblogRepository = weblogRepository;
        this.webloggerPropertiesRepository = webloggerPropertiesRepository;
        this.userManager = userManager;
        this.userWeblogRoleRepository = userWeblogRoleRepository;
        this.userRepository = userRepository;
        this.userCredentialsRepository = userCredentialsRepository;
        this.weblogEntryCommentRepository = weblogEntryCommentRepository;
        this.urlService = urlService;
        this.emailService = emailService;
        this.messages = messageSource;
    }

    @GetMapping(value = "/tb-ui/admin/rest/useradmin/userlist")
    public Map<String, String> getUserEditList() throws ServletException {
        return createUserMap(userRepository.findAll());
    }

    @GetMapping(value = "/tb-ui/admin/rest/useradmin/registrationapproval")
    public List<User> getRegistrationsNeedingApproval() throws ServletException {
        return userRepository.findUsersToApprove();
    }

    @PostMapping(value = "/tb-ui/admin/rest/useradmin/registrationapproval/{id}/approve")
    public void approveRegistration(@PathVariable String id, HttpServletResponse response) {
        User acceptedUser = userRepository.findByIdOrNull(id);
        if (acceptedUser != null) {
            if (!UserStatus.ENABLED.equals(acceptedUser.getStatus())) {
                acceptedUser.setStatus(UserStatus.ENABLED);
                userRepository.saveAndFlush(acceptedUser);
                userRepository.evictUser(acceptedUser);
                emailService.sendRegistrationApprovedNotice(acceptedUser);
            }
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        }
    }

    @PostMapping(value = "/tb-ui/admin/rest/useradmin/registrationapproval/{id}/reject")
    public void rejectRegistration(@PathVariable String id, HttpServletResponse response) {
        User rejectedUser = userRepository.findByIdOrNull(id);
        if (rejectedUser != null) {
            emailService.sendRegistrationRejectedNotice(rejectedUser);
            userManager.removeUser(rejectedUser);
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        }
    }

    @GetMapping(value = "/tb-ui/authoring/rest/weblog/{weblogId}/potentialmembers")
    public Map<String, String> getPotentialNewBlogMembers(@PathVariable String weblogId, Principal p,
            HttpServletResponse response) throws ServletException {

        Weblog weblog = weblogRepository.findById(weblogId).orElse(null);
        if (weblog != null && userManager.checkWeblogRole(p.getName(), weblog, WeblogRole.OWNER)) {
            // member list excludes inactive accounts
            List<User> potentialUsers = userRepository.findByStatusEnabled();

            // filter out people already members
            ListIterator<User> potentialIter = potentialUsers.listIterator();
            List<UserWeblogRole> currentUserList = userWeblogRoleRepository.findByWeblog(weblog);
            while (potentialIter.hasNext() && !currentUserList.isEmpty()) {
                User su = potentialIter.next();
                ListIterator<UserWeblogRole> alreadyIter = currentUserList.listIterator();
                while (alreadyIter.hasNext()) {
                    UserWeblogRole au = alreadyIter.next();
                    if (su.getId().equals(au.getUser().getId())) {
                        potentialIter.remove();
                        alreadyIter.remove();
                        break;
                    }
                }
            }
            return createUserMap(potentialUsers);
        } else {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            return null;
        }
    }

    private Map<String, String> createUserMap(List<User> users) {
        Map<String, String> userMap = new TreeMap<>();
        for (User user : users) {
            userMap.put(user.getId(), user.getScreenName() + " (" + user.getEmailAddress() + ")");
        }
        Map<String, String> sortedMap = userMap.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(
                Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new));
        return sortedMap;
    }

    @GetMapping(value = "/tb-ui/admin/rest/useradmin/user/{id}")
    public UserData getUserData(@PathVariable String id, HttpServletResponse response) throws ServletException {
        User user = userRepository.findByIdOrNull(id);

        if (user != null) {
            UserData data = new UserData();
            UserCredentials creds = userCredentialsRepository.findByUserName(user.getUserName());
            data.setUser(user);
            data.setCredentials(creds);
            return data;
        } else {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return null;
        }
    }

    @GetMapping(value = "/tb-ui/authoring/rest/userprofile/{id}")
    public User getProfileData(@PathVariable String id, Principal p, HttpServletResponse response)
            throws ServletException {
        User user = userRepository.findByIdOrNull(id);
        User authenticatedUser = userRepository.findEnabledByUserName(p.getName());

        if (user != null && user.getId().equals(authenticatedUser.getId())) {
            return user;
        } else {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return null;
        }
    }

    @PostMapping(value = "/tb-ui/register/rest/registeruser")
    public ResponseEntity registerUser(@Valid @RequestBody UserData newData, Locale locale,
            HttpServletResponse response) throws ServletException {
        ValidationError maybeError = advancedValidate(null, newData, true, locale);
        if (maybeError != null) {
            return ResponseEntity.badRequest().body(maybeError);
        }

        long userCount = userRepository.count();
        WebloggerProperties.RegistrationPolicy option = webloggerPropertiesRepository.findOrNull()
                .getRegistrationPolicy();
        if (userCount == 0 || !WebloggerProperties.RegistrationPolicy.DISABLED.equals(option)) {
            boolean mustActivate = userCount > 0;
            if (mustActivate) {
                newData.user.setActivationCode(UUID.randomUUID().toString());
                newData.user.setStatus(UserStatus.REGISTERED);
            } else {
                // initial user is the Admin, is automatically enabled.
                newData.user.setStatus(UserStatus.ENABLED);
            }

            User user = new User();
            user.setUserName(newData.user.getUserName());
            user.setDateCreated(Instant.now());

            ResponseEntity re = saveUser(user, newData, null, response, true);

            if (re.getStatusCode() == HttpStatus.OK && mustActivate) {
                UserData data = (UserData) re.getBody();
                if (data != null) {
                    emailService.sendUserActivationEmail(data.getUser());
                }
            }
            return re;
        } else {
            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
        }
    }

    @PostMapping(value = "/tb-ui/authoring/rest/userprofile/{id}")
    public ResponseEntity updateUserProfile(@PathVariable String id, @Valid @RequestBody UserData newData,
            Principal p, Locale locale, HttpServletResponse response) throws ServletException {
        User user = userRepository.findByIdOrNull(id);
        User authenticatedUser = userRepository.findEnabledByUserName(p.getName());

        if (user != null && user.getId().equals(authenticatedUser.getId())) {
            ValidationError maybeError = advancedValidate(null, newData, false, locale);
            if (maybeError != null) {
                return ResponseEntity.badRequest().body(maybeError);
            }
            return saveUser(user, newData, p, response, false);
        } else {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }

    @PutMapping(value = "/tb-ui/admin/rest/useradmin/user/{id}")
    public ResponseEntity updateUser(@PathVariable String id, @Valid @RequestBody UserData newData, Principal p,
            Locale locale, HttpServletResponse response) throws ServletException {
        User user = userRepository.findByIdOrNull(id);
        ValidationError maybeError = advancedValidate(user, newData, false, locale);
        if (maybeError != null) {
            return ResponseEntity.badRequest().body(maybeError);
        }
        return saveUser(user, newData, p, response, false);
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    static class UserData {
        @Valid
        User user;

        UserCredentials credentials;

        UserData() {
        }

        public User getUser() {
            return user;
        }

        public void setUser(User user) {
            this.user = user;
        }

        public UserCredentials getCredentials() {
            return credentials;
        }

        public void setCredentials(UserCredentials credentials) {
            this.credentials = credentials;
        }
    }

    @GetMapping(value = "/tb-ui/authoring/rest/weblog/{weblogId}/members")
    public List<UserWeblogRole> getWeblogMembers(@PathVariable String weblogId, Principal p,
            HttpServletResponse response) throws ServletException {

        Weblog weblog = weblogRepository.findById(weblogId).orElse(null);
        if (weblog != null && userManager.checkWeblogRole(p.getName(), weblog, WeblogRole.OWNER)) {
            List<UserWeblogRole> uwrs = userWeblogRoleRepository.findByWeblog(weblog);
            return uwrs;
        } else {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            return null;
        }
    }

    @PostMapping(value = "/tb-ui/authoring/rest/weblog/{weblogId}/user/{userId}/role/{role}/attach", produces = "text/plain")
    public ResponseEntity addUserToWeblog(@PathVariable String weblogId, @PathVariable String userId,
            @PathVariable WeblogRole role, Principal p, Locale locale) {

        User requestor = userRepository.findEnabledByUserName(p.getName());
        User newMember = userRepository.findByIdOrNull(userId);
        Weblog weblog = weblogRepository.findById(weblogId).orElse(null);

        if (weblog != null && newMember != null && requestor != null
                && requestor.hasEffectiveGlobalRole(GlobalRole.ADMIN)) {

            UserWeblogRole roleChk = userWeblogRoleRepository.findByUserAndWeblog(newMember, weblog);
            if (roleChk != null) {
                return ResponseEntity.badRequest()
                        .body(messages.getMessage("members.userAlreadyMember", null, locale));
            }
            userManager.grantWeblogRole(newMember, weblog, role);
            return ResponseEntity.ok(messages.getMessage("members.userAdded", null, locale));
        } else {
            return ResponseEntity.status(HttpServletResponse.SC_FORBIDDEN).build();
        }
    }

    @PostMapping(value = "/tb-ui/authoring/rest/weblog/{weblogId}/memberupdate", produces = "text/plain")
    public ResponseEntity updateWeblogMembership(@PathVariable String weblogId, Principal p, Locale locale,
            @RequestBody List<UserWeblogRole> uwrs) throws ServletException {

        Weblog weblog = weblogRepository.findById(weblogId).orElse(null);
        User user = userRepository.findEnabledByUserName(p.getName());
        if (user != null && weblog != null && user.hasEffectiveGlobalRole(GlobalRole.ADMIN)) {

            // must remain at least one admin
            List<UserWeblogRole> owners = uwrs.stream().filter(r -> r.getWeblogRole().equals(WeblogRole.OWNER))
                    .collect(Collectors.toList());
            if (owners.size() < 1) {
                return ResponseEntity.badRequest()
                        .body(messages.getMessage("members.oneAdminRequired", null, locale));
            }

            // one iteration for each line (user) in the members table
            for (UserWeblogRole uwr : uwrs) {
                if (WeblogRole.NOBLOGNEEDED.equals(uwr.getWeblogRole())) {
                    userManager.deleteUserWeblogRole(uwr);
                } else {
                    userManager.grantWeblogRole(uwr.getUser(), uwr.getWeblog(), uwr.getWeblogRole());
                }
            }
            String msg = messages.getMessage("members.membersChanged", null, locale);
            return ResponseEntity.ok(msg);
        } else {
            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
        }
    }

    private ResponseEntity saveUser(User user, UserData newData, Principal p, HttpServletResponse response,
            boolean add) throws ServletException {
        try {
            if (user != null) {
                user.setScreenName(newData.user.getScreenName().trim());
                user.setEmailAddress(newData.user.getEmailAddress().trim());

                if (!UserStatus.ENABLED.equals(user.getStatus())
                        && StringUtils.isNotEmpty(newData.user.getActivationCode())) {
                    user.setActivationCode(newData.user.getActivationCode());
                }

                if (add) {
                    user.setStatus(newData.user.getStatus());
                    if (userRepository.count() == 0) {
                        // first person in is always an admin
                        user.setGlobalRole(GlobalRole.ADMIN);
                    } else {
                        user.setGlobalRole(webloggerPropertiesRepository.findOrNull().isUsersCreateBlogs()
                                ? GlobalRole.BLOGCREATOR
                                : GlobalRole.BLOGGER);
                    }
                } else {
                    // users can't alter own roles or status
                    if (!user.getUserName().equals(p.getName())) {
                        user.setGlobalRole(newData.user.getGlobalRole());
                        user.setStatus(newData.user.getStatus());
                    }
                }

                try {
                    userRepository.saveAndFlush(user);
                    userRepository.evictUser(user);
                    // reset password if set
                    if (newData.credentials != null) {
                        if (!StringUtils.isEmpty(newData.credentials.getPasswordText())) {
                            userManager.updateCredentials(user.getId(), newData.credentials.getPasswordText());
                        }
                        // reset MFA secret if requested
                        if (newData.credentials.isEraseMfaSecret()) {
                            userCredentialsRepository.eraseMfaCode(user.getId());
                        }
                    }
                    response.setStatus(HttpServletResponse.SC_OK);
                } catch (RollbackException e) {
                    return ResponseEntity.status(HttpServletResponse.SC_CONFLICT).body("Persistence Problem");
                }
            } else {
                return new ResponseEntity<>(HttpStatus.NOT_FOUND);
            }
            UserData data = new UserData();
            data.setUser(user);
            UserCredentials creds = userCredentialsRepository.findByUserName(user.getUserName());
            data.setCredentials(creds);
            return ResponseEntity.ok(data);
        } catch (Exception e) {
            log.error("Error updating user", e);
            throw new ServletException(e);
        }
    }

    private ValidationError advancedValidate(User currentUser, UserData data, boolean isAdd, Locale locale) {
        BindException be = new BindException(data, "new data object");

        User testHasUserName = userRepository.findByUserName(data.user.getUserName());
        if (testHasUserName != null && !testHasUserName.getId().equals(data.user.getId())) {
            be.addError(new ObjectError("User object",
                    messages.getMessage("error.add.user.userNameInUse", null, locale)));
        }

        User testHasScreenName = userRepository.findByScreenName(data.user.getScreenName());
        if (testHasScreenName != null && !testHasScreenName.getId().equals(data.user.getId())) {
            be.addError(new ObjectError("User object",
                    messages.getMessage("error.add.user.screenNameInUse", null, locale)));
        }

        if (currentUser != null) {
            UserStatus currentStatus = currentUser.getStatus();
            if (currentStatus != data.getUser().getStatus()) {
                switch (currentStatus) {
                case ENABLED:
                    if (data.getUser().getStatus() != UserStatus.DISABLED) {
                        be.addError(new ObjectError("User object",
                                messages.getMessage("error.useradmin.enabled.only.disabled", null, locale)));
                    }
                    break;
                case DISABLED:
                    if (data.getUser().getStatus() != UserStatus.ENABLED) {
                        be.addError(new ObjectError("User object",
                                messages.getMessage("error.useradmin.disabled.only.enabled", null, locale)));
                    }
                    break;
                case REGISTERED:
                case EMAILVERIFIED:
                    if (data.getUser().getStatus() != UserStatus.ENABLED) {
                        be.addError(new ObjectError("User object",
                                messages.getMessage("error.useradmin.nonenabled.only.enabled", null, locale)));
                    }
                    break;
                default:
                }
            }
        }

        if (data.credentials != null) {
            String maybePassword = data.credentials.getPasswordText();
            if (!StringUtils.isEmpty(maybePassword)) {
                if (!maybePassword.equals(data.credentials.getPasswordConfirm())) {
                    be.addError(new ObjectError("User object",
                            messages.getMessage("error.add.user.passwordConfirmFail", null, locale)));
                } else {
                    if (!PWD_PATTERN.matcher(maybePassword).matches()) {
                        be.addError(new ObjectError("User object",
                                messages.getMessage("error.add.user.passwordComplexityFail", null, locale)));
                    }
                }
            } else {
                if (!StringUtils.isEmpty(data.credentials.getPasswordConfirm())) {
                    // confirm provided but password field itself not filled out
                    be.addError(new ObjectError("User object",
                            messages.getMessage("error.add.user.passwordConfirmFail", null, locale)));
                }
            }

            if (isAdd && StringUtils.isEmpty(data.credentials.getPasswordText())) {
                be.addError(new ObjectError("User object",
                        messages.getMessage("error.add.user.missingPassword", null, locale)));
            }
        }

        return be.getErrorCount() > 0 ? ValidationError.fromBindingErrors(be) : null;
    }

    @GetMapping(value = "/tb-ui/admin/rest/useradmin/user/{id}/weblogs")
    public List<UserWeblogRole> getUsersWeblogs(@PathVariable String id, HttpServletResponse response)
            throws ServletException {
        User user = userRepository.findByIdOrNull(id);
        if (user == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return null;
        }
        List<UserWeblogRole> uwrs = userWeblogRoleRepository.findByUser(user);
        for (UserWeblogRole uwr : uwrs) {
            entityManager.detach(uwr); // uwr now a DTO
            uwr.getWeblog().setAbsoluteURL(urlService.getWeblogURL(uwr.getWeblog()));
            uwr.setUser(null);
        }
        return uwrs;
    }

    @GetMapping(value = "/tb-ui/authoring/rest/loggedinuser/weblogs")
    public List<UserWeblogRole> getLoggedInUsersWeblogs(Principal p, HttpServletResponse response)
            throws ServletException {
        User user = userRepository.findEnabledByUserName(p.getName());
        if (user == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return null;
        }

        List<UserWeblogRole> uwrs = userWeblogRoleRepository.findByUser(user);
        for (UserWeblogRole uwr : uwrs) {
            entityManager.detach(uwr); // uwr now a DTO
            uwr.getWeblog().setAbsoluteURL(urlService.getWeblogURL(uwr.getWeblog()));
            uwr.getWeblog().setUnapprovedComments(
                    weblogEntryCommentRepository.countByWeblogAndStatusUnapproved(uwr.getWeblog()));
            uwr.setUser(null);
        }

        return uwrs;
    }

    @PostMapping(value = "/tb-ui/authoring/rest/weblogrole/{id}/emails/{emailComments}")
    public void setEmailCommentsForWeblog(@PathVariable String id, @PathVariable boolean emailComments, Principal p,
            HttpServletResponse response) {
        UserWeblogRole uwr = userWeblogRoleRepository.findByIdOrNull(id);
        if (uwr != null && uwr.getUser().getUserName().equals(p.getName())) {
            uwr.setEmailComments(emailComments);
            userWeblogRoleRepository.saveAndFlush(uwr);
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        }
    }

    @PostMapping(value = "/tb-ui/authoring/rest/weblogrole/{id}/detach")
    public void resignFromWeblog(@PathVariable String id, Principal p, HttpServletResponse response) {
        UserWeblogRole uwr = userWeblogRoleRepository.findByIdOrNull(id);
        if (uwr != null && uwr.getUser().getUserName().equals(p.getName())) {
            userManager.deleteUserWeblogRole(uwr);
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        }
    }

    @GetMapping(value = "/tb-ui/register/rest/useradminmetadata")
    public UserAdminMetadata getUserAdminMetadata() {
        UserAdminMetadata metadata = new UserAdminMetadata();

        metadata.userStatuses = Arrays.stream(UserStatus.values())
                .collect(Utilities.toLinkedHashMap(UserStatus::name, UserStatus::name));

        metadata.globalRoles = Arrays.stream(GlobalRole.values()).filter(r -> r != GlobalRole.NOAUTHNEEDED)
                .collect(Utilities.toLinkedHashMap(GlobalRole::name, GlobalRole::name));

        return metadata;
    }

    public static class UserAdminMetadata {
        Map<String, String> userStatuses;
        Map<String, String> globalRoles;

        public Map<String, String> getUserStatuses() {
            return userStatuses;
        }

        public Map<String, String> getGlobalRoles() {
            return globalRoles;
        }
    }
}