diff --git a/ccm-core/src/main/java/org/libreccm/api/admin/AdminApi.java b/ccm-core/src/main/java/org/libreccm/api/admin/AdminApi.java index 2c925a9ab..1206776e5 100644 --- a/ccm-core/src/main/java/org/libreccm/api/admin/AdminApi.java +++ b/ccm-core/src/main/java/org/libreccm/api/admin/AdminApi.java @@ -20,6 +20,7 @@ import org.libreccm.api.DefaultResponseHeaders; import org.libreccm.api.PreflightRequestFilter; import org.libreccm.api.admin.categorization.CategoriesApi; import org.libreccm.api.admin.categorization.DomainsApi; +import org.libreccm.api.admin.sites.SitesApi; import org.libreccm.configuration.Configuration; /** @@ -49,6 +50,9 @@ public class AdminApi extends Application { classes.add(RolesApi.class); classes.add(UsersApi.class); + // Sites API + classes.add(SitesApi.class); + // System Information API classes.add(SystemInformationApi.class); diff --git a/ccm-core/src/main/java/org/libreccm/api/admin/categorization/dto/CategoryData.java b/ccm-core/src/main/java/org/libreccm/api/admin/categorization/dto/CategoryData.java index 00bbf64f2..943cee8cc 100644 --- a/ccm-core/src/main/java/org/libreccm/api/admin/categorization/dto/CategoryData.java +++ b/ccm-core/src/main/java/org/libreccm/api/admin/categorization/dto/CategoryData.java @@ -52,7 +52,7 @@ public class CategoryData { private long categoryOrder; public CategoryData() { - // Nothing + super(); } public CategoryData(final Category fromCategory) { diff --git a/ccm-core/src/main/java/org/libreccm/api/admin/security/RolesApi.java b/ccm-core/src/main/java/org/libreccm/api/admin/security/RolesApi.java index 1fa841b34..d1ae08892 100644 --- a/ccm-core/src/main/java/org/libreccm/api/admin/security/RolesApi.java +++ b/ccm-core/src/main/java/org/libreccm/api/admin/security/RolesApi.java @@ -44,7 +44,6 @@ import org.libreccm.security.Role; import org.libreccm.security.RoleManager; import org.libreccm.security.RoleRepository; -import java.net.URI; import java.util.stream.Collectors; import javax.ws.rs.WebApplicationException; diff --git a/ccm-core/src/main/java/org/libreccm/api/admin/sites/SitesApi.java b/ccm-core/src/main/java/org/libreccm/api/admin/sites/SitesApi.java new file mode 100644 index 000000000..57be0aec5 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/api/admin/sites/SitesApi.java @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2020 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.libreccm.api.admin.sites; + +import org.libreccm.api.Identifier; +import org.libreccm.api.IdentifierParser; +import org.libreccm.api.admin.sites.dto.SiteDto; +import org.libreccm.api.admin.web.dto.CcmApplicationId; +import org.libreccm.core.CoreConstants; +import org.libreccm.security.AuthorizationRequired; +import org.libreccm.security.RequiresPrivilege; +import org.libreccm.sites.Site; +import org.libreccm.sites.SiteAwareApplication; +import org.libreccm.sites.SiteManager; +import org.libreccm.sites.SiteRepository; +import org.libreccm.web.ApplicationRepository; +import org.libreccm.web.CcmApplication; + +import java.util.List; +import java.util.stream.Collectors; + +import javax.inject.Inject; +import javax.transaction.Transactional; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +/** + * + * @author Jens Pelzetter + */ +@Path("/sites") +public class SitesApi { + + @Context + private UriInfo uriInfo; + + @Inject + private ApplicationRepository applicationRepository; + + @Inject + private IdentifierParser identifierParser; + + @Inject + private SiteManager siteManager; + + @Inject + private SiteRepository siteRepository; + + @GET + @Path("/") + @Produces(MediaType.APPLICATION_JSON) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public List getSites() { + return siteRepository + .findAll() + .stream() + .map(SiteDto::new) + .collect(Collectors.toList()); + } + + @GET + @Path("/{siteIdentifier}") + @Produces(MediaType.APPLICATION_JSON) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public SiteDto getSite( + @PathParam("siteIdentifier") final String siteIdentifier + ) { + return new SiteDto(findSite(siteIdentifier)); + } + + @POST + @Path("/") + @Consumes(MediaType.APPLICATION_JSON) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public Response addSite(final SiteDto siteDto) { + final Site site = new Site(); + site.setDefaultSite(siteDto.isDefaultSite()); + site.setDefaultTheme(siteDto.getDefaultTheme()); + site.setDomainOfSite(siteDto.getDomainOfSite()); + + siteRepository.save(site); + + return Response + .created( + uriInfo + .getBaseUriBuilder() + .path(site.getDomainOfSite()) + .build() + ).build(); + } + + @PUT + @Path("/{siteIdentifier}") + @Consumes(MediaType.APPLICATION_JSON) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public Response updateSite( + @PathParam("siteIdentifier") final String siteIdentifier, + final SiteDto siteDto + ) { + final Site site = findSite(siteIdentifier); + + site.setDefaultSite(siteDto.isDefaultSite()); + site.setDefaultTheme(siteDto.getDefaultTheme()); + site.setDomainOfSite(siteDto.getDomainOfSite()); + + siteRepository.save(site); + + return Response.ok( + String.format( + "Site %s updated successfully.", + siteIdentifier + ) + ).build(); + } + + @DELETE + @Path("/{siteIdentifier}") + @Produces(MediaType.APPLICATION_JSON) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public Response deleteSite( + @PathParam("siteIdentifier") final String siteIdentifier + ) { + final Site site = findSite(siteIdentifier); + + siteRepository.delete(site); + + return Response.ok( + String.format("Site %s successfully deleted", siteIdentifier) + ).build(); + } + + @GET + @Path("/{siteIdentifier}/applications") + @Produces(MediaType.APPLICATION_JSON) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public List getApplications( + @PathParam("siteIdentifier") final String siteIdentifier + ) { + final Site site = findSite(siteIdentifier); + return site + .getApplications() + .stream() + .map(CcmApplicationId::new) + .collect(Collectors.toList()); + } + + @PUT + @Path("/{siteIdentifier}/applications/{applicationIdentifier}") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public Response addApplication( + @PathParam("siteIdentifier") final String siteIdentifier, + @PathParam("applicationIdentifier") final String applicationIdentifier + ) { + final Site site = findSite(siteIdentifier); + final SiteAwareApplication application = findApplication( + applicationIdentifier + ); + + siteManager.addApplicationToSite(application, site); + + return Response.ok( + String.format( + "Application %s successfully added to Site %s.", + applicationIdentifier, + siteIdentifier + ) + ).build(); + } + + @DELETE + @Path("/{siteIdentifier}/applications/{applicationIdentifier}") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public Response removeApplication( + @PathParam("siteIdentifier") final String siteIdentifier, + @PathParam("applicationIdentifier") final String applicationIdentifier + ) { + final Site site = findSite(siteIdentifier); + final SiteAwareApplication application = findApplication( + applicationIdentifier + ); + + siteManager.removeApplicationFromSite(application, site); + + return Response.ok( + String.format( + "Application %s successfully removed from Site %s.", + applicationIdentifier, + siteIdentifier + ) + ).build(); + } + + private Site findSite(final String siteIdentifier) { + final Identifier identifier = identifierParser.parseIdentifier( + siteIdentifier + ); + switch (identifier.getType()) { + case ID: + return siteRepository.findById( + Long.parseLong(identifier.getIdentifier()) + ).orElseThrow( + () -> new NotFoundException( + String.format( + "No Site with ID %s found.", + identifier.getIdentifier() + ) + ) + ); + case UUID: + return siteRepository + .findByUuid(identifier.getIdentifier()) + .orElseThrow( + () -> new NotFoundException( + String.format( + "No Site with UUID %s found", + identifier.getIdentifier() + ) + ) + ); + default: + return siteRepository + .findByDomain(identifier.getIdentifier()) + .orElseThrow( + () -> new NotFoundException( + String.format( + "No Site for domain %s found.", + identifier.getIdentifier() + ) + ) + ); + } + } + + private SiteAwareApplication findApplication(final String appIdentifier) { + final Identifier identifier = identifierParser.parseIdentifier( + appIdentifier + ); + final CcmApplication application; + switch (identifier.getType()) { + case ID: + application = applicationRepository + .findById(Long.parseLong(identifier.getIdentifier())) + .orElseThrow( + () -> new NotFoundException( + String.format( + "No CcmApplication with ID %s found.", + identifier.getIdentifier() + ) + ) + ); + break; + case UUID: + application = applicationRepository + .findByUuid(identifier.getIdentifier()) + .orElseThrow( + () -> new NotFoundException( + String.format( + "No CcmApplication with UUID %s found.", + identifier.getIdentifier() + ) + ) + ); + break; + default: + application = applicationRepository + .retrieveApplicationForPath(identifier.getIdentifier()) + .orElseThrow( + () -> new NotFoundException( + String.format( + "No CcmApplication for path %s found.", + identifier.getIdentifier() + ) + ) + ); + break; + } + + if (application instanceof SiteAwareApplication) { + return (SiteAwareApplication) application; + } else { + throw new BadRequestException( + String.format( + "Site %s is not a site aware application.", + identifier.getIdentifier() + ) + ); + } + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/api/admin/sites/dto/SiteDto.java b/ccm-core/src/main/java/org/libreccm/api/admin/sites/dto/SiteDto.java new file mode 100644 index 000000000..f493906e6 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/api/admin/sites/dto/SiteDto.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2020 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.libreccm.api.admin.sites.dto; + +import org.libreccm.sites.Site; + +/** + * + * @author Jens Pelzetter + */ +public class SiteDto { + + private long siteId; + + private String uuid; + + private String domainOfSite; + + private boolean defaultSite; + + private String defaultTheme; + + public SiteDto() { + super(); + } + + public SiteDto(final Site fromSite) { + siteId = fromSite.getObjectId(); + uuid = fromSite.getUuid(); + domainOfSite = fromSite.getDomainOfSite(); + defaultSite = fromSite.isDefaultSite(); + defaultTheme = fromSite.getDefaultTheme(); + } + + public long getSiteId() { + return siteId; + } + + public void setSiteId(long siteId) { + this.siteId = siteId; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getDomainOfSite() { + return domainOfSite; + } + + public void setDomainOfSite(String domainOfSite) { + this.domainOfSite = domainOfSite; + } + + public boolean isDefaultSite() { + return defaultSite; + } + + public void setDefaultSite(boolean defaultSite) { + this.defaultSite = defaultSite; + } + + public String getDefaultTheme() { + return defaultTheme; + } + + public void setDefaultTheme(String defaultTheme) { + this.defaultTheme = defaultTheme; + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/sites/Site.java b/ccm-core/src/main/java/org/libreccm/sites/Site.java index e0559bdd1..1fabd8c11 100644 --- a/ccm-core/src/main/java/org/libreccm/sites/Site.java +++ b/ccm-core/src/main/java/org/libreccm/sites/Site.java @@ -49,15 +49,17 @@ import javax.persistence.Table; query = "SELECT s FROM Site s " + "WHERE s.domainOfSite = :domain " + "ORDER BY s.domainOfSite" - ) - , + ), @NamedQuery( name = "Site.findDefaultSite", query = "SELECT s FROM Site s " + "WHERE s.defaultSite = true " + "ORDER BY s.domainOfSite" - ) - , + ), + @NamedQuery( + name = "Site.findByUuid", + query = "SELECT s FROM Site s WHERE s.uuid = :uuid" + ), @NamedQuery( name = "Site.hasSiteForDomain", query = "SELECT (CASE WHEN COUNT(s) > 0 THEN true ELSE false END) " diff --git a/ccm-core/src/main/java/org/libreccm/sites/SiteAwareApplication.java b/ccm-core/src/main/java/org/libreccm/sites/SiteAwareApplication.java index 0cb9e6f6c..42492cd87 100644 --- a/ccm-core/src/main/java/org/libreccm/sites/SiteAwareApplication.java +++ b/ccm-core/src/main/java/org/libreccm/sites/SiteAwareApplication.java @@ -96,8 +96,9 @@ public class SiteAwareApplication extends CcmApplication { } else if (site != null && other.getSite() == null) { return false; } else { - if (!Objects.equals(site.getDomainOfSite(), - other.getSite().getDomainOfSite())) { + if (!Objects.equals( + site.getDomainOfSite(), other.getSite().getDomainOfSite() + )) { return false; } if (site.isDefaultSite() != other.getSite().isDefaultSite()) { @@ -121,16 +122,20 @@ public class SiteAwareApplication extends CcmApplication { public String toString(final String data) { if (site == null) { - return super.toString(String.format(", site = null%d", data)); + return super.toString(String.format(", site = null%s", data)); } else { - return super.toString(String.format(", site = { " - + "domainOfSite = \"%s\", " - + "isDefaultSite = %b," - + "defaultTheme = \"%s\" }%s", - site.getDomainOfSite(), - site.isDefaultSite(), - site.getDefaultTheme(), - data)); + return super.toString( + String.format( + ", site = { " + + "domainOfSite = \"%s\", " + + "isDefaultSite = %b," + + "defaultTheme = \"%s\" }%s", + site.getDomainOfSite(), + site.isDefaultSite(), + site.getDefaultTheme(), + data + ) + ); } } diff --git a/ccm-core/src/main/java/org/libreccm/sites/SiteRepository.java b/ccm-core/src/main/java/org/libreccm/sites/SiteRepository.java index 81389faa3..b42770b50 100644 --- a/ccm-core/src/main/java/org/libreccm/sites/SiteRepository.java +++ b/ccm-core/src/main/java/org/libreccm/sites/SiteRepository.java @@ -41,6 +41,20 @@ public class SiteRepository extends AbstractEntityRepository { private static final long serialVersionUID = 3120528987720524155L; + @Transactional(Transactional.TxType.REQUIRED) + public Optional findByUuid(final String uuid) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery("Site.findByUuid", Site.class) + .setParameter("uuid", uuid) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + /** * Retrieve the {@link Site} for a specific domain. * @@ -127,7 +141,7 @@ public class SiteRepository extends AbstractEntityRepository { public String getIdAttributeName() { return "objectId"; } - + @Override public Long getIdOfEntity(final Site entity) { return entity.getObjectId(); diff --git a/ccm-core/src/site/resources/ccm-core-api.json b/ccm-core/src/site/resources/ccm-core-api.json index 3d041bcdf..227908ae1 100644 --- a/ccm-core/src/site/resources/ccm-core-api.json +++ b/ccm-core/src/site/resources/ccm-core-api.json @@ -69,7 +69,7 @@ }, "/api/admin/categories/{domainIdentifier}/{path}" : { "get" : { - "operationId" : "getCategory_2", + "operationId" : "getCategory_1", "parameters" : [ { "name" : "domainIdentifier", "in" : "path", @@ -162,7 +162,7 @@ }, "/api/admin/categories/ID-{categoryId}" : { "get" : { - "operationId" : "getCategory_1", + "operationId" : "getCategory", "parameters" : [ { "name" : "categoryId", "in" : "path", @@ -237,7 +237,7 @@ }, "/api/admin/categories/{domainIdentifier}/{path}/subcategories" : { "get" : { - "operationId" : "getSubCategories_2", + "operationId" : "getSubCategories", "parameters" : [ { "name" : "domainIdentifier", "in" : "path", @@ -631,7 +631,7 @@ }, "/api/admin/categories/UUID-{categoryId}" : { "get" : { - "operationId" : "getCategory", + "operationId" : "getCategory_2", "parameters" : [ { "name" : "categoryId", "in" : "path", @@ -656,7 +656,7 @@ }, "/api/admin/categories/UUID-{categoryUid}/subcategories" : { "get" : { - "operationId" : "getSubCategories", + "operationId" : "getSubCategories_1", "parameters" : [ { "name" : "categoryUuid", "in" : "path", @@ -697,7 +697,7 @@ }, "/api/admin/categories/ID-{categoryId}/subcategories" : { "get" : { - "operationId" : "getSubCategories_1", + "operationId" : "getSubCategories_2", "parameters" : [ { "name" : "categoryId", "in" : "path", @@ -1299,47 +1299,6 @@ } } }, - "/api/admin/groups/{groupIdentifier}/members" : { - "get" : { - "operationId" : "getMembers", - "parameters" : [ { - "name" : "groupIdentifier", - "in" : "path", - "required" : true, - "schema" : { - "type" : "string" - } - }, { - "name" : "limit", - "in" : "query", - "schema" : { - "type" : "integer", - "format" : "int32", - "default" : 20 - } - }, { - "name" : "offset", - "in" : "query", - "schema" : { - "type" : "integer", - "format" : "int32", - "default" : 0 - } - } ], - "responses" : { - "default" : { - "description" : "default response", - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/ListViewGroupUserMembership" - } - } - } - } - } - } - }, "/api/admin/groups/{groupIdentifier}/roles" : { "get" : { "operationId" : "getRoleMemberships", @@ -1422,6 +1381,47 @@ } } }, + "/api/admin/groups/{groupIdentifier}/members" : { + "get" : { + "operationId" : "getMembers", + "parameters" : [ { + "name" : "groupIdentifier", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "limit", + "in" : "query", + "schema" : { + "type" : "integer", + "format" : "int32", + "default" : 20 + } + }, { + "name" : "offset", + "in" : "query", + "schema" : { + "type" : "integer", + "format" : "int32", + "default" : 0 + } + } ], + "responses" : { + "default" : { + "description" : "default response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListViewGroupUserMembership" + } + } + } + } + } + } + }, "/api/admin/roles/{roleIdentifier}" : { "get" : { "operationId" : "getRole", @@ -1548,6 +1548,60 @@ } } }, + "/api/admin/roles" : { + "get" : { + "operationId" : "getRoles", + "parameters" : [ { + "name" : "limit", + "in" : "query", + "schema" : { + "type" : "integer", + "format" : "int32", + "default" : 20 + } + }, { + "name" : "offset", + "in" : "query", + "schema" : { + "type" : "integer", + "format" : "int32", + "default" : 0 + } + } ], + "responses" : { + "default" : { + "description" : "default response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListViewRoleData" + } + } + } + } + } + }, + "post" : { + "operationId" : "addRole", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/RoleData" + } + } + } + }, + "responses" : { + "default" : { + "description" : "default response", + "content" : { + "*/*" : { } + } + } + } + } + }, "/api/admin/roles/{roleIdentifier}/permissions" : { "get" : { "operationId" : "getPermissions", @@ -1617,6 +1671,34 @@ } } }, + "/api/admin/roles/{roleIdentifier}/permissions/{permissionIdentifier}" : { + "delete" : { + "operationId" : "removePermission", + "parameters" : [ { + "name" : "roleIdentifier", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "permissionIdentifier", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "default" : { + "description" : "default response", + "content" : { + "*/*" : { } + } + } + } + } + }, "/api/admin/roles/{roleIdentifier}/members" : { "get" : { "operationId" : "getMembers_1", @@ -1658,88 +1740,6 @@ } } }, - "/api/admin/roles" : { - "get" : { - "operationId" : "getRoles", - "parameters" : [ { - "name" : "limit", - "in" : "query", - "schema" : { - "type" : "integer", - "format" : "int32", - "default" : 20 - } - }, { - "name" : "offset", - "in" : "query", - "schema" : { - "type" : "integer", - "format" : "int32", - "default" : 0 - } - } ], - "responses" : { - "default" : { - "description" : "default response", - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/ListViewRoleData" - } - } - } - } - } - }, - "post" : { - "operationId" : "addRole", - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/RoleData" - } - } - } - }, - "responses" : { - "default" : { - "description" : "default response", - "content" : { - "*/*" : { } - } - } - } - } - }, - "/api/admin/roles/{roleIdentifier}/permissions/{permissionIdentifier}" : { - "delete" : { - "operationId" : "removePermission", - "parameters" : [ { - "name" : "roleIdentifier", - "in" : "path", - "required" : true, - "schema" : { - "type" : "string" - } - }, { - "name" : "permissionIdentifier", - "in" : "path", - "required" : true, - "schema" : { - "type" : "string" - } - } ], - "responses" : { - "default" : { - "description" : "default response", - "content" : { - "*/*" : { } - } - } - } - } - }, "/api/admin/users" : { "get" : { "operationId" : "getUsers", @@ -2521,13 +2521,13 @@ } } }, - "ListViewGroupUserMembership" : { + "ListViewGroupData" : { "type" : "object", "properties" : { "list" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/GroupUserMembership" + "$ref" : "#/components/schemas/GroupData" } }, "count" : { @@ -2544,13 +2544,13 @@ } } }, - "ListViewGroupData" : { + "ListViewGroupUserMembership" : { "type" : "object", "properties" : { "list" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/GroupData" + "$ref" : "#/components/schemas/GroupUserMembership" } }, "count" : { @@ -2625,6 +2625,29 @@ } } }, + "ListViewRoleData" : { + "type" : "object", + "properties" : { + "list" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/RoleData" + } + }, + "count" : { + "type" : "integer", + "format" : "int64" + }, + "limit" : { + "type" : "integer", + "format" : "int64" + }, + "offset" : { + "type" : "integer", + "format" : "int64" + } + } + }, "ListViewRolePermission" : { "type" : "object", "properties" : { @@ -2686,29 +2709,6 @@ } } }, - "ListViewRoleData" : { - "type" : "object", - "properties" : { - "list" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/RoleData" - } - }, - "count" : { - "type" : "integer", - "format" : "int64" - }, - "limit" : { - "type" : "integer", - "format" : "int64" - }, - "offset" : { - "type" : "integer", - "format" : "int64" - } - } - }, "EmailAddress" : { "required" : [ "address" ], "type" : "object",