com.garyclayburg.persistence.repository.AccountMatcher.java Source code

Java tutorial

Introduction

Here is the source code for com.garyclayburg.persistence.repository.AccountMatcher.java

Source

/*
 * VisualSync - a tool to visualize user data synchronization
 * Copyright (c) 2015 Gary Clayburg
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package com.garyclayburg.persistence.repository;

import com.garyclayburg.attributes.AttributeService;
import com.garyclayburg.persistence.domain.QUser;
import com.garyclayburg.persistence.domain.User;
import com.garyclayburg.persistence.domain.UserAccount;
import com.google.common.collect.Iterables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * Date: 2/5/15
 * Time: 4:26 PM
 *
 * @author Gary Clayburg
 */
@Controller
//@RequestMapping("/matchusers")
public class AccountMatcher {

    @Autowired
    @SuppressWarnings("SpringJavaAutowiredMembersInspection")
    private AttributeService attributeService;

    @Qualifier("auditedUserRepo")
    @Autowired
    @SuppressWarnings("SpringJavaAutowiredMembersInspection")
    private UserStore auditedUserRepo;

    @SuppressWarnings("UnusedDeclaration")
    private static final Logger log = LoggerFactory.getLogger(AccountMatcher.class);
    @Autowired
    @SuppressWarnings({ "SpringJavaAutowiringInspection", "SpringJavaAutowiredMembersInspection" })
    // IntelliJ confused by spring-boot wiring
    protected AutoUserRepo autoUserRepo;

    public User attachAccount(UserAccount scimAccount) {
        User matchedUser = matchAccount(scimAccount);
        User savedUser = null;
        if (matchedUser != null) {
            List<UserAccount> userAccounts = matchedUser.getUserAccounts();

            if (userAccounts != null) {
                ListIterator<UserAccount> listIterator = userAccounts.listIterator();
                boolean updatedAccount = false;
                while (listIterator.hasNext()) {
                    UserAccount userAccount = listIterator.next();
                    String username = userAccount.getUsername();
                    String accountType = userAccount.getAccountType();
                    if (username != null && accountType != null) {
                        if (username.equals(scimAccount.getUsername())
                                && accountType.equals(scimAccount.getAccountType())) {
                            listIterator.set(scimAccount);
                            updatedAccount = true;
                        }
                    }

                }
                if (!updatedAccount) { //add as new account for this matched user
                    userAccounts.add(scimAccount);
                }
            } else { //user does not have any accounts yet.  This will be his first.
                List<UserAccount> newAccounts = new ArrayList<>();
                newAccounts.add(scimAccount);
                matchedUser.setUserAccounts(newAccounts);
            }
            savedUser = auditedUserRepo.save(matchedUser);
        }
        return savedUser;
    }

    public User matchAccount(UserAccount scimAccount) {
        QUser qUser = new QUser("user");

        User matchedUser = null;
        //default policy matches accounts based on username
        String instanceName = scimAccount.getInstanceName();
        Iterable<User> userList;
        if (scimAccount.getInstanceName() == null) {
            // find users that already have a useraccount with specific instancename
            userList = autoUserRepo.findAll(qUser.userAccounts.any().username.eq(scimAccount.getUsername())
                    .and(qUser.userAccounts.any().accountType.eq(scimAccount.getAccountType()))
                    .and(qUser.userAccounts.any().instanceName.isNull()));
        } else {
            // find users that alredy have a useraccount without a specific instancename
            userList = autoUserRepo.findAll(qUser.userAccounts.any().username.eq(scimAccount.getUsername())
                    .and(qUser.userAccounts.any().accountType.eq(scimAccount.getAccountType()))
                    .and(qUser.userAccounts.any().instanceName.eq(instanceName)));
        }
        int matchListSize = Iterables.size(userList);
        if (matchListSize == 1) {
            matchedUser = Iterables.getFirst(userList, null);
            // this scimAccount was matched previously to the stored user
        } else if (matchListSize > 1) {
            log.error("ERR-102 more than one possible account match for username: " + scimAccount.getUsername());
        } else {
            // execute groovy identity policy on everyone to find match
            //todo use closure here to pass in groovy policy for creating username as part of user query?
            List<User> allUsers = autoUserRepo.findAll(); //todo find a more efficient method for this?
            int matches = 0;
            for (User oneUser : allUsers) {
                Map<String, String> generatedAttributes = attributeService.getGeneratedAttributes(oneUser);

                //convention: attributes named username are used for matching during a recon/sync
                String username = generatedAttributes.get("username");
                log.debug("checking username: {} {} {}", username, oneUser.getFirstname(), oneUser.getLastname());
                if (username != null && username.equals(scimAccount.getUsername())) {
                    matches++;
                    if (matchedUser == null) {
                        matchedUser = oneUser; //go with first match
                    }
                }
            }
            log.info("found {} users matching username attribute policy for user {} ", matches,
                    scimAccount.getUsername());
        }
        return matchedUser;
    }

    public void setAttributeService(AttributeService attributeService) {
        this.attributeService = attributeService;
    }
}