public static void assignUserToProject(Long projectID, Long userID) { EntityManager em = getEM(); ProjectUser pu = em.find(ProjectUser.class, userID); em.getTransaction().begin(); pu.setContributor(em.find(Project.class, projectID)); em.getTransaction().commit(); }
/** * Global 리소스에 대해 주어진 리소스의 operation을 허용하는지 여부 * * <p>임시 업로드 파일은 해당 파일을 업로드한 사용자만 접근할 수 있다. 비공개 프로젝트는 해당 프로젝트의 멤버만 접근할 수 있다. 공개 프로젝트는 모든 사용자가 접근할 * 수 있다. 사용자 및 사용자의 아바타는 그 사용자 본인만 갱신 혹은 삭제할 수 있다. 프로젝트는 그 프로젝트의 관리자만이 갱신 혹은 삭제할 수 있다. * * @param user * @param resource * @param operation * @return */ private static boolean isGlobalResourceAllowed( User user, Resource resource, Operation operation) { // Temporary attachments are allowed only for the user who uploads them. if (resource.getType() == ResourceType.ATTACHMENT && resource.getContainer().getType() == ResourceType.USER) { return user.id.equals(resource.getContainer().getId()); } if (operation == Operation.READ) { if (resource.getType() == ResourceType.PROJECT) { Project project = Project.find.byId(resource.getId()); return project != null && (project.isPublic || ProjectUser.isMember(user.id, project.id)); } // anyone can read any resource which is not a project. return true; } // UPDATE, DELETE switch (resource.getType()) { case USER: case USER_AVATAR: return user.id.equals(resource.getId()); case PROJECT: return ProjectUser.isManager(user.id, resource.getId()); default: // undefined return false; } }
@Test public void roleOf() { // GIVEN String loginId = "yobi"; Project project = Project.findByOwnerAndProjectName(loginId, "projectYobi"); // WHEN String roleName = ProjectUser.roleOf(loginId, project); // THEN assertThat(roleName).isEqualTo("manager"); // WHEN roleName = ProjectUser.roleOf("admin", project); // THEN assertThat(roleName).isEqualTo("sitemanager"); // WHEN roleName = ProjectUser.roleOf((String) null, project); // THEN assertThat(roleName).isEqualTo("anonymous"); // WHEN roleName = ProjectUser.roleOf("keesun", project); // THEN assertThat(roleName).isEqualTo("anonymous"); // WHEN roleName = ProjectUser.roleOf("laziel", project); // THEN assertThat(roleName).isEqualTo("member"); }
@Test public void isMember() throws Exception { // Given // When // Then assertThat(ProjectUser.isMember(2l, 2l)).isEqualTo(true); assertThat(ProjectUser.isMember(2l, 3l)).isEqualTo(false); }
@Test public void create() throws Exception { // Given // When ProjectUser.create(2l, 3l, 2l); // Then assertThat(ProjectUser.findByIds(2l, 3l).role.id).isEqualTo(2l); }
@Test public void assignRole() throws Exception { // Given // When ProjectUser.assignRole(2l, 1l, 2l); ProjectUser.assignRole(2l, 3l, 2l); flush(); // Then assertThat(ProjectUser.findByIds(2l, 1l).role.id).isEqualTo(2l); assertThat(ProjectUser.findByIds(2l, 3l).role.id).isEqualTo(2l); }
/** * {@code user}가 프로젝트 리소스인 {@code resource}에 {@code operation}을 하는 것이 허용되는지의 여부를 반환한다. * * <p>See docs/technical/access-control.md for more information. * * @param user * @param project * @param resource * @param operation * @return */ private static boolean isProjectResourceAllowed( User user, Project project, Resource resource, Operation operation) { if (ProjectUser.isManager(user.id, project.id)) { return true; } // If the resource is an attachment, the permission depends on its container. if (resource.getType() == ResourceType.ATTACHMENT) { switch (operation) { case READ: return isAllowed(user, resource.getContainer(), Operation.READ); case UPDATE: case DELETE: return isAllowed(user, resource.getContainer(), Operation.UPDATE); } } // Access Control for members, nonmembers and anonymous. // - Anyone can read public project's resource. // - Members can update anything and delete anything except code repository. // - Nonmember can update or delete a resource if only // * the user is the author of the resource, // * the resource is not a code repository, // * and the project to which the resource belongs is public. // See docs/technical/access-control.md for more information. switch (operation) { case READ: return project.isPublic || ProjectUser.isMember(user.id, project.id); case UPDATE: if (ProjectUser.isMember(user.id, project.id)) { return true; } if (resource.getType() == ResourceType.CODE) { // Nonmember cannot update the repository. return false; } else { return project.isPublic && isEditableAsAuthor(user, project, resource); } case DELETE: if (resource.getType() == ResourceType.CODE) { return false; } else { return ProjectUser.isMember(user.id, project.id) || (project.isPublic && isEditableAsAuthor(user, project, resource)); } default: // undefined return false; } }
@Test public void isManager() throws Exception { // Given ProjectUser.assignRole(2l, 3l, 1l); flush(); // When Long userIdCase1 = 2l; Long userIdCase2 = 5l; // Then assertThat(ProjectUser.checkOneMangerPerOneProject(userIdCase1, 3l)).isEqualTo(true); assertThat(ProjectUser.checkOneMangerPerOneProject(userIdCase2, 3l)).isEqualTo(false); }
@Test public void isGuest() { // Given Project project = getTestProject(1L); User anonymous = User.anonymous; User member = getTestUser(3L); User guest = getTestUser(4L); // When // Then assertThat(ProjectUser.isGuest(project, anonymous)).isFalse(); assertThat(ProjectUser.isGuest(project, member)).isFalse(); assertThat(ProjectUser.isGuest(project, guest)).isTrue(); }
@Test public void isAllowedToSettings() { // GIVEN String loginId = "yobi"; Project project = Project.findByOwnerAndProjectName(loginId, "projectYobi"); // WHEN // THEN assertThat(ProjectUser.isAllowedToSettings(loginId, project)).isTrue(); // WHEN // THEN assertThat(ProjectUser.isAllowedToSettings("admin", project)).isTrue(); // WHEN // THEN assertThat(ProjectUser.isAllowedToSettings(null, project)).isFalse(); // WHEN // THEN assertThat(ProjectUser.isAllowedToSettings("keesun", project)).isFalse(); }
@Test public void options() throws Exception { // Given // When // Then assertThat(ProjectUser.options(1l).containsValue("laziel")).isEqualTo(true); }
/** * user가 해당 project에서 주어진 resourceType의 resource를 생성할 수 있는 여부를 반환한다. * * <p>자신이 프로젝트 멤버일 경우에는 프로젝트에 속하는 모든 리소스에 대한 생성권한을 갖고 로그인 유저일 경우에는 이슈와 게시물에 한해서만 생성할 수 있다. * * @param user * @param project * @param resourceType * @return user가 해당 project에서 주어진 resourceType의 resource를 생성할 수 있는지 여부 */ public static boolean isProjectResourceCreatable( User user, Project project, ResourceType resourceType) { if (user == null) return false; if (user.isSiteManager()) { return true; } if (ProjectUser.isMember(user.id, project.id)) { // Project members can create anything. return true; } else { // If the project is private, nonmembers cannot create anything. if (!project.isPublic) { return false; } // If the project is public, login users can create issues and posts. if (!user.isAnonymous()) { switch (resourceType) { case ISSUE_POST: case BOARD_POST: case ISSUE_COMMENT: case NONISSUE_COMMENT: case FORK: return true; default: return false; } } return false; } }
@Test public void findByIds() throws Exception { // Given // When Role role = ProjectUser.findByIds(2l, 1l).role; // Then assertThat(role.id).isEqualTo(1l); }
/** * 사용자를 삭제한다. * * <p>when 관리자 페이지 사용자 삭제시 * * @param userId the user id * @return the result * @see {@link Project#isOnlyManager(Long)} */ @Transactional public static Result deleteUser(Long userId) { if (User.findByLoginId(session().get("loginId")).isSiteManager()) { if (Project.isOnlyManager(userId)) { flash(Constants.WARNING, "site.userList.deleteAlert"); } else { User user = User.find.byId(userId); for (ProjectUser projectUser : user.projectUser) { projectUser.delete(); } user.changeState(UserState.DELETED); } } else { flash(Constants.WARNING, "error.auth.unauthorized.waringMessage"); } return redirect(routes.SiteApp.userList(1, null)); }
@Test public void findMemberListByProject() throws Exception { // Given // When List<ProjectUser> projectUsers = ProjectUser.findMemberListByProject(1l); // Then assertThat(projectUsers.size()).isEqualTo(2); assertThat(projectUsers.get(0).user.id).isEqualTo(2l); assertThat(projectUsers.get(0).user.loginId).isEqualTo("yobi"); assertThat(projectUsers.get(0).role.name).isEqualTo("manager"); }
/** * 대량의 메일목록을 JSON으로 반환한다. * * <p>when 사이트 관리자페이지의 대량 메일 발송시 사용 * * <p>{@code currentUser} 가 사이트관리자가 아니면 경고메세지와 함께 fobidden을 반환한다. 요청 content-type이 * application/json이 아니면 {@link Http.Status#NOT_ACCEPTABLE} 을 반환한다. {@code projects}가 null 이면 비어있는 * json객체를 반환한다. 모두에게 보내기 요청시에는 모든 사용자 목록을 json으로 반환한다. 대상이 특정 프로젝트 멤버일시에는 해당 프로젝트의 멤버를 json으로 * 반환한다. * * @return the result */ public static Result mailList() { Set<String> emails = new HashSet<>(); Map<String, String[]> projects = request().body().asFormUrlEncoded(); if (!UserApp.currentUser().isSiteManager()) { return forbidden(ErrorViews.Forbidden.render("error.auth.unauthorized.waringMessage")); } if (!request().accepts("application/json")) { return status(Http.Status.NOT_ACCEPTABLE); } if (projects == null) { return ok(toJson(new HashSet<String>())); } if (projects.containsKey("all")) { if (projects.get("all")[0].equals("true")) { for (User user : User.find.findList()) { emails.add(user.email); } } } else { for (String[] projectNames : projects.values()) { String projectName = projectNames[0]; String[] parts = projectName.split("/"); String owner = parts[0]; String name = parts[1]; Project project = Project.findByOwnerAndProjectName(owner, name); for (ProjectUser projectUser : ProjectUser.findMemberListByProject(project.id)) { Logger.debug(projectUser.user.email); emails.add(projectUser.user.email); } } } return ok(toJson(emails)); }