project member invite/edit/remove

This commit is contained in:
Jake Potrebic 2020-08-10 19:35:17 -07:00
parent 0470c0bafa
commit 6608bb8339
No known key found for this signature in database
GPG Key ID: 7C58557EC9C421F8
8 changed files with 85 additions and 14 deletions

View File

@ -2,14 +2,14 @@
function updateIndices() {
var memberList = $('.list-members');
memberList.find('.user-new').each(function(i) {
$(this).find('input').attr('name', 'users[' + i + ']');
$(this).find('select').attr('name', 'roles[' + i + ']');
memberList.find('.user-new').each(function() {
$(this).find('input').attr('name', 'users');
$(this).find('select').attr('name', 'roles');
});
memberList.find('.user-changed').each(function(i) {
$(this).find('input').attr('name', 'userUps[' + i + ']');
$(this).find('select').attr('name', 'roleUps[' + i + ']');
$(this).find('input').attr('name', 'userUps');
$(this).find('select').attr('name', 'roleUps');
});
}

View File

@ -12,14 +12,16 @@ import me.minidigger.hangar.model.Category;
import me.minidigger.hangar.model.FlagReason;
import me.minidigger.hangar.model.NamedPermission;
import me.minidigger.hangar.model.Permission;
import me.minidigger.hangar.model.Role;
import me.minidigger.hangar.model.Visibility;
import me.minidigger.hangar.model.generated.Note;
import me.minidigger.hangar.model.viewhelpers.ProjectData;
import me.minidigger.hangar.model.viewhelpers.ProjectPage;
import me.minidigger.hangar.model.viewhelpers.ScopedProjectData;
import me.minidigger.hangar.model.viewhelpers.UserData;
import me.minidigger.hangar.security.annotations.GlobalPermission;
import me.minidigger.hangar.security.annotations.ProjectPermission;
import me.minidigger.hangar.service.OrgService;
import me.minidigger.hangar.service.RoleService;
import me.minidigger.hangar.service.UserActionLogService;
import me.minidigger.hangar.service.UserService;
import me.minidigger.hangar.service.pluginupload.ProjectFiles;
@ -64,8 +66,10 @@ import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Controller
public class ProjectsController extends HangarController {
@ -80,6 +84,7 @@ public class ProjectsController extends HangarController {
private final ProjectService projectService;
private final ProjectFactory projectFactory;
private final PagesSerivce pagesSerivce;
private final RoleService roleService;
private final UserActionLogService userActionLogService;
private final ProjectFiles projectFiles;
private final TemplateHelper templateHelper;
@ -89,7 +94,7 @@ public class ProjectsController extends HangarController {
private final HttpServletRequest request;
@Autowired
public ProjectsController(HangarConfig hangarConfig, RouteHelper routeHelper, UserService userService, OrgService orgService, FlagService flagService, ProjectService projectService, ProjectFactory projectFactory, PagesSerivce pagesSerivce, UserActionLogService userActionLogService, ProjectFiles projectFiles, TemplateHelper templateHelper, HangarDao<UserDao> userDao, HangarDao<ProjectDao> projectDao, HttpServletRequest request) {
public ProjectsController(HangarConfig hangarConfig, RouteHelper routeHelper, UserService userService, OrgService orgService, FlagService flagService, ProjectService projectService, ProjectFactory projectFactory, PagesSerivce pagesSerivce, RoleService roleService, UserActionLogService userActionLogService, ProjectFiles projectFiles, TemplateHelper templateHelper, HangarDao<UserDao> userDao, HangarDao<ProjectDao> projectDao, HttpServletRequest request) {
this.hangarConfig = hangarConfig;
this.routeHelper = routeHelper;
this.userService = userService;
@ -98,6 +103,7 @@ public class ProjectsController extends HangarController {
this.projectService = projectService;
this.projectFactory = projectFactory;
this.pagesSerivce = pagesSerivce;
this.roleService = roleService;
this.userActionLogService = userActionLogService;
this.projectFiles = projectFiles;
this.templateHelper = templateHelper;
@ -333,9 +339,20 @@ public class ProjectsController extends HangarController {
}
@Secured("ROLE_USER")
@ProjectPermission(NamedPermission.MANAGE_SUBJECT_MEMBERS)
@RequestMapping("/{author}/{slug}/manage/members/remove")
public Object removeMember(@PathVariable Object author, @PathVariable Object slug) {
return null; // TODO implement removeMember request controller
public ModelAndView removeMember(@PathVariable String author, @PathVariable String slug, @RequestParam String username) {
ProjectData projectData = projectService.getProjectData(author, slug);
UserData user = userService.getUserData(username);
if (user == null) throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
if (roleService.removeMember(projectData.getProject(), user.getUser().getId()) != 0) {
userActionLogService.project(
request,
LoggedActionType.PROJECT_MEMBER_REMOVED.with(ProjectContext.of(projectData.getProject().getId())),
user.getUser().getName() + " is not a member of " + projectData.getNamespace(),
user.getUser().getName() + " is a member of " + projectData.getNamespace());
}
return new ModelAndView("redirect:" + routeHelper.getRouteUrl("projects.showSettings", author, slug));
}
@Secured("ROLE_USER")
@ -373,7 +390,12 @@ public class ProjectsController extends HangarController {
@RequestParam(value = "license-url", required = false) String licenseUrl,
@RequestParam("forum-sync") boolean forumSync,
@RequestParam String description,
@RequestParam("update-icon") boolean updateIcon) {
@RequestParam("update-icon") boolean updateIcon,
@RequestParam(required = false) List<Long> users,
@RequestParam(required = false) List<Role> roles,
@RequestParam(required = false) List<String> userUps,
@RequestParam(required = false) List<Role> roleUps) {
ProjectsTable projectsTable = projectService.getProjectData(author, slug).getProject();
projectsTable.setCategory(category);
Set<String> keywordSet = keywords != null ? Set.of(keywords.split(" ")) : Set.of();
@ -402,8 +424,22 @@ public class ProjectsController extends HangarController {
}
}
// TODO add new roles
// TODO update existing roles
if (users != null && roles != null) {
for (int i = 0; i < users.size(); i++) {
roleService.addRole(projectsTable, users.get(i), roles.get(i), false);
// TODO notifications
}
}
if (userUps != null && roleUps != null) {
Map<String, UsersTable> usersToUpdate = userService.getUsers(userUps).stream().collect(Collectors.toMap(UsersTable::getName, user -> user));
if (usersToUpdate.size() != roleUps.size()) throw new RuntimeException("Mismatching userUps & roleUps size");
for (int i = 0; i < userUps.size(); i++) {
roleService.updateRole(projectsTable, usersToUpdate.get(userUps.get(i)).getId(), roleUps.get(i));
}
}
userActionLogService.project(request, LoggedActionType.PROJECT_SETTINGS_CHANGED.with(ProjectContext.of(projectsTable.getId())), "", "");
return new RedirectView(routeHelper.getRouteUrl("projects.show", author, slug));

View File

@ -13,4 +13,7 @@ public interface ProjectMembersDao {
@SqlUpdate("INSERT INTO project_members VALUES (:projectId, :userId)")
void insert(@BindBean ProjectMembersTable entry);
@SqlUpdate("DELETE FROM project_members WHERE project_id = :projectId AND user_id = :userId")
int delete(long projectId, long userId);
}

View File

@ -4,6 +4,8 @@ import me.minidigger.hangar.model.viewhelpers.FlagActivity;
import me.minidigger.hangar.model.viewhelpers.ReviewActivity;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.customizer.BindBean;
import org.jdbi.v3.sqlobject.customizer.BindList;
import org.jdbi.v3.sqlobject.customizer.BindList.EmptyHandling;
import org.jdbi.v3.sqlobject.customizer.Define;
import org.jdbi.v3.sqlobject.customizer.Timestamped;
import org.jdbi.v3.sqlobject.statement.GetGeneratedKeys;
@ -38,6 +40,9 @@ public interface UserDao {
@SqlQuery("select * from users where LOWER(name) = LOWER(:name)")
UsersTable getByName(String name);
@SqlQuery("SELECT * FROM users WHERE name IN (<userNames>)")
List<UsersTable> getUsers(@BindList(onEmpty = EmptyHandling.NULL_STRING) List<String> userNames);
@SqlQuery("SELECT sq.name," +
" sq.join_date," +
" sq.created_at," +

View File

@ -20,11 +20,17 @@ public interface UserProjectRolesDao {
@SqlQuery("SELECT * FROM user_project_roles WHERE project_id = :projectId AND user_id = :userId")
UserProjectRolesTable getByProjectAndUser(long projectId, long userId);
@Timestamped
@SqlUpdate("INSERT INTO user_project_roles (created_at, user_id, role_type, project_id, is_accepted) " +
"VALUES (:now, :userId, :roleType, :projectId, :isAccepted)")
@Timestamped
void insert(@BindBean UserProjectRolesTable userProjectRolesTable);
@SqlUpdate("UPDATE user_project_roles SET role_type = :roleType, is_accepted = :isAccepted WHERE id = :id")
void update(@BindBean UserProjectRolesTable userProjectRolesTable);
@SqlUpdate("DELETE FROM user_project_roles WHERE project_id = :projectId AND user_id = :userId")
void delete(long projectId, long userId);
@RegisterBeanMapper(ProjectsTable.class)
@RegisterBeanMapper(value = UserProjectRolesTable.class, prefix = "upr")
@SqlQuery("SELECT p.*, upr.id upr_id, upr.created_at upr_created_at, upr.user_id upr_user_id, upr.role_type upr_role_type, upr.project_id upr_project_id, upr.is_accepted upr_is_accepted FROM user_project_roles upr LEFT OUTER JOIN projects p ON upr.project_id = p.id WHERE user_id = :userId AND upr.is_accepted = false ORDER BY upr.created_at")

View File

@ -69,10 +69,26 @@ public class RoleService {
userProjectRolesDao.get().insert(new UserProjectRolesTable(userId, role.getValue(), projectsTable.getId(), isAccepted));
}
public void updateRole(ProjectsTable projectsTable, long userId, Role role) {
UserProjectRolesTable userProjectRole = userProjectRolesDao.get().getByProjectAndUser(projectsTable.getId(), userId);
if (userProjectRole == null) return;
userProjectRole.setRoleType(role.getValue());
userProjectRolesDao.get().update(userProjectRole);
}
public void removeRole(ProjectsTable projectsTable, long userId) {
userProjectRolesDao.get().delete(projectsTable.getId(), userId);
}
public void addMember(long projectId, long userId) {
projectMembersDao.get().insert(new ProjectMembersTable(projectId, userId));
}
public int removeMember(ProjectsTable projectsTable, long userId) {
removeRole(projectsTable, userId);
return projectMembersDao.get().delete(projectsTable.getId(), userId);
}
public void addGlobalRole(long userId, long roleId) {
userGlobalRolesDao.get().insert(new UserGlobalRolesTable(userId, roleId));
}

View File

@ -172,6 +172,10 @@ public class UserService {
return new UserData(getHeaderData(), user, isOrga, projectCount, organizations, globalRoles, userPerm, orgaPerm);
}
public List<UsersTable> getUsers(List<String> userNames) {
return userDao.get().getUsers(userNames);
}
public UsersTable getOrCreate(String username, AuthUser authUser) {
UsersTable user = userDao.get().getByName(username);
if (user == null) {

View File

@ -126,7 +126,8 @@ public class ProjectService {
if (currentUser == null) {
return new ScopedProjectData();
} else {
return projectDao.get().getScopedProjectData(projectId, currentUser.getId());
ScopedProjectData sp = projectDao.get().getScopedProjectData(projectId, currentUser.getId());
return sp == null ? new ScopedProjectData() : sp;
}
}