From c4efbbc67a8dc11cb9a606e19633e3c3b4a6d454 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 3 Sep 2020 22:24:59 -0700
Subject: [PATCH] finished user admin page

---
 .../controller/ApplicationController.java     | 55 ++++++++++---------
 .../hangar/controller/UsersController.java    |  2 +-
 .../model/viewhelpers/JoinableData.java       | 12 +++-
 .../model/viewhelpers/OrganizationData.java   | 10 +++-
 .../hangar/model/viewhelpers/ProjectData.java |  2 +-
 .../hangar/model/viewhelpers/UserData.java    |  9 ++-
 .../io/papermc/hangar/service/OrgService.java | 15 ++++-
 .../papermc/hangar/service/UserService.java   |  9 ++-
 .../templates/users/admin/userAdmin.ftlh      | 14 ++---
 .../resources/templates/users/projects.ftlh   |  6 +-
 10 files changed, 83 insertions(+), 51 deletions(-)

diff --git a/src/main/java/io/papermc/hangar/controller/ApplicationController.java b/src/main/java/io/papermc/hangar/controller/ApplicationController.java
index 1ab816cb8..1d802fdca 100644
--- a/src/main/java/io/papermc/hangar/controller/ApplicationController.java
+++ b/src/main/java/io/papermc/hangar/controller/ApplicationController.java
@@ -1,6 +1,29 @@
 package io.papermc.hangar.controller;
 
+import io.papermc.hangar.db.customtypes.LoggedActionType;
+import io.papermc.hangar.db.customtypes.LoggedActionType.ProjectContext;
 import io.papermc.hangar.db.model.Stats;
+import io.papermc.hangar.model.NamedPermission;
+import io.papermc.hangar.model.Permission;
+import io.papermc.hangar.model.Visibility;
+import io.papermc.hangar.model.viewhelpers.Activity;
+import io.papermc.hangar.model.viewhelpers.LoggedActionViewModel;
+import io.papermc.hangar.model.viewhelpers.OrganizationData;
+import io.papermc.hangar.model.viewhelpers.ProjectFlag;
+import io.papermc.hangar.model.viewhelpers.ReviewQueueEntry;
+import io.papermc.hangar.model.viewhelpers.UnhealthyProject;
+import io.papermc.hangar.model.viewhelpers.UserData;
+import io.papermc.hangar.security.annotations.GlobalPermission;
+import io.papermc.hangar.service.JobService;
+import io.papermc.hangar.service.OrgService;
+import io.papermc.hangar.service.SitemapService;
+import io.papermc.hangar.service.StatsService;
+import io.papermc.hangar.service.UserActionLogService;
+import io.papermc.hangar.service.UserService;
+import io.papermc.hangar.service.VersionService;
+import io.papermc.hangar.service.project.FlagService;
+import io.papermc.hangar.service.project.ProjectService;
+import io.papermc.hangar.util.AlertUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.ClassPathResource;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -12,41 +35,18 @@ import org.springframework.ui.ModelMap;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.server.ResponseStatusException;
 import org.springframework.web.servlet.ModelAndView;
 
+import javax.servlet.http.HttpServletRequest;
 import java.time.LocalDate;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
-import javax.servlet.http.HttpServletRequest;
-
-import io.papermc.hangar.db.customtypes.LoggedActionType;
-import io.papermc.hangar.db.customtypes.LoggedActionType.ProjectContext;
-import io.papermc.hangar.model.NamedPermission;
-import io.papermc.hangar.model.Permission;
-import io.papermc.hangar.model.Visibility;
-import io.papermc.hangar.model.viewhelpers.Activity;
-import io.papermc.hangar.model.viewhelpers.LoggedActionViewModel;
-import io.papermc.hangar.model.viewhelpers.ProjectFlag;
-import io.papermc.hangar.model.viewhelpers.ReviewQueueEntry;
-import io.papermc.hangar.model.viewhelpers.UnhealthyProject;
-import io.papermc.hangar.model.viewhelpers.UserData;
-import io.papermc.hangar.security.annotations.GlobalPermission;
-import io.papermc.hangar.service.JobService;
-import io.papermc.hangar.service.SitemapService;
-import io.papermc.hangar.service.UserActionLogService;
-import io.papermc.hangar.service.UserService;
-import io.papermc.hangar.service.VersionService;
-import io.papermc.hangar.service.StatsService;
-import io.papermc.hangar.service.project.FlagService;
-import io.papermc.hangar.service.project.ProjectService;
-import io.papermc.hangar.util.AlertUtil;
 
 @Controller
 public class ApplicationController extends HangarController {
@@ -54,6 +54,7 @@ public class ApplicationController extends HangarController {
     private final UserService userService;
     private final ProjectService projectService;
     private final FlagService flagService;
+    private final OrgService orgService;
     private final UserActionLogService userActionLogService;
     private final VersionService versionService;
     private final JobService jobService;
@@ -63,9 +64,10 @@ public class ApplicationController extends HangarController {
     private final HttpServletRequest request;
 
     @Autowired
-    public ApplicationController(UserService userService, ProjectService projectService, VersionService versionService, FlagService flagService, UserActionLogService userActionLogService, JobService jobService, SitemapService sitemapService, StatsService statsService, HttpServletRequest request) {
+    public ApplicationController(UserService userService, ProjectService projectService, OrgService orgService, VersionService versionService, FlagService flagService, UserActionLogService userActionLogService, JobService jobService, SitemapService sitemapService, StatsService statsService, HttpServletRequest request) {
         this.userService = userService;
         this.projectService = projectService;
+        this.orgService = orgService;
         this.flagService = flagService;
         this.userActionLogService = userActionLogService;
         this.versionService = versionService;
@@ -218,7 +220,8 @@ public class ApplicationController extends HangarController {
         ModelAndView mav = new ModelAndView("users/admin/userAdmin");
         UserData userData = userService.getUserData(user);
         mav.addObject("u", userData);
-        // TODO organization
+        OrganizationData organizationData = orgService.getOrganizationData(userData.getUser());
+        mav.addObject("orga", organizationData);
         mav.addObject("userProjectRoles", projectService.getProjectsAndRoles(userData.getUser().getId()));
         return fillModel(mav);
     }
diff --git a/src/main/java/io/papermc/hangar/controller/UsersController.java b/src/main/java/io/papermc/hangar/controller/UsersController.java
index 4d6999d05..3353f805a 100644
--- a/src/main/java/io/papermc/hangar/controller/UsersController.java
+++ b/src/main/java/io/papermc/hangar/controller/UsersController.java
@@ -224,7 +224,7 @@ public class UsersController extends HangarController {
         OrganizationsTable organizationsTable = orgService.getOrganization(user);
         mav.addObject("u", userService.getUserData(user));
         if (organizationsTable != null) {
-            mav.addObject("o", orgService.getOrganizationData(organizationsTable));
+            mav.addObject("o", orgService.getOrganizationData(organizationsTable, null));
             mav.addObject("so", orgService.getScopedOrganizationData(organizationsTable));
         }
         return fillModel(mav);
diff --git a/src/main/java/io/papermc/hangar/model/viewhelpers/JoinableData.java b/src/main/java/io/papermc/hangar/model/viewhelpers/JoinableData.java
index 8e9d98fdd..dd4ffe0b6 100644
--- a/src/main/java/io/papermc/hangar/model/viewhelpers/JoinableData.java
+++ b/src/main/java/io/papermc/hangar/model/viewhelpers/JoinableData.java
@@ -13,11 +13,13 @@ public class JoinableData<R extends RoleTable, T> {
 
     protected T joinable;
     protected long ownerId;
+    protected String ownerName;
     protected Map<R, UsersTable> members;
     protected RoleCategory roleCategory;
 
-    public JoinableData(T joinable, long ownerId, Map<R, UsersTable> members, RoleCategory roleCategory) {
+    public JoinableData(T joinable, long ownerId, String ownerName, Map<R, UsersTable> members, RoleCategory roleCategory) {
         this.joinable = joinable;
+        this.ownerName = ownerName;
         this.ownerId = ownerId;
         this.members = members;
         this.roleCategory = roleCategory;
@@ -27,6 +29,14 @@ public class JoinableData<R extends RoleTable, T> {
         return joinable;
     }
 
+    public long getOwnerId() {
+        return ownerId;
+    }
+
+    public String getOwnerName() {
+        return ownerName;
+    }
+
     public Map<R, UsersTable> getMembers() {
         return members;
     }
diff --git a/src/main/java/io/papermc/hangar/model/viewhelpers/OrganizationData.java b/src/main/java/io/papermc/hangar/model/viewhelpers/OrganizationData.java
index d4b67f8d9..eaae9f9a9 100644
--- a/src/main/java/io/papermc/hangar/model/viewhelpers/OrganizationData.java
+++ b/src/main/java/io/papermc/hangar/model/viewhelpers/OrganizationData.java
@@ -8,13 +8,15 @@ import io.papermc.hangar.db.model.UserProjectRolesTable;
 import io.papermc.hangar.db.model.UsersTable;
 
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
 
 public class OrganizationData extends JoinableData<UserOrganizationRolesTable, OrganizationsTable> {
 
     private final Map<UserProjectRolesTable, ProjectsTable> projectRoles;
 
-    public OrganizationData(OrganizationsTable org, Map<UserOrganizationRolesTable, UsersTable> members, Map<UserProjectRolesTable, ProjectsTable> projectRoles) {
-        super(org, org.getOwnerId(), members, RoleCategory.ORGANIZATION);
+    public OrganizationData(OrganizationsTable org, UsersTable orgUser, Map<UserOrganizationRolesTable, UsersTable> members, Map<UserProjectRolesTable, ProjectsTable> projectRoles) {
+        super(org, org.getOwnerId(), orgUser.getName(), members, RoleCategory.ORGANIZATION);
         this.projectRoles = projectRoles;
     }
 
@@ -22,6 +24,10 @@ public class OrganizationData extends JoinableData<UserOrganizationRolesTable, O
         return this.joinable;
     }
 
+    public Map<UsersTable, UserRole<UserOrganizationRolesTable>> adminTable() {
+        return getMembers().entrySet().stream().collect(Collectors.toMap(Entry::getValue, entry -> new UserRole<>(entry.getKey())));
+    }
+
     public Map<UserProjectRolesTable, ProjectsTable> getProjectRoles() {
         return projectRoles;
     }
diff --git a/src/main/java/io/papermc/hangar/model/viewhelpers/ProjectData.java b/src/main/java/io/papermc/hangar/model/viewhelpers/ProjectData.java
index 9f7c2428c..9d3c7270b 100644
--- a/src/main/java/io/papermc/hangar/model/viewhelpers/ProjectData.java
+++ b/src/main/java/io/papermc/hangar/model/viewhelpers/ProjectData.java
@@ -29,7 +29,7 @@ public class ProjectData extends JoinableData<UserProjectRolesTable, ProjectsTab
 
 
     public ProjectData(ProjectsTable joinable, UsersTable projectOwner, int publicVersions, Map<UserProjectRolesTable, UsersTable> members, List<ProjectFlag> flags, int noteCount, ProjectVisibilityChangesTable lastVisibilityChange, String lastVisibilityChangeUser, ProjectVersionsTable recommendedVersion, String iconUrl, long starCount, long watcherCount, ProjectViewSettings settings) {
-        super(joinable, projectOwner.getId(), members, RoleCategory.PROJECT);
+        super(joinable, projectOwner.getId(), projectOwner.getName(), members, RoleCategory.PROJECT);
         this.projectOwner = projectOwner;
         this.publicVersions = publicVersions;
         this.flags = flags;
diff --git a/src/main/java/io/papermc/hangar/model/viewhelpers/UserData.java b/src/main/java/io/papermc/hangar/model/viewhelpers/UserData.java
index c602edac9..bc3618953 100644
--- a/src/main/java/io/papermc/hangar/model/viewhelpers/UserData.java
+++ b/src/main/java/io/papermc/hangar/model/viewhelpers/UserData.java
@@ -1,6 +1,5 @@
 package io.papermc.hangar.model.viewhelpers;
 
-import io.papermc.hangar.db.model.OrganizationsTable;
 import io.papermc.hangar.db.model.UserOrganizationRolesTable;
 import io.papermc.hangar.db.model.UsersTable;
 import io.papermc.hangar.model.Permission;
@@ -17,7 +16,7 @@ public class UserData {
     private UsersTable user;
     private boolean isOrga = false;
     private int projectCount;
-    private Map<OrganizationsTable, UserRole<UserOrganizationRolesTable>> orgas;
+    private Map<OrganizationData, UserRole<UserOrganizationRolesTable>> orgas;
     private List<Role> globalRoles;
     private Permission userPerm;
     private Permission orgaPerm;
@@ -26,7 +25,7 @@ public class UserData {
         return new UserData(headerData, user, false, 0, new HashMap<>(), new ArrayList<>(), Permission.None, Permission.None);
     }
 
-    public UserData(HeaderData headerData, UsersTable user, boolean isOrga, int projectCount, Map<OrganizationsTable, UserRole<UserOrganizationRolesTable>> orgas, List<Role> globalRoles, Permission userPerm, Permission orgaPerm) {
+    public UserData(HeaderData headerData, UsersTable user, boolean isOrga, int projectCount, Map<OrganizationData, UserRole<UserOrganizationRolesTable>> orgas, List<Role> globalRoles, Permission userPerm, Permission orgaPerm) {
         this.headerData = headerData;
         this.user = user;
         this.isOrga = isOrga;
@@ -81,11 +80,11 @@ public class UserData {
         this.projectCount = projectCount;
     }
 
-    public Map<OrganizationsTable, UserRole<UserOrganizationRolesTable>> getOrgas() {
+    public Map<OrganizationData, UserRole<UserOrganizationRolesTable>> getOrgas() {
         return orgas;
     }
 
-    public void setOrgas(Map<OrganizationsTable, UserRole<UserOrganizationRolesTable>> orgas) {
+    public void setOrgas(Map<OrganizationData, UserRole<UserOrganizationRolesTable>> orgas) {
         this.orgas = orgas;
     }
 
diff --git a/src/main/java/io/papermc/hangar/service/OrgService.java b/src/main/java/io/papermc/hangar/service/OrgService.java
index 35a2bc1fa..367349b52 100644
--- a/src/main/java/io/papermc/hangar/service/OrgService.java
+++ b/src/main/java/io/papermc/hangar/service/OrgService.java
@@ -14,6 +14,7 @@ import io.papermc.hangar.model.Permission;
 import io.papermc.hangar.model.viewhelpers.OrgMember;
 import io.papermc.hangar.model.viewhelpers.OrganizationData;
 import io.papermc.hangar.model.viewhelpers.ScopedOrganizationData;
+import org.jetbrains.annotations.Nullable;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
@@ -82,7 +83,17 @@ public class OrgService {
         return new ScopedOrganizationData();
     }
 
-    public OrganizationData getOrganizationData(OrganizationsTable org) {
-        return new OrganizationData(org, organizationDao.get().getOrgMembers(org.getId()), projectDao.get().getProjectRoles(org.getUserId()));
+    public OrganizationData getOrganizationData(UsersTable potentialOrg) {
+        OrganizationsTable org = organizationDao.get().getByUserId(potentialOrg.getId());
+        if (org == null) return null;
+        return getOrganizationData(org, potentialOrg);
+    }
+
+    public OrganizationData getOrganizationData(OrganizationsTable org, @Nullable UsersTable orgUser) {
+        UsersTable user = orgUser;
+        if (orgUser == null) {
+            user = userDao.get().getById(org.getUserId());
+        }
+        return new OrganizationData(org, user,organizationDao.get().getOrgMembers(org.getId()), projectDao.get().getProjectRoles(org.getUserId()));
     }
 }
diff --git a/src/main/java/io/papermc/hangar/service/UserService.java b/src/main/java/io/papermc/hangar/service/UserService.java
index 34d32144b..f0e5decba 100644
--- a/src/main/java/io/papermc/hangar/service/UserService.java
+++ b/src/main/java/io/papermc/hangar/service/UserService.java
@@ -17,6 +17,7 @@ import io.papermc.hangar.model.UserOrdering;
 import io.papermc.hangar.model.viewhelpers.Author;
 import io.papermc.hangar.model.viewhelpers.FlagActivity;
 import io.papermc.hangar.model.viewhelpers.HeaderData;
+import io.papermc.hangar.model.viewhelpers.OrganizationData;
 import io.papermc.hangar.model.viewhelpers.ReviewActivity;
 import io.papermc.hangar.model.viewhelpers.Staff;
 import io.papermc.hangar.model.viewhelpers.UserData;
@@ -46,10 +47,11 @@ public class UserService {
     private final HangarDao<OrganizationDao> organizationDao;
     private final RoleService roleService;
     private final PermissionService permissionService;
+    private final OrgService orgService;
     private final HangarConfig config;
 
     @Autowired
-    public UserService(HangarDao<UserDao> userDao, HangarConfig config, HangarDao<OrganizationDao> orgDao, HangarDao<ProjectDao> projectDao, HangarDao<OrganizationDao> organizationDao, RoleService roleService, PermissionService permissionService) {
+    public UserService(HangarDao<UserDao> userDao, HangarConfig config, HangarDao<OrganizationDao> orgDao, HangarDao<ProjectDao> projectDao, HangarDao<OrganizationDao> organizationDao, RoleService roleService, PermissionService permissionService, OrgService orgService) {
         this.userDao = userDao;
         this.config = config;
         this.orgDao = orgDao;
@@ -57,6 +59,7 @@ public class UserService {
         this.organizationDao = organizationDao;
         this.roleService = roleService;
         this.permissionService = permissionService;
+        this.orgService = orgService;
     }
 
     public UsersTable getCurrentUser() {
@@ -163,9 +166,9 @@ public class UserService {
         // TODO getUserData
         int projectCount = projectDao.get().getProjectCountByUserId(user.getId());
         Map<OrganizationsTable, UserOrganizationRolesTable> dbOrgs = orgDao.get().getUserOrganizationsAndRoles(user.getId());
-        Map<OrganizationsTable, UserRole<UserOrganizationRolesTable>> organizations = new HashMap<>();
+        Map<OrganizationData, UserRole<UserOrganizationRolesTable>> organizations = new HashMap<>();
         dbOrgs.forEach((organization, userOrganizationRolesTable) -> {
-            organizations.put(organization, new UserRole<>(userOrganizationRolesTable));
+            organizations.put(orgService.getOrganizationData(organization, null), new UserRole<>(userOrganizationRolesTable));
         });
         List<Role> globalRoles = roleService.getGlobalRolesForUser(user.getId(), null);
         boolean isOrga = globalRoles.contains(Role.ORGANIZATION);
diff --git a/src/main/resources/templates/users/admin/userAdmin.ftlh b/src/main/resources/templates/users/admin/userAdmin.ftlh
index 214dad80c..fb49f96df 100644
--- a/src/main/resources/templates/users/admin/userAdmin.ftlh
+++ b/src/main/resources/templates/users/admin/userAdmin.ftlh
@@ -41,17 +41,16 @@
                 <#if !u.isOrga()>
                     <@panel "Organizations">
                         <@roleTable keyName="Organization" tableType="orgRole" withOwner=true roles=u.orgas roleTypes=orgRoles ; org, role>
-                        <#-- @ftlvariable name="org" type="io.papermc.hangar.db.model.OrganizationsTable" -->
-                            <a href="${routes.getRouteUrl("userAdmin", org.name)}">
-                                ${org.name}
+                        <#-- @ftlvariable name="org" type="io.papermc.hangar.model.viewhelpers.OrganizationData" -->
+                            <a href="${routes.getRouteUrl("userAdmin", org.org.name)}">
+                                ${org.org.name}
                             </a>
                         </@roleTable>
                     </@panel>
                 <#else>
                     <@panel "Members">
-                        TODO organization members map
-                        <@roleTable keyName="User" tableType="memberRole" withOwner=false roles={} roleTypes=orgRoles ; member, role>
-                        <#-- @ftlvariable name="member" type="io.papermc.hangar.model.viewhelpers.UserData" -->
+                        <#-- TODO organization members map-->
+                        <@roleTable keyName="User" tableType="memberRole" withOwner=false roles=orga.adminTable() roleTypes=orgRoles ; member, role>
                             <a href="${routes.getRouteUrl("userAdmin", member.user.name)}">
                                 ${member.user.name}
                             </a>
@@ -97,7 +96,8 @@
             <tr data-role-type="${tableType}" data-role-id="${role.role.roleId}">
                 <td><#nested object, role /></td>
                 <#if withOwner>
-                    <td><a href="${routes.getRouteUrl("userAdmin", object.projectOwner.name)}">${object.projectOwner.name}</a></td>
+                    <#-- @ftlvariable name="object" type="io.papermc.hangar.model.viewhelpers.JoinableData" -->
+                    <td><a href="${routes.getRouteUrl("userAdmin", object.ownerName)}">${object.ownerName}</a></td>
                 </#if>
                 <#if !role.role.assignable>
                     <td>
diff --git a/src/main/resources/templates/users/projects.ftlh b/src/main/resources/templates/users/projects.ftlh
index 76b875de4..6e8e32b7d 100644
--- a/src/main/resources/templates/users/projects.ftlh
+++ b/src/main/resources/templates/users/projects.ftlh
@@ -77,9 +77,9 @@
                             <tr>
                                 <td>
                                     <#import "*/utils/userAvatar.ftlh" as userAvatar>
-                                    <@userAvatar.userAvatar userName=organization.name avatarUrl=utils.avatarUrl(organization.name) clazz="user-avatar-xxs"></@userAvatar.userAvatar>
-                                <a href="${routes.getRouteUrl("users.showProjects", organization.name)}">
-                                ${organization.name}
+                                    <@userAvatar.userAvatar userName=organization.org.name avatarUrl=utils.avatarUrl(organization.org.name) clazz="user-avatar-xxs"></@userAvatar.userAvatar>
+                                <a href="${routes.getRouteUrl("users.showProjects", organization.org.name)}">
+                                ${organization.org.name}
                                 </a>
                                 <div class="pull-right">
                                 ${role.role.title}