/** * Licensed to The Apereo Foundation under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * * The Apereo Foundation licenses this file to you under the Educational * Community 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://opensource.org/licenses/ecl2.txt * * 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. * */ package org.opencastproject.dataloader; import static org.opencastproject.security.api.DefaultOrganization.DEFAULT_ORGANIZATION_ID; import org.opencastproject.kernel.security.OrganizationDirectoryServiceImpl; import org.opencastproject.metadata.dublincore.DublinCore; import org.opencastproject.metadata.dublincore.DublinCoreCatalog; import org.opencastproject.metadata.dublincore.DublinCores; import org.opencastproject.security.api.AccessControlEntry; import org.opencastproject.security.api.AccessControlList; import org.opencastproject.security.api.DefaultOrganization; import org.opencastproject.security.api.JaxbOrganization; import org.opencastproject.security.api.JaxbRole; import org.opencastproject.security.api.JaxbUser; import org.opencastproject.security.api.Organization; import org.opencastproject.security.api.OrganizationDirectoryService; import org.opencastproject.security.api.Permissions; import org.opencastproject.security.api.SecurityConstants; import org.opencastproject.security.api.SecurityService; import org.opencastproject.security.api.UnauthorizedException; import org.opencastproject.security.impl.jpa.JpaGroup; import org.opencastproject.security.impl.jpa.JpaOrganization; import org.opencastproject.security.impl.jpa.JpaRole; import org.opencastproject.security.impl.jpa.JpaUser; import org.opencastproject.series.api.SeriesException; import org.opencastproject.series.api.SeriesService; import org.opencastproject.userdirectory.JpaGroupRoleProvider; import org.opencastproject.userdirectory.JpaUserAndRoleProvider; import org.opencastproject.util.NotFoundException; import org.apache.commons.lang3.BooleanUtils; import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * A data loader to populate the series and JPA user provider with sample data. */ public class UserAndSeriesLoader { /** The number of series to load */ public static final int NUM_SERIES = 10; /** The number of students per series to load */ public static final int STUDENTS_PER_SERIES = 20; /** The number of instructors per series to load */ public static final int INSTRUCTORS_PER_SERIES = 2; /** The number of admins per series to load */ public static final int ADMINS_PER_SERIES = 1; /** The series prefix */ public static final String SERIES_PREFIX = "SERIES_"; /** The user role */ public static final String USER_ROLE = "ROLE_USER"; /** The instructor role */ public static final String INSTRUCTOR_ROLE = "ROLE_INSTRUCTOR"; /** The course admin role */ public static final String COURSE_ADMIN_ROLE = "ROLE_COURSE_ADMIN"; /** The student role suffix */ public static final String STUDENT_PREFIX = "STUDENT"; /** The instructor role suffix */ public static final String INSTRUCTOR_PREFIX = "INSTRUCTOR"; /** The departmental admin (not the super admin) role suffix */ public static final String ADMIN_PREFIX = "ADMIN"; /** Configuration property to set if to load default users */ public static final String PROP_DEMO_LOAD_USER = "org.opencastproject.security.demo.loadusers"; /** The read permission */ public static final String READ = Permissions.Action.READ.toString(); /** The write permission */ public static final String WRITE = Permissions.Action.WRITE.toString(); /** The contribute permission */ public static final String CONTRIBUTE = Permissions.Action.CONTRIBUTE.toString(); /** The logger */ protected static final Logger logger = LoggerFactory.getLogger(UserAndSeriesLoader.class); /** The series service */ protected SeriesService seriesService = null; /** The JPA-based user provider, which includes an addUser() method */ protected JpaUserAndRoleProvider jpaUserProvider = null; protected JpaGroupRoleProvider jpaGroupRoleProvider = null; /** The security service */ protected SecurityService securityService = null; /** The organization directory */ protected OrganizationDirectoryServiceImpl organizationDirectoryService = null; /** * Callback on component activation. */ protected void activate(ComponentContext cc) { // Load the demo users, if necessary if (BooleanUtils.toBoolean(cc.getBundleContext().getProperty(PROP_DEMO_LOAD_USER))) { // Load 100 series and 1000 users, but don't block activation new Loader().start(); } } protected class Loader extends Thread { @Override public void run() { logger.info("Adding sample series..."); for (int i = 1; i <= NUM_SERIES; i++) { String seriesId = SERIES_PREFIX + i; DublinCoreCatalog dc = DublinCores.mkOpencastEpisode().getCatalog(); AccessControlList acl = new AccessControlList(); // Add read permissions for viewing the series content in engage acl.getEntries().add(new AccessControlEntry(SERIES_PREFIX + i + "_" + STUDENT_PREFIX, READ, true)); acl.getEntries().add(new AccessControlEntry(SERIES_PREFIX + i + "_" + INSTRUCTOR_PREFIX, READ, true)); acl.getEntries().add(new AccessControlEntry(SERIES_PREFIX + i + "_" + ADMIN_PREFIX, READ, true)); // Add contribute permissions for adding recordings to these series acl.getEntries().add(new AccessControlEntry(SERIES_PREFIX + i + "_" + INSTRUCTOR_PREFIX, CONTRIBUTE, true)); acl.getEntries().add(new AccessControlEntry(SERIES_PREFIX + i + "_" + ADMIN_PREFIX, CONTRIBUTE, true)); // Add write permissions for the instructors and admins to make changes to the series themselves acl.getEntries().add(new AccessControlEntry(SERIES_PREFIX + i + "_" + INSTRUCTOR_PREFIX, WRITE, true)); acl.getEntries().add(new AccessControlEntry(SERIES_PREFIX + i + "_" + ADMIN_PREFIX, WRITE, true)); try { dc.set(DublinCore.PROPERTY_IDENTIFIER, seriesId); dc.set(DublinCore.PROPERTY_TITLE, "Series #" + i); dc.set(DublinCore.PROPERTY_CREATOR, "Creator #" + i); dc.set(DublinCore.PROPERTY_CONTRIBUTOR, "Contributor #" + i); Organization org = organizationDirectoryService.getOrganization(DEFAULT_ORGANIZATION_ID); try { JaxbOrganization jaxbOrganization = JaxbOrganization.fromOrganization(org); securityService.setUser(new JaxbUser("userandseriesloader", "demo", jaxbOrganization, new JaxbRole( SecurityConstants.GLOBAL_ADMIN_ROLE, jaxbOrganization))); securityService.setOrganization(org); try { // Test if the serie already exist, it does not overwrite it. if (seriesService.getSeries(seriesId) != null) continue; } catch (NotFoundException e) { // If the series does not exist, we create it. seriesService.updateSeries(dc); seriesService.updateAccessControl(seriesId, acl); } } catch (UnauthorizedException e) { logger.warn(e.getMessage()); } catch (SeriesException e) { logger.warn("Unable to create series {}", dc); } catch (NotFoundException e) { logger.warn("Unable to find series {}", dc); } finally { securityService.setOrganization(null); securityService.setUser(null); } logger.debug("Added series {}", dc); } catch (NotFoundException e) { logger.warn("Unable to find organization {}", e.getMessage()); } } load(STUDENT_PREFIX, 20, new String[] { USER_ROLE }, DEFAULT_ORGANIZATION_ID); load(INSTRUCTOR_PREFIX, 2, new String[] { USER_ROLE, INSTRUCTOR_ROLE }, DEFAULT_ORGANIZATION_ID); load(ADMIN_PREFIX, 1, new String[] { USER_ROLE, COURSE_ADMIN_ROLE }, DEFAULT_ORGANIZATION_ID); loadLdapUser(DEFAULT_ORGANIZATION_ID); logger.info("Finished loading sample series and users"); loadGroup("admin", DEFAULT_ORGANIZATION_ID, "Admins", "Admin group", new String[] { COURSE_ADMIN_ROLE, INSTRUCTOR_ROLE, INSTRUCTOR_ROLE }, new String[] { "admin1", "admin2", "admin3", "admin4" }); loadGroup("instructor", DEFAULT_ORGANIZATION_ID, "Instructors", "Instructors group", new String[] { USER_ROLE, INSTRUCTOR_ROLE }, new String[] { "instructor1", "instructor2", "instructor3", "instructor4" }); loadGroup("student", DEFAULT_ORGANIZATION_ID, "Students", "Students group", new String[] { USER_ROLE }, new String[] { "student1", "student2", "student3", "student4" }); logger.info("Finished loading sample groups"); } } /** * Loads demo users into persistence. * * @param rolePrefix * the role prefix * @param numPerSeries * the number of users to load per series * @param additionalRoles * any additional roles to add for each user * @param orgId * the organization id */ protected void load(String rolePrefix, int numPerSeries, String[] additionalRoles, String orgId) { String lowerCasePrefix = rolePrefix.toLowerCase(); int totalUsers = numPerSeries * NUM_SERIES; logger.info("Adding sample {}s, usernames and passwords are {}1/{}1... {}{}/{}{}", new Object[] { lowerCasePrefix, lowerCasePrefix, lowerCasePrefix, lowerCasePrefix, totalUsers, lowerCasePrefix, totalUsers }); for (int i = 1; i <= totalUsers; i++) { if (jpaUserProvider.loadUser(lowerCasePrefix + i, orgId) == null) { Set<JpaRole> roleSet = new HashSet<JpaRole>(); for (String additionalRole : additionalRoles) { roleSet.add(new JpaRole(additionalRole, getOrganization(orgId))); } roleSet.add(new JpaRole(SERIES_PREFIX + (((i - 1) % NUM_SERIES) + 1) + "_" + rolePrefix, getOrganization(orgId))); JpaUser user = new JpaUser(lowerCasePrefix + i, lowerCasePrefix + i, getOrganization(orgId), jpaUserProvider.getName(), true, roleSet); try { jpaUserProvider.addUser(user); logger.debug("Added {}", user); } catch (Exception e) { logger.warn("Can not add {}: {}", user, e); } } } } /** * Loads demo group into persistence * * @param groupId * the group id * @param orgId * the organization id * @param name * the group name * @param description * the group description * @param additionalRoles * any additional roles to the group * @param members * the members associated to this group */ protected void loadGroup(String groupId, String orgId, String name, String description, String[] additionalRoles, String[] members) { if (jpaGroupRoleProvider.loadGroup(groupId, orgId) == null) { Set<JpaRole> roles = new HashSet<JpaRole>(); for (String additionalRole : additionalRoles) { roles.add(new JpaRole(additionalRole, getOrganization(orgId))); } JpaGroup group = new JpaGroup(groupId, getOrganization(orgId), name, description, roles, new HashSet<String>( Arrays.asList(members))); try { jpaGroupRoleProvider.addGroup(group); } catch (Exception e) { logger.warn("Can not add {}: {}", group, e); } } } /** * Load a user for testing the ldap provider * * @param organizationId * the organization */ protected void loadLdapUser(String organizationId) { Set<JpaRole> ldapUserRoles = new HashSet<JpaRole>(); ldapUserRoles.add(new JpaRole(USER_ROLE, getOrganization(organizationId))); // This is the public identifier for Josh Holtzman in the UC Berkeley Directory, which is available for anonymous // binding. String ldapUserId = "231693"; if (jpaUserProvider.loadUser(ldapUserId, organizationId) == null) { try { jpaUserProvider.addUser(new JpaUser(ldapUserId, "ldap", getOrganization(organizationId), jpaUserProvider .getName(), true, ldapUserRoles)); logger.debug("Added ldap user '{}' into organization '{}'", ldapUserId, organizationId); } catch (UnauthorizedException ex) { logger.error("Unable to add an administrative user because you have not enough permissions."); } } } /** * Create a new organization from a default organization * * @param orgId * the organization identifier * @return the created organization */ protected JpaOrganization getOrganization(String orgId) { DefaultOrganization org = new DefaultOrganization(); return new JpaOrganization(orgId, org.getName(), org.getServers(), org.getAdminRole(), org.getAnonymousRole(), org.getProperties()); } /** * @param jpaUserProvider * the jpaUserProvider to set */ public void setJpaUserProvider(JpaUserAndRoleProvider jpaUserProvider) { this.jpaUserProvider = jpaUserProvider; } /** * @param jpaGroupRoleProvider * the jpaGroupRoleProvider to set */ public void setJpaGroupRoleProvider(JpaGroupRoleProvider jpaGroupRoleProvider) { this.jpaGroupRoleProvider = jpaGroupRoleProvider; } /** * @param seriesService * the seriesService to set */ public void setSeriesService(SeriesService seriesService) { this.seriesService = seriesService; } /** * @param securityService * the securityService to set */ public void setSecurityService(SecurityService securityService) { this.securityService = securityService; } /** * @param organizationDirectoryService * the organizationDirectoryService to set */ public void setOrganizationDirectoryService(OrganizationDirectoryService organizationDirectoryService) { this.organizationDirectoryService = (OrganizationDirectoryServiceImpl) organizationDirectoryService; } }