package cz.muni.fi.rtc.teacherWorkbench.importer;

import java.util.Collection;
import java.util.Random;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.springframework.security.providers.encoding.PasswordEncoder;
import org.springframework.security.providers.ldap.authenticator.LdapShaPasswordEncoder;

import com.ibm.team.repository.client.IContributorManager;
import com.ibm.team.repository.client.ITeamRepository;
import com.ibm.team.repository.client.internal.TeamRepository;
import com.ibm.team.repository.common.IContributor;
import com.ibm.team.repository.common.IDefaultLicenseProviderService;
import com.ibm.team.repository.common.ILicenseAdminService;
import com.ibm.team.repository.common.TeamRepositoryException;
import com.novell.ldap.LDAPAttribute;
import com.novell.ldap.LDAPAttributeSet;
import com.novell.ldap.LDAPConnection;
import com.novell.ldap.LDAPEntry;
import com.novell.ldap.LDAPException;
import com.novell.ldap.LDAPModification;

import cz.muni.fi.rtc.teacherWorkbench.importer.exceptions.ConfigurationException;
import cz.muni.fi.rtc.teacherWorkbench.importer.exceptions.ImporterException;
import cz.muni.fi.rtc.teacherWorkbench.model.ImportedPerson;

/**
 * Class for importing people into LDAP and RTC
 * @author Jan Stastny
 */
public class PeopleImporter {

	private ImporterConfiguration configuration;

	/**
	 * Connection established by getLdapConnection called by init()
	 */
	private LDAPConnection connection = null;

	/**
	 * Connection established by getRepositoryConnection called by init()
	 */
	private ITeamRepository repo = null;
	
	private Log log = LogFactory
			.getLog(cz.muni.fi.rtc.teacherWorkbench.importer.PeopleImporter.class);
	
	private IProgressMonitor monitor = LogProgressMonitor.getInstance();

	/**
	 * Constructs new Importer using the configuration passed as argument
	 * 
	 * @param conf
	 *            Configuration of the importer
	 * @throws ImporterException If the configuration values are not correct or connection to some services fails
	 */
	public PeopleImporter(ImporterConfiguration conf) throws ImporterException {
		this.configuration = conf;
		init();
	}
	
	/**
	 * Initialize the instance
	 * @throws ImporterException rethrown from called methods.
	 */
	private void init() throws ImporterException {
		this.connection = Utils.establishLdapConnection(configuration);
		this.repo = Utils.establishRepositoryConnection(configuration);
	}
	
	
	/**
	 * Inserts the users to the LDAP database and creates their account in RTC
	 * assigning them default licence. LDAP exceptions are not thrown but logger
	 * as ERROR instead.
	 * 
* Mandatory configuration fields: ldapGroupPeople, ldapGroupJazzUsers *
* Mandatory user fields: * * * @param users * @throws ImporterException * Thrown when: - Class not configured correctly - Mandatory * fields of some users are not filled (checked before writting * to LDAP -- atomic fail) */ public void importUsers(Collection users) throws ImporterException { if (configuration.getLdapGroupPeople() == null) { throw new ConfigurationException("ldapGroupPeople not configured"); } if (configuration.getLdapGroupJazzUsers() == null) { throw new ConfigurationException("LdapGroupJazzUsers not configured"); } for (ImportedPerson person : users) { if (person.getUID() == null || person.getUID().equals("")) { throw new ImporterException("Person " + person + " is missing UID", new IllegalArgumentException(person.toString())); } if (person.getRawPassword() == null || person.getRawPassword().equals("")) { throw new ImporterException("Person " + person + " is missing rawPassword", new IllegalArgumentException(person.toString())); } if (person.getEmailAddress() == null || person.getEmailAddress().equals("")) { throw new ImporterException("Person " + person + " is missing email address", new IllegalArgumentException(person.toString())); } if (person.getFirstName() == null) { throw new ImporterException("Person " + person + " is missing first name", new IllegalArgumentException(person.toString())); } if (person.getLastName() == null || person.getLastName().equals("")) { throw new ImporterException("Person " + person + " is missing last name", new IllegalArgumentException(person.toString())); } if (person.getDescription() == null) { throw new ImporterException("Person " + person + " is missing description", new IllegalArgumentException(person.toString())); } } Random random = new Random(); for (ImportedPerson person : users) { try { // Import into LDAP LDAPAttributeSet attributeSet = new LDAPAttributeSet(); attributeSet.add(new LDAPAttribute("uid", person.getUID())); attributeSet.add(new LDAPAttribute("sn", person.getLastName())); attributeSet.add(new LDAPAttribute("cn", person.getFirstName() + " " + person.getLastName())); PasswordEncoder passEncoder = new LdapShaPasswordEncoder(); byte[] salt = {}; random.nextBytes(salt); String saltedPassword = passEncoder.encodePassword(person .getRawPassword(), salt); attributeSet.add(new LDAPAttribute("userPassword", saltedPassword)); attributeSet.add(new LDAPAttribute("description", person .getDescription())); attributeSet.add(new LDAPAttribute("mail", person .getEmailAddress())); attributeSet.add(new LDAPAttribute("objectClass", "inetOrgPerson")); String dn = "uid=" + person.getUID() + "," + configuration.getLdapGroupPeople(); connection.add(new LDAPEntry(dn, attributeSet)); LDAPModification mod = new LDAPModification( LDAPModification.ADD, new LDAPAttribute("member", dn)); connection.modify( configuration.getLdapGroupJazzUsers(), mod); log.info("Created LDAP user " + person.getUID()); // Import into RTC IContributorManager conManager = repo.contributorManager(); IContributor contributor = (IContributor) IContributor.ITEM_TYPE.createItem(); contributor.setUserId(person.getUID()); contributor.setName(person.getFirstName() + " " + person.getLastName()); contributor.setEmailAddress(person.getEmailAddress()); IContributor newContributor = conManager.saveContributor(contributor, monitor); // assign license to the newly created contributor assignDefaultLicense(newContributor, getDefaultLicenseId()); log.info("Created RTC user " + person.getUID()); } catch (LDAPException e) { log.error("Error executing LDAP", e); } catch (TeamRepositoryException e) { log.error("Error adding user to RTC", e); } } } private void assignDefaultLicense(IContributor contributor, String licenseId) { if (licenseId == null) { // default license id not specified. log.error("Licence id is null"); return; } try { ILicenseAdminService adminService = (ILicenseAdminService) ((TeamRepository)repo).getServiceInterface(ILicenseAdminService.class); adminService.assignLicense(contributor, licenseId); } catch (TeamRepositoryException e) { //logErrorAssigningLicense(contributor, licenseId, e); log.error("Failed assigning licence to contributor "+contributor, e); } } private String getDefaultLicenseId() { try { IDefaultLicenseProviderService defaultLicenseProviderService = (IDefaultLicenseProviderService) ((TeamRepository)repo).getServiceInterface(IDefaultLicenseProviderService.class); String licenseId = defaultLicenseProviderService.getDefaultLicenseId(); return licenseId; } catch (Exception e) { // log error log.error("Error fetching default licence", e); return null; } } }