diff --git a/frontend/pages/_user/index.vue b/frontend/pages/_user/index.vue index 7740b625..2569bd95 100644 --- a/frontend/pages/_user/index.vue +++ b/frontend/pages/_user/index.vue @@ -13,11 +13,19 @@ {{ $t('author.orgs') }} - - {{ org.name }} + + + + + + {{ orgName }} + + + {{ orgRole.role.title }} + - + {{ $t('author.noOrgs', [user.name]) }} @@ -62,6 +70,7 @@ import { Component } from 'nuxt-property-decorator'; import { PaginatedResult, Project, ProjectCompact, Role } from 'hangar-api'; import { Context } from '@nuxt/types'; +import { RoleTable } from 'hangar-internal'; import { UserAvatar } from '~/components/users'; import { ProjectList } from '~/components/projects'; import { UserPropPage } from '~/components/mixins'; @@ -76,8 +85,7 @@ import MemberList from '~/components/projects/MemberList.vue'; }) export default class AuthorPage extends UserPropPage { projects!: PaginatedResult; - // todo load orgs from server - orgs: PaginatedResult = { result: [], pagination: { offset: 0, count: 0, limit: 20 } }; + organizations!: { [key: string]: RoleTable }; starred!: PaginatedResult; watching!: PaginatedResult; orgRoles!: Role[]; @@ -88,17 +96,18 @@ export default class AuthorPage extends UserPropPage { }; } - async asyncData({ $api, route, $util }: Context) { + async asyncData({ $api, params, $util }: Context) { const data = await Promise.all([ - $api.request>(`users/${route.params.user}/starred`, false), - $api.request>(`users/${route.params.user}/watching`, false), + $api.request>(`users/${params.user}/starred`, false), + $api.request>(`users/${params.user}/watching`, false), $api.request>(`projects`, false, 'get', { - owner: route.params.user, + owner: params.user, }), $api.requestInternal('data/orgRoles', false, 'get'), + $api.requestInternal<{ [key: string]: RoleTable }>(`organizations/${params.user}/userOrganizations`, false), ]).catch($util.handlePageRequestError); if (typeof data === 'undefined') return; - return { starred: data[1], watching: data[0], projects: data[2], orgRoles: data[3] }; + return { starred: data[1], watching: data[0], projects: data[2], orgRoles: data[3], organizations: data[4] }; } } diff --git a/src/main/java/io/papermc/hangar/controller/internal/OrganizationController.java b/src/main/java/io/papermc/hangar/controller/internal/OrganizationController.java index 2b3faf5c..6c09fe33 100644 --- a/src/main/java/io/papermc/hangar/controller/internal/OrganizationController.java +++ b/src/main/java/io/papermc/hangar/controller/internal/OrganizationController.java @@ -1,6 +1,7 @@ package io.papermc.hangar.controller.internal; import io.papermc.hangar.exceptions.HangarApiException; +import io.papermc.hangar.model.db.roles.OrganizationRoleTable; import io.papermc.hangar.model.internal.HangarOrganization; import io.papermc.hangar.model.internal.api.requests.CreateOrganizationForm; import io.papermc.hangar.security.annotations.Anyone; @@ -22,6 +23,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import javax.validation.Valid; +import java.util.Map; @Controller @RequestMapping("/api/internal/organizations") @@ -59,4 +61,10 @@ public class OrganizationController { System.out.println(createOrganizationForm); organizationFactory.createOrganization(createOrganizationForm.getName(), createOrganizationForm.getNewMembers()); } + + @Anyone + @GetMapping(path = "/{user}/userOrganizations", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getUserOrganizationRoles(@PathVariable String user) { + return ResponseEntity.ok(organizationService.getUserOrganizationRoles(user)); + } } diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/table/roles/OrganizationRolesDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/table/roles/OrganizationRolesDAO.java index b16c28ed..8b053a58 100644 --- a/src/main/java/io/papermc/hangar/db/dao/internal/table/roles/OrganizationRolesDAO.java +++ b/src/main/java/io/papermc/hangar/db/dao/internal/table/roles/OrganizationRolesDAO.java @@ -2,6 +2,7 @@ package io.papermc.hangar.db.dao.internal.table.roles; import io.papermc.hangar.db.mappers.RoleMapperFactory; import io.papermc.hangar.model.db.roles.OrganizationRoleTable; +import org.jdbi.v3.sqlobject.config.KeyColumn; import org.jdbi.v3.sqlobject.config.RegisterColumnMapperFactory; import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper; import org.jdbi.v3.sqlobject.customizer.BindBean; @@ -11,6 +12,8 @@ import org.jdbi.v3.sqlobject.statement.SqlQuery; import org.jdbi.v3.sqlobject.statement.SqlUpdate; import org.springframework.stereotype.Repository; +import java.util.Map; + @Repository @RegisterConstructorMapper(OrganizationRoleTable.class) @RegisterColumnMapperFactory(RoleMapperFactory.class) @@ -42,4 +45,12 @@ public interface OrganizationRolesDAO extends IRolesDAO { @Override @SqlQuery("SELECT * FROM user_organization_roles WHERE organization_id = :organizationId AND user_id = :userId") OrganizationRoleTable getTable(@BindBean OrganizationRoleTable table); + + @KeyColumn("name") + @SqlQuery("SELECT o.name, uor.*" + + " FROM user_organization_roles uor" + + " JOIN organizations o ON o.id = uor.organization_id" + + " JOIN users u ON uor.user_id = u.id" + + " WHERE u.name = :user AND uor.accepted IS TRUE") + Map getUserOrganizationRoles(String user, Long userId); } diff --git a/src/main/java/io/papermc/hangar/service/internal/organizations/OrganizationService.java b/src/main/java/io/papermc/hangar/service/internal/organizations/OrganizationService.java index 1bcd3f0b..8ed976a1 100644 --- a/src/main/java/io/papermc/hangar/service/internal/organizations/OrganizationService.java +++ b/src/main/java/io/papermc/hangar/service/internal/organizations/OrganizationService.java @@ -4,10 +4,12 @@ import io.papermc.hangar.db.dao.HangarDao; import io.papermc.hangar.db.dao.internal.HangarOrganizationsDAO; import io.papermc.hangar.db.dao.internal.table.OrganizationDAO; import io.papermc.hangar.db.dao.internal.table.UserDAO; +import io.papermc.hangar.db.dao.internal.table.roles.OrganizationRolesDAO; import io.papermc.hangar.exceptions.HangarApiException; import io.papermc.hangar.model.common.Permission; import io.papermc.hangar.model.db.OrganizationTable; import io.papermc.hangar.model.db.UserTable; +import io.papermc.hangar.model.db.roles.OrganizationRoleTable; import io.papermc.hangar.model.internal.HangarOrganization; import io.papermc.hangar.service.HangarService; import io.papermc.hangar.service.PermissionService; @@ -16,18 +18,21 @@ import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Map; @Service public class OrganizationService extends HangarService { private final HangarOrganizationsDAO hangarOrganizationsDAO; + private final OrganizationRolesDAO organizationRolesDAO; private final OrganizationDAO organizationDAO; private final UserDAO userDAO; private final PermissionService permissionService; @Autowired - public OrganizationService(HangarDao hangarOrganizationsDAO, HangarDao organizationDAO, HangarDao userDAO, PermissionService permissionService) { + public OrganizationService(HangarDao hangarOrganizationsDAO, HangarDao organizationRolesDAO, HangarDao organizationDAO, HangarDao userDAO, PermissionService permissionService) { this.hangarOrganizationsDAO = hangarOrganizationsDAO.get(); + this.organizationRolesDAO = organizationRolesDAO.get(); this.organizationDAO = organizationDAO.get(); this.userDAO = userDAO.get(); this.permissionService = permissionService; @@ -54,4 +59,8 @@ public class OrganizationService extends HangarService { var members = hangarOrganizationsDAO.getOrganizationMembers(organizationTable.getId(), getHangarUserId(), permissionService.getOrganizationPermissions(getHangarUserId(), organizationTable.getId()).has(Permission.ManageOrganizationMembers)); return new HangarOrganization(organizationTable.getId(), owner, members); } + + public Map getUserOrganizationRoles(String user) { + return organizationRolesDAO.getUserOrganizationRoles(user, getHangarUserId()); + } }