public void updateProjectPermission( Project project, String name, Permission perm, boolean group, User modifier) throws ProjectManagerException { logger.info( "User " + modifier.getUserId() + " updating permissions for project " + project.getName() + " for " + name + " " + perm.toString()); projectLoader.updatePermission(project, name, perm, group); if (group) { projectLoader.postEvent( project, EventType.GROUP_PERMISSION, modifier.getUserId(), "Permission for group " + name + " set to " + perm.toString()); } else { projectLoader.postEvent( project, EventType.USER_PERMISSION, modifier.getUserId(), "Permission for user " + name + " set to " + perm.toString()); } }
public void updateProjectDescription(Project project, String description, User modifier) throws ProjectManagerException { projectLoader.updateDescription(project, description, modifier.getUserId()); projectLoader.postEvent( project, EventType.DESCRIPTION, modifier.getUserId(), "Description changed to " + description); }
public synchronized Project removeProject(Project project, User deleter) throws ProjectManagerException { projectLoader.removeProject(project, deleter.getUserId()); projectLoader.postEvent(project, EventType.DELETED, deleter.getUserId(), null); projectsByName.remove(project.getName()); projectsById.remove(project.getId()); return project; }
public boolean hasPermission(User user, Type type) { Permission perm = userPermissionMap.get(user.getUserId()); if (perm != null && (perm.isPermissionSet(Type.ADMIN) || perm.isPermissionSet(type))) { return true; } return hasGroupPermission(user, type); }
public void removeProjectProxyUser(Project project, String proxyName, User modifier) throws ProjectManagerException { logger.info( "User " + modifier.getUserId() + " removing proxy user " + proxyName + " from project " + project.getName()); project.removeProxyUser(proxyName); projectLoader.postEvent( project, EventType.PROXY_USER, modifier.getUserId(), "Proxy user " + proxyName + " has been removed form the project."); updateProjectSetting(project); }
public void addProjectProxyUser(Project project, String proxyName, User modifier) throws ProjectManagerException { logger.info( "User " + modifier.getUserId() + " adding proxy user " + proxyName + " to project " + project.getName()); project.addProxyUser(proxyName); projectLoader.postEvent( project, EventType.PROXY_USER, modifier.getUserId(), "Proxy user " + proxyName + " is added to project."); updateProjectSetting(project); }
/** * Permanently delete all project files and properties data for all versions of a project and log * event in project_events table * * @param project * @param deleter * @return * @throws ProjectManagerException */ public synchronized Project purgeProject(Project project, User deleter) throws ProjectManagerException { projectLoader.cleanOlderProjectVersion(project.getId(), project.getVersion() + 1); projectLoader.postEvent( project, EventType.PURGE, deleter.getUserId(), String.format("Purged versions before %d", project.getVersion() + 1)); return project; }
public Project createProject(String projectName, String description, User creator) throws ProjectManagerException { if (projectName == null || projectName.trim().isEmpty()) { throw new ProjectManagerException("Project name cannot be empty."); } else if (description == null || description.trim().isEmpty()) { throw new ProjectManagerException("Description cannot be empty."); } else if (creator == null) { throw new ProjectManagerException("Valid creator user must be set."); } else if (!projectName.matches("[a-zA-Z][a-zA-Z_0-9|-]*")) { throw new ProjectManagerException( "Project names must start with a letter, followed by any number of letters, digits, '-' or '_'."); } if (projectsByName.contains(projectName)) { throw new ProjectManagerException("Project already exists."); } logger.info("Trying to create " + projectName + " by user " + creator.getUserId()); Project newProject = projectLoader.createNewProject(projectName, description, creator); projectsByName.put(newProject.getName(), newProject); projectsById.put(newProject.getId(), newProject); if (creatorDefaultPermissions) { // Add permission to project projectLoader.updatePermission( newProject, creator.getUserId(), new Permission(Permission.Type.ADMIN), false); // Add proxy user newProject.getProxyUsers().add(creator.getUserId()); try { updateProjectSetting(newProject); } catch (ProjectManagerException e) { e.printStackTrace(); throw e; } } projectLoader.postEvent(newProject, EventType.CREATED, creator.getUserId(), null); return newProject; }
public boolean hasUserPermission(User user, Type type) { Permission perm = userPermissionMap.get(user.getUserId()); if (perm == null) { // Check group return false; } if (perm.isPermissionSet(Type.ADMIN) || perm.isPermissionSet(type)) { return true; } return false; }
public void removeProjectPermission(Project project, String name, boolean group, User modifier) throws ProjectManagerException { logger.info( "User " + modifier.getUserId() + " removing permissions for project " + project.getName() + " for " + name); projectLoader.removePermission(project, name, group); if (group) { projectLoader.postEvent( project, EventType.GROUP_PERMISSION, modifier.getUserId(), "Permission for group " + name + " removed."); } else { projectLoader.postEvent( project, EventType.USER_PERMISSION, modifier.getUserId(), "Permission for user " + name + " removed."); } }
public Permission getCollectivePermission(User user) { Permission permissions = new Permission(); Permission perm = userPermissionMap.get(user.getUserId()); if (perm != null) { permissions.addPermissions(perm); } for (String group : user.getGroups()) { perm = groupPermissionMap.get(group); if (perm != null) { permissions.addPermissions(perm); } } return permissions; }
public void uploadProject(Project project, File archive, String fileType, User uploader) throws ProjectManagerException { logger.info("Uploading files to " + project.getName()); // Unzip. File file = null; try { if (fileType == null) { throw new ProjectManagerException("Unknown file type for " + archive.getName()); } else if ("zip".equals(fileType)) { file = unzipFile(archive); } else { throw new ProjectManagerException("Unsupported archive type for file " + archive.getName()); } } catch (IOException e) { throw new ProjectManagerException("Error unzipping file.", e); } logger.info("Validating Flow for upload " + archive.getName()); DirectoryFlowLoader loader = new DirectoryFlowLoader(logger); loader.loadProjectFlow(file); if (!loader.getErrors().isEmpty()) { logger.error("Error found in upload to " + project.getName() + ". Cleaning up."); try { FileUtils.deleteDirectory(file); } catch (IOException e) { file.deleteOnExit(); e.printStackTrace(); } StringBuffer errorMessage = new StringBuffer(); errorMessage.append("Error found in upload. Cannot upload.\n"); for (String error : loader.getErrors()) { errorMessage.append(error); errorMessage.append('\n'); } throw new ProjectManagerException(errorMessage.toString()); } Map<String, Props> jobProps = loader.getJobProps(); List<Props> propProps = loader.getProps(); synchronized (project) { int newVersion = projectLoader.getLatestProjectVersion(project) + 1; Map<String, Flow> flows = loader.getFlowMap(); for (Flow flow : flows.values()) { flow.setProjectId(project.getId()); flow.setVersion(newVersion); } logger.info("Uploading file to db " + archive.getName()); projectLoader.uploadProjectFile( project, newVersion, fileType, archive.getName(), archive, uploader.getUserId()); logger.info("Uploading flow to db " + archive.getName()); projectLoader.uploadFlows(project, newVersion, flows.values()); logger.info("Changing project versions " + archive.getName()); projectLoader.changeProjectVersion(project, newVersion, uploader.getUserId()); project.setFlows(flows); logger.info("Uploading Job properties"); projectLoader.uploadProjectProperties(project, new ArrayList<Props>(jobProps.values())); logger.info("Uploading Props properties"); projectLoader.uploadProjectProperties(project, propProps); } logger.info("Uploaded project files. Cleaning up temp files."); projectLoader.postEvent( project, EventType.UPLOADED, uploader.getUserId(), "Uploaded project files zip " + archive.getName()); try { FileUtils.deleteDirectory(file); } catch (IOException e) { file.deleteOnExit(); e.printStackTrace(); } logger.info( "Cleaning up old install files older than " + (project.getVersion() - projectVersionRetention)); projectLoader.cleanOlderProjectVersion( project.getId(), project.getVersion() - projectVersionRetention); }
public Permission getUserPermission(User user) { return userPermissionMap.get(user.getUserId()); }
public Map<String, ValidationReport> uploadProject( Project project, File archive, String fileType, User uploader, Props additionalProps) throws ProjectManagerException { logger.info("Uploading files to " + project.getName()); // Unzip. File file = null; try { if (fileType == null) { throw new ProjectManagerException("Unknown file type for " + archive.getName()); } else if ("zip".equals(fileType)) { file = unzipFile(archive); } else { throw new ProjectManagerException("Unsupported archive type for file " + archive.getName()); } } catch (IOException e) { throw new ProjectManagerException("Error unzipping file.", e); } // Since props is an instance variable of ProjectManager, and each // invocation to the uploadProject manager needs to pass a different // value for the PROJECT_ARCHIVE_FILE_PATH key, it is necessary to // create a new instance of Props to make sure these different values // are isolated from each other. Props prop = new Props(props); prop.putAll(additionalProps); prop.put(ValidatorConfigs.PROJECT_ARCHIVE_FILE_PATH, archive.getAbsolutePath()); // Basically, we want to make sure that for different invocations to the // uploadProject method, // the validators are using different values for the // PROJECT_ARCHIVE_FILE_PATH configuration key. // In addition, we want to reload the validator objects for each upload, so // that we can change the validator configuration files without having to // restart Azkaban web server. If the XmlValidatorManager is an instance // variable, 2 consecutive invocations to the uploadProject // method might cause the second one to overwrite the // PROJECT_ARCHIVE_FILE_PATH configuration parameter // of the first, thus causing a wrong archive file path to be passed to the // validators. Creating a separate XmlValidatorManager object for each // upload will prevent this issue without having to add // synchronization between uploads. Since we're already reloading the XML // config file and creating validator objects for each upload, this does // not add too much additional overhead. ValidatorManager validatorManager = new XmlValidatorManager(prop); logger.info( "Validating project " + archive.getName() + " using the registered validators " + validatorManager.getValidatorsInfo().toString()); Map<String, ValidationReport> reports = validatorManager.validate(project, file); ValidationStatus status = ValidationStatus.PASS; for (Entry<String, ValidationReport> report : reports.entrySet()) { if (report.getValue().getStatus().compareTo(status) > 0) { status = report.getValue().getStatus(); } } if (status == ValidationStatus.ERROR) { logger.error("Error found in upload to " + project.getName() + ". Cleaning up."); try { FileUtils.deleteDirectory(file); } catch (IOException e) { file.deleteOnExit(); e.printStackTrace(); } return reports; } DirectoryFlowLoader loader = (DirectoryFlowLoader) validatorManager.getDefaultValidator(); Map<String, Props> jobProps = loader.getJobProps(); List<Props> propProps = loader.getProps(); synchronized (project) { int newVersion = projectLoader.getLatestProjectVersion(project) + 1; Map<String, Flow> flows = loader.getFlowMap(); for (Flow flow : flows.values()) { flow.setProjectId(project.getId()); flow.setVersion(newVersion); } logger.info("Uploading file to db " + archive.getName()); projectLoader.uploadProjectFile( project, newVersion, fileType, archive.getName(), archive, uploader.getUserId()); logger.info("Uploading flow to db " + archive.getName()); projectLoader.uploadFlows(project, newVersion, flows.values()); logger.info("Changing project versions " + archive.getName()); projectLoader.changeProjectVersion(project, newVersion, uploader.getUserId()); project.setFlows(flows); logger.info("Uploading Job properties"); projectLoader.uploadProjectProperties(project, new ArrayList<Props>(jobProps.values())); logger.info("Uploading Props properties"); projectLoader.uploadProjectProperties(project, propProps); } logger.info("Uploaded project files. Cleaning up temp files."); projectLoader.postEvent( project, EventType.UPLOADED, uploader.getUserId(), "Uploaded project files zip " + archive.getName()); try { FileUtils.deleteDirectory(file); } catch (IOException e) { file.deleteOnExit(); e.printStackTrace(); } logger.info( "Cleaning up old install files older than " + (project.getVersion() - projectVersionRetention)); projectLoader.cleanOlderProjectVersion( project.getId(), project.getVersion() - projectVersionRetention); return reports; }
private synchronized Project createNewProject( Connection connection, String name, String description, User creator) throws ProjectManagerException { QueryRunner runner = new QueryRunner(); ProjectResultHandler handler = new ProjectResultHandler(); // See if it exists first. try { List<Project> project = runner.query( connection, ProjectResultHandler.SELECT_ACTIVE_PROJECT_BY_NAME, handler, name); if (!project.isEmpty()) { throw new ProjectManagerException( "Active project with name " + name + " already exists in db."); } } catch (SQLException e) { logger.error(e); throw new ProjectManagerException("Checking for existing project failed. " + name, e); } final String INSERT_PROJECT = "INSERT INTO projects ( name, active, modified_time, create_time, version, last_modified_by, description, enc_type, settings_blob) values (?,?,?,?,?,?,?,?,?)"; // Insert project try { long time = System.currentTimeMillis(); int i = runner.update( connection, INSERT_PROJECT, name, true, time, time, null, creator.getUserId(), description, defaultEncodingType.getNumVal(), null); if (i == 0) { throw new ProjectManagerException("No projects have been inserted."); } connection.commit(); } catch (SQLException e) { logger.error(INSERT_PROJECT + " failed."); try { connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } throw new ProjectManagerException("Insert project for existing project failed. " + name, e); } // Do another query to grab and return the project. Project project = null; try { List<Project> projects = runner.query( connection, ProjectResultHandler.SELECT_ACTIVE_PROJECT_BY_NAME, handler, name); if (projects.isEmpty()) { throw new ProjectManagerException("No active project with name " + name + " exists in db."); } else if (projects.size() > 1) { throw new ProjectManagerException("More than one active project " + name); } project = projects.get(0); } catch (SQLException e) { logger.error(e); throw new ProjectManagerException("Checking for existing project failed. " + name, e); } return project; }