public class GlobalConstants {

    public static final String PARTY_NAME_STRING = "partyName";
    public static final String ASCENDING_STRING = "asc";
    public static final String DESCENDING_STRING = "desc";
    public static final String JWT_SUBJECT_ATTRIBUTE_STRING = "sub";
    public static final String JWT_EXPIRY_ATTRIBUTE_STRING = "exp";
    public static final String JWT_TYPE_ATTRIBUTE_STRING = "type";
    public static final String EMAIL_STRING = "email";
    public static final String USER_NAME_STRING = "username";

    // OAUTH Related Constants
    public static final String CLIENT_CREDENTIALS_FLOW = "client_credentials";
    public static final String AUTHORIZATION_CODE_FLOW = "authorization_code";
    public static final String REFRESH_TOKEN_FLOW = "refresh_token";

} public class Credentials {

    private String username = null;

    private String password = null;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Credentials{" + "username='" + username + '\'' + ", password='*******" + '}';
    }
} public class FrontEndUser {
    private String username = null;

    private String firstname = null;

    private String lastname = null;

    private String email = null;

    private LocalDate dateOfBirth = null;

    private String placeOBirth = null;

    private String phoneNumber = null;

    private Long userID = null;

    private String companyID = null;

    private Map<NimbleConfigurationProperties.LanguageID, String> companyName = null;

    private String accessToken = null;

    private String rocketChatToken = null;

    private String rocketChatUsername = null;

    private String rocketChatUserID = null;

    private Boolean showWelcomeInfo = false;

    private String vat = null;

    public Map<NimbleConfigurationProperties.LanguageID, String> getCompanyName() {
        return companyName;
    }

    public void setCompanyName(Map<NimbleConfigurationProperties.LanguageID, String> companyName) {
        this.companyName = companyName;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public LocalDate getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(LocalDate dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    public String getPlaceOBirth() {
        return placeOBirth;
    }

    public void setPlaceOBirth(String placeOBirth) {
        this.placeOBirth = placeOBirth;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public Long getUserID() {
        return userID;
    }

    public void setUserID(Long userID) {
        this.userID = userID;
    }

    public String getCompanyID() {
        return companyID;
    }

    public void setCompanyID(String companyID) {
        this.companyID = companyID;
    }

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public Boolean getShowWelcomeInfo() {
        return showWelcomeInfo;
    }

    public void setShowWelcomeInfo(Boolean showWelcomeInfo) {
        this.showWelcomeInfo = showWelcomeInfo;
    }

    public String getRocketChatToken() {
        return rocketChatToken;
    }

    public void setRocketChatToken(String rocketChatToken) {
        this.rocketChatToken = rocketChatToken;
    }

    public String getRocketChatUsername() {
        return rocketChatUsername;
    }

    public void setRocketChatUsername(String rocketChatUsername) {
        this.rocketChatUsername = rocketChatUsername;
    }

    public String getRocketChatUserID() {
        return rocketChatUserID;
    }

    public void setRocketChatUserID(String rocketChatUserID) {
        this.rocketChatUserID = rocketChatUserID;
    }

    public String getVat() {
        return vat;
    }

    public void setVat(String vat) {
        this.vat = vat;
    }

    @Override
    public String toString() {
        return "FrontEndUser{" +
                "username='" + username + '\'' +
                ", firstname='" + firstname + '\'' +
                ", lastname='" + lastname + '\'' +
                ", email='" + email + '\'' +
                ", dateOfBirth=" + dateOfBirth +
                ", placeOBirth='" + placeOBirth + '\'' +
                ", phoneNumber='" + phoneNumber + '\'' +
                ", userID=" + userID +
                ", companyID='" + companyID + '\'' +
                ", companyName='" + companyName + '\'' +
                ", showWelcomeInfo=" + showWelcomeInfo +
                ", vat='" + vat + '\'' +
                '}';
    }
} @Controller
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
public class IdentityController {

    public static final String REFRESH_TOKEN_SESSION_KEY = "refresh_token";

    private static final Logger logger = LoggerFactory.getLogger(IdentityController.class);

    @Autowired
    private PersonRepository personRepository;

    @Autowired
    private PartyRepository partyRepository;

    @Autowired
    private DelegateServiceClient delegateServiceClient;

    @Autowired
    private ExecutionContext executionContext;

    @Autowired
    private FederationConfig federationConfig;

    @Autowired
    private QualifyingPartyRepository qualifyingPartyRepository;

    @Autowired
    private DeliveryTermsRepository deliveryTermsRepository;

    @Autowired
    private PaymentMeansRepository paymentMeansRepository;

    @Autowired
    private UaaUserRepository uaaUserRepository;

    @Autowired
    private UserInvitationRepository userInvitationRepository;

    @Autowired
    private KeycloakAdmin keycloakAdmin;

    @Autowired
    private OAuthClient oAuthClient;

    @Autowired
    private HttpSession httpSession;

    @Autowired
    private EmailService emailService;

    @Autowired
    private IdentityService identityService;

    @Autowired
    private UblUtils ublUtils;

    @Autowired
    private RocketChatService chatService;

    @Autowired
    private FederationService federationService;

    @Autowired
    private IndexingClientController indexingController;


    @ApiOperation(value = "Provide Nimble Token for a trusted identity provider token.", tags = {})
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Token Generated"),
            @ApiResponse(code = 400, message = "Invalid Token")})
    @RequestMapping(value = "/federation/exchangeToken", produces = {"application/json"}, method = RequestMethod.GET)
    ResponseEntity<FederationResponse> exchangeToken(@RequestHeader(value = "efToken") String efToken,
                                        @RequestHeader(value = "efEndpoint") String efEndpoint, HttpServletResponse response) throws ServerException, URISyntaxException {

        // TODO Remove hardcoded values and migrate to another service
        logger.info("Request Received for Federation, efEndpoint: " + efEndpoint + " efToken: " + efToken);

        if (!federationService.verifyToken(efToken)) {
            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
        }

        String vfosEndpoint = "https://nifi.smecluster.com/l33t/products/vfos";
        String nimbleEndpoint = "https://nifi.smecluster.com/l33t/products/nimble";
        String nimbleImagesEndpoint = "https://nifi.smecluster.com/l33t/products/nimbleImages";
        String smeClusterEndpoint = "https://nifi.smecluster.com/l33t/products/smecluster";

        HashSet<String> authorizedResources = new HashSet<String>();
        authorizedResources.add(vfosEndpoint);
        authorizedResources.add(nimbleEndpoint);
        authorizedResources.add(smeClusterEndpoint);
        authorizedResources.add(nimbleImagesEndpoint);

        FederationResponse federationResponse = new FederationResponse();

        String rootURI = efEndpoint.split("\\?")[0];
        if(rootURI.endsWith("/")){
            rootURI = rootURI.substring(0, rootURI.length() - 1);
        }


        if (authorizedResources.contains(rootURI)) {

            if (vfosEndpoint.equals(rootURI)) {
                response.addHeader("ssoToken", "HoQkZDFbTyeEQtkOI1KD4XXra7DPc5VBK4wHaQDlY3Qz6U0FVQ");
                federationResponse.setSsoToken("HoQkZDFbTyeEQtkOI1KD4XXra7DPc5VBK4wHaQDlY3Qz6U0FVQ");

            } else if (nimbleEndpoint.equals(rootURI)) {

                Token token = federationService.exchangeToken(efToken);
                response.addHeader("ssoToken", token.getAccess_token());
                federationResponse.setSsoToken(token.getAccess_token());
            }

            if (null == federationResponse.getSsoToken()) {
                federationResponse.setSsoToken("null");
                response.addHeader("ssoToken", "null");
            }
        }else {
            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
        }
        return new ResponseEntity<>(federationResponse, HttpStatus.OK);
    }

    @ApiOperation(value = "Verify a token.", tags = {})
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Valid Token"),
            @ApiResponse(code = 400, message = "Invalid Token")})
    @RequestMapping(value = "/verify", produces = {"application/json"}, consumes = {"application/json"}, method = RequestMethod.POST)
    ResponseEntity verifyToken(@ApiParam(value = "Token provided by the IDP", required = true) @RequestBody Token token) throws ServerException {
        boolean status = keycloakAdmin.verify(token.getAccess_token());
        if (status) {
            return new ResponseEntity<>(HttpStatus.OK);
        }else {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
    }

    @ApiOperation(value = "Authenticate a federated user.", response = FrontEndUser.class, tags = {})
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "User authenticated", response = FrontEndUser.class),
            @ApiResponse(code = 400, message = "Invalid Token", response = FrontEndUser.class)})
    @RequestMapping(value = "/federation/login", produces = {"application/json"}, consumes = {"application/json"}, method = RequestMethod.POST)
    ResponseEntity<FrontEndUser> loginFederatedUser(
            @ApiParam(value = "Access token provided by the IDP", required = true) @RequestBody Token token) throws IOException {

        logger.info("got the code from efacotry"+token.toString());

        FrontEndUser frontEndUser = new FrontEndUser();

        if (token.getCode() == null) {
            return new ResponseEntity<>(frontEndUser, HttpStatus.BAD_REQUEST);
        }

        token = federationService.getAccessToken(token.getCode(), GlobalConstants.AUTHORIZATION_CODE_FLOW, null, token.getRedirect_URL());

        if (null == token.getAccess_token()) {
            return new ResponseEntity<>(frontEndUser, HttpStatus.BAD_REQUEST);
        }

        String accessToken = token.getAccess_token();
        String audience = JWT.decode(accessToken).getClaim("aud").asString();
        String keycloakUserID = JWT.decode(accessToken).getClaim("sub").asString();
        String email = JWT.decode(accessToken).getClaim("email").asString();
        // get user resource
        UserResource userResource = keycloakAdmin.getUserResource(keycloakUserID);
        if(userResource != null){
            // check whether the user is an eFactory user
            String eFactoryUserId = keycloakAdmin.getEFactoryUserId(userResource);
            if(eFactoryUserId != null){
                boolean refreshToken = false;
                // the user is an eFactory user but the token does not have eFactoryUser role
                // add this role to the user and refresh the token
                if(!identityService.hasAnyRole(accessToken, EFACTORY_USER)){
                    // add eFactoryUser role
                    keycloakAdmin.addRole(keycloakUserID,EFACTORY_USER.toString());
                    refreshToken = true;
                }
                // the user does not have VAT number
                Map<String,List<String>> attributes = userResource.toRepresentation().getAttributes();
                if(attributes == null || !attributes.containsKey("vatin")){
                    // retrieve VAT number from EFactory Keycloak
                    String vat = federationService.getEFactoryUserVatAttribute(eFactoryUserId);
                    // add it to the user
                    if(vat != null){
                        UserRepresentation userRepresentation = userResource.toRepresentation();
                        if(userRepresentation.getAttributes() == null){
                            userRepresentation.setAttributes(new HashMap<>());
                        }
                        userRepresentation.getAttributes().put("vatin", Collections.singletonList(vat));
                        userResource.update(userRepresentation);
                        refreshToken = true;
                    }
                }

                if(refreshToken){
                    // get token
                    token = federationService.getAccessToken(null,GlobalConstants.REFRESH_TOKEN_FLOW,token.getRefresh_token(),null);
                    accessToken = token.getAccess_token();
                }
            }
        }

        Claim companyClaim = JWT.decode(accessToken).getClaim("company");
        if(!companyClaim.isNull()){
            String vatin = companyClaim.asMap().get("vatin").toString();
            frontEndUser.setVat(vatin);
        }

        // check identity database
        UaaUser potentialUser = uaaUserRepository.findByExternalID(keycloakUserID);
        if (potentialUser == null) {

            logger.info("User " + email + " not found in local database, but on Keycloak.");
            // create a new user

            frontEndUser.setUsername(email);
            frontEndUser.setFirstname(JWT.decode(accessToken).getClaim("given_name").asString());
            frontEndUser.setLastname(JWT.decode(accessToken).getClaim("family_name").asString());
            // create UBL party of user
            PersonType newUser = UblAdapter.adaptPerson(frontEndUser);
            personRepository.save(newUser);

            // update id of user
            newUser.setID(newUser.getHjid().toString());
            personRepository.save(newUser);

            // create entry in identity DB
            UaaUser uaaUser = new UaaUser(email, newUser, keycloakUserID);
            uaaUserRepository.save(uaaUser);

            // update user data
            frontEndUser.setUserID(Long.parseLong(newUser.getID()));
            frontEndUser.setUsername(email);
            frontEndUser.setAccessToken(accessToken);

            logger.info("Registering a new user with email {} and id {}", frontEndUser.getEmail(), frontEndUser.getUserID());

        }else {
            // create front end user DTO
            List<PartyType> companies = partyRepository.findByPerson(potentialUser.getUBLPerson());
            frontEndUser = UblAdapter.adaptUser(potentialUser, companies);

            // set and store tokens
            frontEndUser.setAccessToken(accessToken);

            logger.info("User " + email + " successfully logged in.");
        }
        httpSession.setAttribute(REFRESH_TOKEN_SESSION_KEY, token.getRefresh_token());
        return new ResponseEntity<>(frontEndUser, HttpStatus.OK);
    }

    @ApiOperation(value = "Register a new user to the nimble.", response = FrontEndUser.class, tags = {})
    @ApiResponses(value = {
            @ApiResponse(code = 201, message = "User created", response = FrontEndUser.class),
            @ApiResponse(code = 405, message = "User not registered", response = FrontEndUser.class)})
    @RequestMapping(value = "/register/user", produces = {"application/json"}, consumes = {"application/json"}, method = RequestMethod.POST)
    ResponseEntity<FrontEndUser> registerUser(
            @ApiParam(value = "User object that needs to be registered to Nimble.", required = true) @RequestBody UserRegistration userRegistration) {

        FrontEndUser frontEndUser = userRegistration.getUser();
        Credentials credentials = userRegistration.getCredentials();

        // validate data
        if (frontEndUser == null || credentials == null
                || credentials.getUsername() == null || credentials.getUsername().equals(frontEndUser.getEmail()) == false) {
            Map<String,String> paramMap = new HashMap<String, String>();
            paramMap.put("activity", LogEvent.REGISTER_USER_ERROR.getActivity());
            LoggerUtils.logWithMDC(logger, paramMap, LoggerUtils.LogLevel.INFO, " Tried to register an invalid user {}", userRegistration.toString());
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

        // create user on Keycloak
        String keycloakID;
        try {
            keycloakID = keycloakAdmin.registerUser(
                    frontEndUser.getFirstname(), frontEndUser.getLastname(), credentials.getPassword(), frontEndUser.getEmail());
        } catch (WebApplicationException ex) {
            Map<String,String> paramMap = new HashMap<String, String>();
            paramMap.put("activity", LogEvent.REGISTER_USER_ERROR.getActivity());
            LoggerUtils.logErrorWithMDC(logger, paramMap," Error occurred in keycloak while registering the user", ex);
            if (ex.getResponse().getStatus() == HttpStatus.CONFLICT.value())
                return new ResponseEntity<>(HttpStatus.CONFLICT);
            throw ex;
        }

        // check whether the user is already registered
        UaaUser uaaUser = uaaUserRepository.findOneByUsername(frontEndUser.getEmail());
        if(uaaUser != null){
            logger.error("The user {} is already registered",userRegistration.toString());
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

        // create UBL party of user
        PersonType newUser = UblAdapter.adaptPerson(frontEndUser);
        personRepository.save(newUser);

        // update id of user
        newUser.setID(newUser.getHjid().toString());
        personRepository.save(newUser);

        // create entry in identity DB
        uaaUser = new UaaUser(credentials.getUsername(), newUser, keycloakID);
        uaaUserRepository.save(uaaUser);

        Map<String,String> paramMapReg = new HashMap<String, String>();
        paramMapReg.put("userId",credentials.getUsername());
        paramMapReg.put("activity", LogEvent.REGISTER_USER.getActivity());

        LoggerUtils.logWithMDC(logger, paramMapReg, LoggerUtils.LogLevel.INFO, "Invitation: added user {}({}) to company {}({})", frontEndUser.getEmail(),
                newUser.getID());
        // update user data
        frontEndUser.setUserID(Long.parseLong(newUser.getID()));
        frontEndUser.setUsername(credentials.getUsername());

        // check if user was invited and add to company
        Optional<UserInvitation> invitationOpt = userInvitationRepository.findByEmail(frontEndUser.getEmail()).stream().findFirst();
        if (invitationOpt.isPresent()) {
            UserInvitation invitation = invitationOpt.get();

            // fetch company
            Optional<PartyType> companyOpt = partyRepository.findByHjid(Long.parseLong(invitation.getCompanyId())).stream().findFirst();
            if (companyOpt.isPresent() == false) {
                Map<String,String> paramMap = new HashMap<String, String>();
                paramMap.put("activity", LogEvent.REGISTER_USER_ERROR.getActivity());
                LoggerUtils.logWithMDC(logger, paramMap, LoggerUtils.LogLevel.ERROR, "Invalid invitation: Company %s not found", invitation.getCompanyId());
                return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
            }
            PartyType company = companyOpt.get();

            // add new user
            company.getPerson().add(newUser);
            partyRepository.save(company);

            // save new state of invitation
            invitation.setPending(false);
            userInvitationRepository.save(invitation);

            // set roles
            for (String role : invitation.getRoleIDs()) {
                try {
                    keycloakAdmin.addRole(keycloakID, role);
                }
                catch (Exception ex) {
                    logger.error("Error while setting role", ex);
                }
            }

            String companyName = ublUtils.getName(company);
            String companyId = UblAdapter.adaptPartyIdentifier(company);
            Map<String,String> paramMap = new HashMap<String, String>();
            paramMap.put("userId",credentials.getUsername());
            paramMap.put("companyId",companyId);
            paramMap.put("companyName",companyName);
            paramMap.put("activity", LogEvent.INVITED_USER_REGISTRATION.getActivity());
            LoggerUtils.logWithMDC(logger, paramMap, LoggerUtils.LogLevel.INFO, "Invitation: added user {}({}) to company {}({})", frontEndUser.getEmail(),
                    newUser.getID(), companyName, companyId);
        }

        // Create a user in rocket isChatEnabled
        if (chatService.isChatEnabled()) {
            chatService.registerUser(frontEndUser, credentials, false, 0);
        }
        logger.info("Registering a new user with email {} and id {}", frontEndUser.getEmail(), frontEndUser.getUserID());

        return new ResponseEntity<>(frontEndUser, HttpStatus.OK);
    }

    public @ApiOperation(value = "", notes = "Register company controller.", response = CompanyRegistration.class, tags = {})
    @ApiResponses(value = {
            @ApiResponse(code = 201, message = "Company registered", response = CompanyRegistration.class),
            @ApiResponse(code = 405, message = "Company not registered", response = CompanyRegistration.class)})
    @RequestMapping(value = "/register/company", produces = {"application/json"}, consumes = {"application/json"}, method = RequestMethod.POST)
    ResponseEntity<?> registerCompany(
            @ApiParam(value = "Company object that is registered on NIMBLE.", required = true) @RequestBody CompanyRegistration companyRegistration,
            @RequestHeader(value = "Authorization") String bearer,
            HttpServletResponse response, HttpServletRequest request) throws IOException {

        Address companyAddress = companyRegistration.getSettings().getDetails().getAddress();
        if (companyAddress == null || companyRegistration.getSettings().getDetails().getLegalName() == null)
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);

        Optional<PersonType> userPartyOpt = personRepository.findByHjid(companyRegistration.getUserID()).stream().findFirst();

        // check if user exists
        if (userPartyOpt.isPresent() == false) {
            logger.info("Cannot find user with id {}", companyRegistration.getUserID());
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

        PersonType userParty = userPartyOpt.get();

        // create company
        PartyType newCompany = UblAdapter.adaptCompanyRegistration(companyRegistration, userParty);
        partyRepository.save(newCompany);

        // create delivery terms
        DeliveryTermsType blankDeliveryTerms = new DeliveryTermsType();
        deliveryTermsRepository.save(blankDeliveryTerms);
        blankDeliveryTerms.setID(blankDeliveryTerms.getHjid().toString());
        deliveryTermsRepository.save(blankDeliveryTerms);

        // create payment means
        PaymentMeansType paymentMeans = UblUtils.emptyUBLObject(new PaymentMeansType());
        paymentMeansRepository.save(paymentMeans);
        paymentMeans.setID(paymentMeans.getHjid().toString());
        paymentMeansRepository.save(paymentMeans);

        // create purchase terms
        TradingPreferences purchaseTerms = new TradingPreferences();
        purchaseTerms.getDeliveryTerms().clear();
        purchaseTerms.getDeliveryTerms().add(blankDeliveryTerms);
        purchaseTerms.getPaymentMeans().clear();
        purchaseTerms.getPaymentMeans().add(paymentMeans);
        newCompany.setPurchaseTerms(purchaseTerms);

        // update id of company
        UblUtils.setID(newCompany, newCompany.getHjid().toString());
        // set federation id of company
        newCompany.setFederationInstanceID(federationConfig.getFederationInstanceId());
        // create metadata for the company
        MetadataType metadataType = MetadataUtility.createEntityMetadata(null,Arrays.asList(newCompany.getHjid().toString()));
        newCompany.setMetadata(metadataType);
        // save the company
        partyRepository.save(newCompany);

        // create qualifying party
        QualifyingPartyType qualifyingParty = UblAdapter.adaptQualifyingParty(companyRegistration.getSettings(), newCompany);
        qualifyingPartyRepository.save(qualifyingParty);

        // add id to response object
        companyRegistration.setCompanyID(newCompany.getHjid());
        companyRegistration.setUserID(userParty.getHjid());

        // adapt role of user and refresh access token
        try {
            String keyCloakId = getKeycloakUserId(userParty);
            keycloakAdmin.addRole(keyCloakId, KeycloakAdmin.INITIAL_REPRESENTATIVE_ROLE);
        } catch (Exception e) {
            logger.error("Could not set role for user " + userParty.getID(), e);
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }

        // inform platform managers
        try {
            informPlatformManager(userParty, newCompany);
        } catch (Exception ex) {
            logger.error("Could not notify platform managers", ex);
        }

        // refresh tokens
        if (identityService.hasAnyRole(bearer, EFACTORY_USER) && httpSession.getAttribute(REFRESH_TOKEN_SESSION_KEY) != null) {
            Token token = federationService.getAccessToken(null, GlobalConstants.REFRESH_TOKEN_FLOW, httpSession.getAttribute(REFRESH_TOKEN_SESSION_KEY).toString(), null);
            companyRegistration.setAccessToken(token.getAccess_token());
        }else if(httpSession.getAttribute(REFRESH_TOKEN_SESSION_KEY) != null) {
            OAuth2AccessToken tokenResponse = oAuthClient.refreshToken(httpSession.getAttribute(REFRESH_TOKEN_SESSION_KEY).toString());
            httpSession.setAttribute(REFRESH_TOKEN_SESSION_KEY, tokenResponse.getRefreshToken());
            companyRegistration.setAccessToken(tokenResponse.getValue());
        }

        //indexing the new company in the indexing service
        eu.nimble.service.model.solr.party.PartyType newParty = DataModelUtils.toIndexParty(newCompany,qualifyingParty);
        List<IndexingClient> indexingClients = indexingController.getClients();
        for (IndexingClient indexingClient : indexingClients) {
            indexingClient.setParty(newParty, bearer);
        }

        String companyName = ublUtils.getName(newCompany);
        String companyId = String.valueOf(companyRegistration.getCompanyID());
        String userId = String.valueOf(companyRegistration.getUserID());
        Map<String,String> paramMap = new HashMap<String, String>();
        paramMap.put("userId", userId);
        paramMap.put("companyId",companyId);
        paramMap.put("companyName",companyName);
        paramMap.put("activity", LogEvent.REGISTER_COMPANY.getActivity());
        LoggerUtils.logWithMDC(logger, paramMap, LoggerUtils.LogLevel.INFO, "Registered company with id {} for user with id {}", companyRegistration.getCompanyID(), companyRegistration.getUserID());

        return new ResponseEntity<>(companyRegistration, HttpStatus.OK);
    }

    @ApiOperation(value = "", notes = "Login controller for rocket isChatEnabled.", response = CompanyRegistrationResponse.class, tags = {})
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Successful login", response = FrontEndUser.class),
            @ApiResponse(code = 401, message = "Unauthorized access", response = FrontEndUser.class)})
    @RequestMapping(value = "/sso", produces = {"application/json"}, method = RequestMethod.POST)
    ResponseEntity sso(@CookieValue(value = "rocket_chat_token") String rocketChatToken) {
        logger.info("Rocket isChatEnabled sso endpoint has been reached and the cookie value is : " + rocketChatToken);
        RocketChatResponse rocketChatResponse = new RocketChatResponse();
        rocketChatResponse.setLoginToken(rocketChatToken);
        return new ResponseEntity<>(rocketChatResponse, HttpStatus.OK);
    }

    @ApiOperation(value = "", notes = "Login controller with credentials.", response = CompanyRegistrationResponse.class, tags = {})
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Successful login", response = FrontEndUser.class),
            @ApiResponse(code = 401, message = "Login failed", response = FrontEndUser.class)})
    @RequestMapping(value = "/login", produces = {"application/json"}, method = RequestMethod.POST)
    ResponseEntity<FrontEndUser> loginUser(
            @ApiParam(value = "User object that needs to be registered to Nimble.", required = true) @RequestBody Credentials credentials,
            HttpServletResponse response) {

        // invalidate old session (e.g. of previous user)
        httpSession.invalidate();

        // try to obtain access token
        OAuth2AccessToken accessToken;
        String keycloakUserID;
        try {
            Map<String,String> paramMap = new HashMap<String, String>();
            paramMap.put("userId",credentials.getUsername());
            paramMap.put("activity", LogEvent.LOGIN_ATTEMPT.getActivity());
            LoggerUtils.logWithMDC(logger, paramMap, LoggerUtils.LogLevel.INFO, "User " + credentials.getUsername() + " wants to login...");
            accessToken = oAuthClient.getToken(credentials.getUsername(), credentials.getPassword());
            keycloakUserID = new OpenIdConnectUserDetails(accessToken.getValue()).getUserId();
        } catch (OAuth2AccessDeniedException ex) {
            Map<String,String> paramMap = new HashMap<String, String>();
            paramMap.put("userId",credentials.getUsername());
            paramMap.put("activity", LogEvent.LOGIN_ERROR.getActivity());
            LoggerUtils.logErrorWithMDC(logger, paramMap,"User " + credentials.getUsername() + " not found in Keycloak?", ex);
            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
        } catch (IOException ex) {
            Map<String,String> paramMap = new HashMap<String, String>();
            paramMap.put("userId",credentials.getUsername());
            paramMap.put("activity", LogEvent.LOGIN_ERROR.getActivity());
            LoggerUtils.logErrorWithMDC(logger, paramMap, "Error in decoding " + credentials.getUsername() + "'s access token", ex);
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }

        // check identity database
        UaaUser potentialUser = uaaUserRepository.findByExternalID(keycloakUserID);
        if (potentialUser == null) {
            logger.info("User " + credentials.getUsername() + " not found in local database, but on Keycloak.");
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }

        Set<String> roles = keycloakAdmin.getUserRoles(keycloakUserID);
        Iterator<String> iterator = roles.iterator();

        while (iterator.hasNext()){
            if(iterator.next().equals(KeycloakAdmin.NIMBLE_DELETED_USER)){
                logger.info("User " + credentials.getUsername() + " user already deleted from the platform.");
                return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
            }
        }

        // create front end user DTO
        List<PartyType> companies = partyRepository.findByPerson(potentialUser.getUBLPerson());
        FrontEndUser frontEndUser = UblAdapter.adaptUser(potentialUser, companies);

        // set and store tokens
        frontEndUser.setAccessToken(accessToken.getValue());
        httpSession.setAttribute(REFRESH_TOKEN_SESSION_KEY, accessToken.getRefreshToken().getValue());

        // add vat number to frontEndUser
        Claim companyClaim = JWT.decode(accessToken.getValue()).getClaim("company");
        if(!companyClaim.isNull()){
            frontEndUser.setVat(companyClaim.asMap().get("vatin").toString());
        }
        if(chatService.isChatEnabled()){
            RocketChatLoginResponse rocketChatToken = chatService.loginOrCreateUser(frontEndUser, credentials, true, true);
            frontEndUser.setRocketChatToken(rocketChatToken.getData().getAuthToken());
            frontEndUser.setRocketChatUsername(rocketChatToken.getData().getMe().getUsername());
            frontEndUser.setRocketChatUserID(rocketChatToken.getData().getUserId());
        }

        Map<String,String> paramMap = new HashMap<String, String>();
        paramMap.put("userId",credentials.getUsername());
        paramMap.put("activity", LogEvent.LOGIN_SUCCESS.getActivity());
        if (frontEndUser != null) {
            paramMap.put("companyId", frontEndUser.getCompanyID());
            if (frontEndUser.getCompanyName() != null) {
                paramMap.put("companyName", frontEndUser.getCompanyName().get(NimbleConfigurationProperties.LanguageID.ENGLISH));
            }
        }

        LoggerUtils.logWithMDC(logger, paramMap, LoggerUtils.LogLevel.INFO, "User " + credentials.getUsername() + " successfully logged in.");

        return new ResponseEntity<>(frontEndUser, HttpStatus.OK);
    }


    @ApiOperation(value = "", notes = "Reset a users password")
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = "Password reset was successful"),
        @ApiResponse(code = 400, message = "Password could not be reset")})
    @RequestMapping(value = "/reset-password", consumes = {"application/json"}, method = RequestMethod.POST)
    ResponseEntity<?> resetPassword(
            @RequestHeader(value = "Authorization") String bearerToken,
            @ApiParam(value = "Old and new credentials", required = true) @RequestBody ResetPassword resetPasswordCredentials) throws IOException {

        UaaUser user = identityService.getUserfromBearer(bearerToken);

        // request password change
        boolean success = keycloakAdmin.resetPassword(user, resetPasswordCredentials.getOldPassword(), resetPasswordCredentials.getNewPassword());

        return success ? ResponseEntity.ok().build() : ResponseEntity.badRequest().build();
    }

    @ApiOperation(value = "", notes = "Send email to reset the password")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Password reset email sent successfully"),
            @ApiResponse(code = 404, message = "Username not found")})
    @RequestMapping(value = "/password-recovery", consumes = {"application/json"}, method = RequestMethod.POST)
    ResponseEntity<?> passwordRecovery(@ApiParam(value = "Email Account", required = true) @RequestBody ResetCredentials resetCredentials) throws IOException {
        logger.info("Password recovery request received for : {}", resetCredentials.getUsername());
        String token = keycloakAdmin.initiatePasswordRecoveryProcess(resetCredentials.getUsername());
        emailService.sendResetCredentialsLink(resetCredentials.getUsername(), token,executionContext.getLanguageId());
        return ResponseEntity.ok().build();
    }

    @ApiOperation(value = "", notes = "Reset a users password with action token")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Password reset was successful"),
            @ApiResponse(code = 400, message = "Invalid link/token")})
    @RequestMapping(value = "/reset-forgot-password", consumes = {"application/json"}, method = RequestMethod.POST)
    ResponseEntity<?> resetForgotPassword(@ApiParam(value = "Action token and new credentials", required = true) @RequestBody ResetCredentials resetCredentials) throws IOException {

        keycloakAdmin.resetPasswordViaRecoveryProcess(resetCredentials.getKey(), resetCredentials.getNewPassword());
        return ResponseEntity.ok().build();
    }

    @ApiOperation(value = "", notes = "Get user info", response = Map.class, tags = {})
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Found user", response = Map.class),
            @ApiResponse(code = 404, message = "User not found", response = Map.class)})
    @RequestMapping(value = "/user-info", produces = {"application/json"}, method = RequestMethod.GET)
    ResponseEntity<?> getUserInfo(@RequestHeader(value = "Authorization") String bearer) throws IOException {

        OpenIdConnectUserDetails userDetails = OpenIdConnectUserDetails.fromBearer(bearer);

        String username = userDetails.getUsername();
        Optional<UaaUser> potentialUaaUser = uaaUserRepository.findByUsername(username).stream().findFirst();

        if (potentialUaaUser.isPresent()) {
            Map<String, String> userInfo = new HashMap<>();
            UaaUser uaaUser = potentialUaaUser.get();
            PersonType personType = uaaUser.getUBLPerson();
            userInfo.put("ublPersonID", personType.getID());
            Optional<PartyType> potentialPartyType = partyRepository.findByPerson(personType).stream().findFirst();
            if (potentialPartyType.isPresent()) {
                PartyType partyType = potentialPartyType.get();
                userInfo.put("ublPartyID", UblAdapter.adaptPartyIdentifier(partyType));
            }

            return ResponseEntity.ok(userInfo);
        }

        return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
    }

    @ApiOperation(value = "", notes = "Set welcome info flag")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Changed flag"),
            @ApiResponse(code = 404, message = "User not found")})
    @RequestMapping(value = "/set-welcome-info/{flag}", produces = {"application/json"}, method = RequestMethod.POST)
    ResponseEntity<?> setShowWelcomeInfoFlag(
            @ApiParam(value = "Show welcome info flag", required = true) @PathVariable Boolean flag,
            @RequestHeader(value = "Authorization") String bearer) throws IOException {

        UaaUser user = identityService.getUserfromBearer(bearer);
        user.setShowWelcomeInfo(flag);
        uaaUserRepository.save(user);

        return ResponseEntity.ok().build();
    }

    private String getKeycloakUserId(PersonType ublPerson) throws Exception {
        List<UaaUser> potentialUser = uaaUserRepository.findByUblPerson(ublPerson);
        UaaUser uaaUser = potentialUser.stream().findFirst().orElseThrow(() -> new Exception("Invalid user mapping"));
        return uaaUser.getExternalID();
    }

    private void informPlatformManager(PersonType representative, PartyType company) {
        List<UserRepresentation> managers = keycloakAdmin.getPlatformManagers();
        List<String> emails = managers.stream().map(UserRepresentation::getEmail).collect(Collectors.toList());

        emailService.notifyPlatformManagersNewCompany(emails, representative, company,executionContext.getLanguageId());
    }

    @ApiOperation(value = "Update user's favourite list of id's", response = String.class)
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Favourite id's successfully applied", response = String[].class),
            @ApiResponse(code = 401, message = "Not authorized"),
            @ApiResponse(code = 404, message = "User not found"),
            @ApiResponse(code = 400, message = "Error while applying roles")})
    @RequestMapping(value = "/favourite/{personId}", consumes = {"application/json"},produces = {"application/json"}, method = RequestMethod.PUT)
    ResponseEntity<?> setFavouriteIdList(
            @ApiParam(value = "Id of company to change settings from.", required = true) @PathVariable Long personId,
            @RequestParam("status") Integer status,
            @ApiParam(value = "Set of roles to apply.", required = true) @RequestBody List<String> itemIds) throws IOException {

        logger.debug("Requesting person favourite catalogue line id's for {}", personId);
        // search for persons
        List<PersonType> foundPersons = personRepository.findByHjid(personId);

        // check if person was found
        if (foundPersons.isEmpty()) {
            logger.info("Requested person with Id {} not found", personId);
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }

        PersonType person = foundPersons.get(0);
        List<String> fhjids = person.getFavouriteProductID();

        if(status == 1){
            String exists =  fhjids.stream().filter(x -> x.equals(itemIds.get(0))).findAny().orElse(null);
            if(exists == null){
                fhjids.add(itemIds.get(0));
            }else {
                fhjids.remove(itemIds.get(0));
            }
        }else {
          fhjids.removeAll(itemIds);
        }
        person.setFavouriteProductID(fhjids);
        personRepository.save(person);
        return ResponseEntity.ok().build();

    }
} public class CreateChannelRequest {

    private String userId;
    private String userToken;
    private String initiatingPartyID;
    private String respondingPartyID;
    private String productName;
    private String channelName;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserToken() {
        return userToken;
    }

    public void setUserToken(String userToken) {
        this.userToken = userToken;
    }

    public String getInitiatingPartyID() {
        return initiatingPartyID;
    }

    public void setInitiatingPartyID(String initiatingPartyID) {
        this.initiatingPartyID = initiatingPartyID;
    }

    public String getRespondingPartyID() {
        return respondingPartyID;
    }

    public void setRespondingPartyID(String respondingPartyID) {
        this.respondingPartyID = respondingPartyID;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getChannelName() {
        return channelName;
    }

    public void setChannelName(String channelName) {
        this.channelName = channelName;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("class CreateChannelRequest {\n");

        sb.append("    initiatingPartyID: ").append(toIndentedString(initiatingPartyID)).append("\n");
        sb.append("    respondingPartyID: ").append(toIndentedString(respondingPartyID)).append("\n");
        sb.append("    productName: ").append(toIndentedString(productName)).append("\n");
        sb.append("    channelName: ").append(toIndentedString(channelName)).append("\n");
        sb.append("}");
        return sb.toString();
    }

    /**
     * Convert the given object to string with each line indented by 4 spaces
     * (except the first line).
     */
    private String toIndentedString(Object o) {
        if (o == null) {
            return "null";
        }
        return o.toString().replace("\n", "\n    ");
    }
} public class CreateChannelResponse {

    private boolean success;

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }
} public class ChatUser {

    private String username;
    private ArrayList<UserEmail> emails;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public ArrayList<UserEmail> getEmails() {
        return emails;
    }

    public void setEmails(ArrayList<UserEmail> emails) {
        this.emails = emails;
    }
} public class ChatUsers {

    private ArrayList<ChatUser> users;

    public ArrayList<ChatUser> getUsers() {
        return users;
    }

    public void setUsers(ArrayList<ChatUser> users) {
        this.users = users;
    }
} public class UserEmail {

    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
} public class RocketChatLoginResponse {

    private String status;
    private RocketChatLoginResponseData data;

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public RocketChatLoginResponseData getData() {
        return data;
    }

    public void setData(RocketChatLoginResponseData data) {
        this.data = data;
    }
} public class RockerChatRegisterResponse {

    private boolean success = false;
    private String error;
    private RocketChatUser user;

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public RocketChatUser getUser() {
        return user;
    }

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

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }
} public class RocketChatDeleteResponse {

    private boolean success = false;
    private String error;

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }
}
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.nimble.core.infrastructure.identity.constants.GlobalConstants;
import eu.nimble.core.infrastructure.identity.entity.dto.Credentials;
import eu.nimble.core.infrastructure.identity.entity.dto.FrontEndUser;
import eu.nimble.core.infrastructure.identity.system.IdentityController;
import eu.nimble.core.infrastructure.identity.system.dto.rocketchat.channel.CreateChannelRequest;
import eu.nimble.core.infrastructure.identity.system.dto.rocketchat.channel.CreateChannelResponse;
import eu.nimble.core.infrastructure.identity.system.dto.rocketchat.list.ChatUser;
import eu.nimble.core.infrastructure.identity.system.dto.rocketchat.list.ChatUsers;
import eu.nimble.core.infrastructure.identity.system.dto.rocketchat.list.UserEmail;
import eu.nimble.core.infrastructure.identity.system.dto.rocketchat.login.RocketChatLoginResponse;
import eu.nimble.core.infrastructure.identity.system.dto.rocketchat.register.RockerChatRegisterResponse;
import eu.nimble.core.infrastructure.identity.system.dto.rocketchat.register.RocketChatDeleteResponse;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("X-User-Id", userID);
        headers.set("X-Auth-Token", authToken);
        HttpEntity<String> entity = new HttpEntity<String>(headers);

        RestTemplate rs = new RestTemplate();
        try {

            ResponseEntity<String> response = rs.exchange(uri, HttpMethod.GET, entity, String.class);
            ObjectMapper mapper = new ObjectMapper();
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

            try {
                chatUsers = mapper.readValue(response.getBody(), ChatUsers.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return chatUsers;
    }

    /**
     * The following method registers a user in Rocket.Chat, User name will be created firstname.lastname.email_domain
     *
     * @param frontEndUser
     * @param credentials
     * @param userNameAlreadyExists
     * @return
     */
    public RockerChatRegisterResponse registerUser(FrontEndUser frontEndUser, Credentials credentials, boolean userNameAlreadyExists, int retryCounter) {

        RockerChatRegisterResponse rockerChatRegisterResponse = new RockerChatRegisterResponse();

        try {
            RestTemplate rs = new RestTemplate();
            String uri = rocketChatURL + "/api/v1/users.register";

            String temp = credentials.getUsername().substring(credentials.getUsername().indexOf("@") + 1); // e.g. @google.com
            String companyEmailName = temp.substring(0, temp.indexOf("."));

            String rocketChatUserName = frontEndUser.getFirstname() + "." + frontEndUser.getLastname() + "." + companyEmailName;
            if (userNameAlreadyExists) {
                rocketChatUserName = rocketChatUserName + ((int) (Math.random() * 100));
            }

            JSONObject request = new JSONObject();
            request.put(GlobalConstants.EMAIL_STRING, credentials.getUsername());
            request.put("pass", new Md5PasswordEncoder().encodePassword(credentials.getUsername(), null).substring(0, 8));
            request.put(GlobalConstants.USER_NAME_STRING, rocketChatUserName);
            request.put("name", frontEndUser.getFirstname() + " " + frontEndUser.getLastname());

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);


            ResponseEntity<String> registerResponse = rs.exchange(uri, HttpMethod.POST, entity, String.class);
            ObjectMapper mapper = new ObjectMapper();
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            rockerChatRegisterResponse = new RockerChatRegisterResponse();
            rockerChatRegisterResponse = mapper.readValue(registerResponse.getBody(), RockerChatRegisterResponse.class);

            if (rockerChatRegisterResponse.isSuccess() && null == rockerChatRegisterResponse.getError()) {
                logger.info("A new user have been created in Rocket.Chat with username {}", rockerChatRegisterResponse.getUser().getUsername());
            }

            // If the user name already exists then a new user name should be created
            if (rockerChatRegisterResponse.isSuccess() && null != rockerChatRegisterResponse.getError()) {
                if (rockerChatRegisterResponse.getError().equals("Username is already in use") && retryCounter <= 1) {
                    logger.info("User name conflict when creating a new user with username {}", rocketChatUserName);
                    rockerChatRegisterResponse = registerUser(frontEndUser, credentials, true, retryCounter + 1);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return rockerChatRegisterResponse;
    }

    /**
     * The following method deletes a user from Rocket.Chat
     *
     * @param userEmailAddress
     * @return
     */
    public void deleteUser(String userEmailAddress) {
        // find the user for the given email address and delete it from Rocket.Chat
        ChatUsers chatUsers = listUsers();
        for (ChatUser user : chatUsers.getUsers()) {
            if(user.getEmails() != null){
                for (UserEmail userEmail : user.getEmails()) {
                    if(userEmail.getAddress().contentEquals(userEmailAddress)){
                        // delete the user from Rocket.Chat
                        Credentials credentials = new Credentials();
                        credentials.setUsername(rocketChatUser);
                        credentials.setPassword(rocketChatPassword);
                        RocketChatLoginResponse rocketChatLoginResponse = loginOrCreateUser(new FrontEndUser(), credentials, false, false);

                        RestTemplate rs = new RestTemplate();
                        String uri = rocketChatURL + "/api/v1/users.delete";

                        HttpHeaders headers = new HttpHeaders();
                        headers.setContentType(MediaType.APPLICATION_JSON);
                        headers.set("X-User-Id", rocketChatLoginResponse.getData().getUserId());
                        headers.set("X-Auth-Token", rocketChatLoginResponse.getData().getAuthToken());

                        JSONObject request = new JSONObject();
                        request.put(GlobalConstants.USER_NAME_STRING, user.getUsername());

                        HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);

                        ResponseEntity<String> registerResponse = rs.exchange(uri, HttpMethod.POST, entity, String.class);
                        ObjectMapper mapper = new ObjectMapper();
                        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

                        try{

                            RocketChatDeleteResponse rocketChatDeleteResponse = mapper.readValue(registerResponse.getBody(), RocketChatDeleteResponse.class);
