diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java index ca941abe..8809c64c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ActivatableEntityController.java @@ -32,6 +32,10 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ActivatableEntityDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Content; /** Abstract Entity-Controller that defines generic Entity rest API endpoints that are supported * by all entity types that has activation feature and can be activated or deactivated. @@ -57,7 +61,30 @@ public abstract class ActivatableEntityController getAll(filterMap)).getOrThrow(); } + @Operation( + summary = "Get a page of all specific domain entity that are currently inactive.", + description = "Sorting: the sort parameter to sort the list of entities before paging\n" + + "the sort parameter is the name of the entity-model attribute to sort with a leading '-' sign for\n" + + "descending sort order. Note that not all entity-model attribute are suited for sorting while the most\n" + + "are.\n", + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = { @Content(mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) }), + parameters = { + @Parameter( + name = Page.ATTR_PAGE_NUMBER, + description = "The number of the page to get from the whole list. If the page does not exists, the API retruns with the first page."), + @Parameter( + name = Page.ATTR_PAGE_SIZE, + description = "The size of the page to get."), + @Parameter( + name = Page.ATTR_SORT, + description = "the sort parameter to sort the list of entities before paging"), + @Parameter( + name = API.PARAM_INSTITUTION_ID, + description = "The institution identifier of the request.\n" + + "Default is the institution identifier of the institution of the current user"), + + }) @RequestMapping( path = API.INACTIVE_PATH_SEGMENT, method = RequestMethod.GET, @@ -114,6 +165,16 @@ public abstract class ActivatableEntityController getAll(filterMap)).getOrThrow(); } + @Operation( + summary = "Activate a single entity by its modelId.", + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = { @Content(mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) }), + parameters = { + @Parameter( + name = API.PARAM_MODEL_ID, + description = "The model identifier of the entity object to activate.", + in = ParameterIn.PATH) + }) @RequestMapping( path = API.PATH_VAR_ACTIVE, method = RequestMethod.POST, @@ -124,6 +185,16 @@ public abstract class ActivatableEntityController { * @return Page of domain-model-entities of specified type */ @Operation( summary = "Get a page of the specific domain entity. Sorting and filtering is applied before paging", + description = "Sorting: the sort parameter to sort the list of entities before paging\n" + + "the sort parameter is the name of the entity-model attribute to sort with a leading '-' sign for\n" + + "descending sort order. Note that not all entity-model attribute are suited for sorting while the most\n" + + "are.\n" + + "

\n" + + "Filter: The filter attributes accepted by this API depend on the actual entity model (domain object)\n" + + "and are of the form [domain-attribute-name]=[filter-value]. E.g.: name=abc or type=EXAM. Usually\n" + + "filter attributes of text type are treated as SQL wildcard with %[text]% to filter all text containing\n" + + "a given text-snippet.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( content = { @Content(mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) }), parameters = { @@ -147,10 +157,7 @@ public abstract class EntityController { description = "The size of the page to get."), @Parameter( name = Page.ATTR_SORT, - description = "the sort parameter to sort the list of entities before paging\n" - + "the sort parameter is the name of the entity-model attribute to sort with a leading '-' sign for\n" - + "descending sort order. Note that not all entity-model attribute are suited for sorting while the most are.", - example = "-name"), + description = "the sort parameter to sort the list of entities before paging"), @Parameter( name = API.PARAM_INSTITUTION_ID, description = "The institution identifier of the request.\n" @@ -158,11 +165,7 @@ public abstract class EntityController { @Parameter( name = "filterCriteria", description = "Additional filter criterias \n" + - "The filter criteria attributes accepted by this API depend on the actual entity model (domain entity)\n" - + "and are query of the form [domain-attribute-name]=[filter-value]. E.g.: name=abc or type=EXAM.\n" - + "For OpenAPI 3 input please use the form: {\"columnName\":\"filterValue\"}\n" - + "Usually filter attributes of text type are treated as SQL wildcard with %[text]% to filter all text containing\n" - + "a given text-snippet.", + "For OpenAPI 3 input please use the form: {\"columnName\":\"filterValue\"}", example = "{\"name\":\"ethz\"}", required = false, allowEmptyValue = true) @@ -215,8 +218,13 @@ public abstract class EntityController { // ****************** @Operation( - summary = "Get a filtered list of specific entity name keys.\n" + - "An entity name key is a minimal entity data object with the entity-type, modelId and the name of the entity.", + summary = "Get a filtered list of specific entity name keys.", + description = "An entity name key is a minimal entity data object with the entity-type, modelId and the name of the entity." + + "

\n" + + "Filter: The filter attributes accepted by this API depend on the actual entity model (domain object)\n" + + "and are of the form [domain-attribute-name]=[filter-value]. E.g.: name=abc or type=EXAM. Usually\n" + + "filter attributes of text type are treated as SQL wildcard with %[text]% to filter all text containing\n" + + "a given text-snippet.", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( content = { @Content(mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) }), parameters = { @@ -227,11 +235,7 @@ public abstract class EntityController { @Parameter( name = "filterCriteria", description = "Additional filter criterias \n" + - "The filter criteria attributes accepted by this API depend on the actual entity model (domain entity)\n" - + "and are query of the form [domain-attribute-name]=[filter-value]. E.g.: name=abc or type=EXAM.\n" - + "For OpenAPI 3 input please use the form: {\"columnName\":\"filterValue\"}\n" - + "Usually filter attributes of text type are treated as SQL wildcard with %[text]% to filter all text containing\n" - + "a given text-snippet.", + "For OpenAPI 3 input please use the form: {\"columnName\":\"filterValue\"}", example = "{\"name\":\"ethz\"}", required = false, allowEmptyValue = true) @@ -273,6 +277,34 @@ public abstract class EntityController { // * GET (dependency) // ****************** + @Operation( + summary = "Get a list of dependency keys of all dependent entity objects for a " + + "specified source entity and bulk action.", + description = "Get a list of dependency keys of all dependent entity objects for a " + + "specified source entity and bulk action.\n " + + "This can be used to verify depended objects for a certain bulk action to " + + "give a report of affected objects beforehand.\n " + + "For example for a delete action of a certain object, this gives all objects " + + "that will also be deleted within the deletion of the source object", + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = { @Content(mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) }), + + parameters = { + @Parameter( + name = API.PARAM_MODEL_ID, + description = "The model identifier of the source entity object to geht the dependencies for.", + in = ParameterIn.PATH), + @Parameter( + name = API.PARAM_BULK_ACTION_TYPE, + description = "The bulk action type defining the type of action to get the dependencies for.\n" + + "This is the name of the enumeration "), + @Parameter( + name = API.PARAM_BULK_ACTION_ADD_INCLUDES, + description = "Indicates if the following 'includes' paramerer shall be processed or not.\n The default is false "), + @Parameter( + name = API.PARAM_BULK_ACTION_INCLUDES, + description = "A comma separated list of names of the EntityType enummeration that defines all entity types that shall be included in the result.") + }) @RequestMapping( path = API.MODEL_ID_VAR_PATH_SEGMENT + API.DEPENDENCY_PATH_SEGMENT, method = RequestMethod.GET, @@ -302,6 +334,16 @@ public abstract class EntityController { // * GET (single) // ****************** + @Operation( + summary = "Get a single entity by its modelId.", + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = { @Content(mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) }), + parameters = { + @Parameter( + name = API.PARAM_MODEL_ID, + description = "The model identifier of the entity object to get.", + in = ParameterIn.PATH) + }) @RequestMapping( path = API.MODEL_ID_VAR_PATH_SEGMENT, method = RequestMethod.GET, @@ -319,6 +361,15 @@ public abstract class EntityController { // * GET (list) // ****************** + @Operation( + summary = "Get a list of entity objects by a given list of model identifiers of entities.", + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = { @Content(mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) }), + parameters = { + @Parameter( + name = API.PARAM_MODEL_ID_LIST, + description = "Comma separated list of model identifiers.") + }) @RequestMapping( path = API.LIST_PATH_SEGMENT, method = RequestMethod.GET, @@ -340,12 +391,33 @@ public abstract class EntityController { // * POST (create) // ****************** + @Operation( + summary = "Create a new entity object of specifies type by using the given form parameter", + description = "This expects " + MediaType.APPLICATION_FORM_URLENCODED_VALUE + + " format for the form parameter" + + " and tries to create a new entity object from this form parameter, " + + "resulting in an error if there are missing" + + " or incorrect form paramter. The needed form paramter " + + + "can be verified within the specific entity object.", + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = { @Content(mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) }), + parameters = { + @Parameter( + name = "formParams", + description = "The from paramter value map that is been used to create a new entity object.", + in = ParameterIn.DEFAULT), + @Parameter( + name = API.PARAM_INSTITUTION_ID, + description = "The institution identifier of the request.\n" + + "Default is the institution identifier of the institution of the current user"), + }) @RequestMapping( method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public T create( - @RequestParam final MultiValueMap allRequestParams, + @RequestParam final MultiValueMap formParams, @RequestParam( name = API.PARAM_INSTITUTION_ID, required = true, @@ -355,7 +427,7 @@ public abstract class EntityController { // check write privilege for requested institution and concrete entityType this.checkWritePrivilege(institutionId); - final POSTMapper postMap = new POSTMapper(allRequestParams, request.getQueryString()) + final POSTMapper postMap = new POSTMapper(formParams, request.getQueryString()) .putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); final M requestModel = this.createNew(postMap); @@ -372,6 +444,14 @@ public abstract class EntityController { // * PUT (save) // **************** + @Operation( + summary = "Modifies an already existing entity object of the specific type.", + description = "This expects " + MediaType.APPLICATION_JSON_VALUE + + " format for the response data and verifies consistencies " + + "within the definition of the specific entity object type. " + + "Missing (NULL) parameter that are not mandatory will be ignored and the original value will not be affected", + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = { @Content(mediaType = MediaType.APPLICATION_JSON_VALUE) })) @RequestMapping( method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE, @@ -389,6 +469,25 @@ public abstract class EntityController { // * DELETE (hard-delete) // ************************ + @Operation( + summary = "Deletes a single entity (and all its dependencies) by its modelId.", + description = "To check or report what dependent object also would be deleted for a certain entity object, " + + + "please use the dependency endpoint to get a report of all dependend entity objects.", + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = { @Content(mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) }), + parameters = { + @Parameter( + name = API.PARAM_MODEL_ID, + description = "The model identifier of the entity object to get.", + in = ParameterIn.PATH), + @Parameter( + name = API.PARAM_BULK_ACTION_ADD_INCLUDES, + description = "Indicates if the following 'includes' paramerer shall be processed or not.\n The default is false "), + @Parameter( + name = API.PARAM_BULK_ACTION_INCLUDES, + description = "A comma separated list of names of the EntityType enummeration that defines all entity types that shall be included in the result.") + }) @RequestMapping( path = API.MODEL_ID_VAR_PATH_SEGMENT, method = RequestMethod.DELETE, @@ -411,6 +510,25 @@ public abstract class EntityController { // * DELETE ALL (hard-delete) // ************************** + @Operation( + summary = "Deletes all given entity (and all its dependencies) by a given list of model identifiers.", + description = "To check or report what dependent object also would be deleted for a certain entity object, " + + + "please use the dependency endpoint to get a report of all dependend entity objects.", + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = { @Content(mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) }), + parameters = { + @Parameter( + name = API.PARAM_MODEL_ID_LIST, + description = "The list of model identifiers of specific entity type to delete.", + in = ParameterIn.QUERY), + @Parameter( + name = API.PARAM_BULK_ACTION_ADD_INCLUDES, + description = "Indicates if the following 'includes' paramerer shall be processed or not.\n The default is false "), + @Parameter( + name = API.PARAM_BULK_ACTION_INCLUDES, + description = "A comma separated list of names of the EntityType enummeration that defines all entity types that shall be included in the result.") + }) @RequestMapping( method = RequestMethod.DELETE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java index 2302d637..ed98d2d2 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java @@ -52,10 +52,12 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientConnectionService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientNotificationService; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; @WebServiceProfile @RestController @RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.EXAM_MONITORING_ENDPOINT) +@SecurityRequirement(name = "oauth2") public class ExamMonitoringController { private static final Logger log = LoggerFactory.getLogger(ExamMonitoringController.class); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamProctoringController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamProctoringController.java index 1be45e90..26df46e8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamProctoringController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamProctoringController.java @@ -37,10 +37,12 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringRoomService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; @WebServiceProfile @RestController @RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.EXAM_PROCTORING_ENDPOINT) +@SecurityRequirement(name = "oauth2") public class ExamProctoringController { private static final Logger log = LoggerFactory.getLogger(ExamProctoringController.class); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InfoController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InfoController.java index eae1ca9f..73ab5e0e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InfoController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InfoController.java @@ -24,10 +24,12 @@ import ch.ethz.seb.sebserver.gbl.model.EntityName; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; @WebServiceProfile @RestController @RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.INFO_ENDPOINT) +@SecurityRequirement(name = "oauth2") public class InfoController { private final InstitutionDAO institutionDAO; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizController.java index 947d7fe3..ea84a216 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizController.java @@ -32,10 +32,12 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.Authorization import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; @WebServiceProfile @RestController @RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.QUIZ_DISCOVERY_ENDPOINT) +@SecurityRequirement(name = "oauth2") public class QuizController { private final int defaultPageSize;