more tests
This commit is contained in:
parent
2dcba3a0da
commit
eccbd47d39
11 changed files with 180 additions and 38 deletions
|
@ -30,6 +30,7 @@ public class APIMessage implements Serializable {
|
|||
GENERIC("0", HttpStatus.INTERNAL_SERVER_ERROR, "Generic error message"),
|
||||
UNAUTHORIZED("1000", HttpStatus.UNAUTHORIZED, "UNAUTHORIZED"),
|
||||
FORBIDDEN("1001", HttpStatus.FORBIDDEN, "FORBIDDEN"),
|
||||
RESOURCE_NOT_FOUND("1002", HttpStatus.NOT_FOUND, "resource not found"),
|
||||
ILLEGAL_API_ARGUMENT("1010", HttpStatus.BAD_REQUEST, "Illegal API request argument"),
|
||||
UNEXPECTED("1100", HttpStatus.INTERNAL_SERVER_ERROR, "Unexpected intenral server-side error"),
|
||||
FIELD_VALIDATION("1200", HttpStatus.BAD_REQUEST, "Field validation error"),
|
||||
|
|
|
@ -52,4 +52,11 @@ public class EntityProcessingReport {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EntityProcessingReport [source=" + this.source + ", dependencies=" + this.dependencies + ", errors="
|
||||
+ this.errors
|
||||
+ "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
|
|||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityType;
|
||||
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
|
@ -18,19 +19,16 @@ public final class ResourceNotFoundException extends RuntimeException {
|
|||
|
||||
private static final long serialVersionUID = 8319235723086949618L;
|
||||
|
||||
public final EntityType entityType;
|
||||
public final String entityId;
|
||||
public final EntityKey entityKey;
|
||||
|
||||
public ResourceNotFoundException(final EntityType entityType, final String entityId) {
|
||||
super("Resource " + entityType + " with ID: " + entityId + " not found");
|
||||
this.entityType = entityType;
|
||||
this.entityId = entityId;
|
||||
public ResourceNotFoundException(final EntityType entityType, final String modelId) {
|
||||
super("Resource " + entityType + " with ID: " + modelId + " not found");
|
||||
this.entityKey = new EntityKey(modelId, entityType);
|
||||
}
|
||||
|
||||
public ResourceNotFoundException(final EntityType entityType, final String entityId, final Throwable cause) {
|
||||
super("Resource " + entityType + " with ID: " + entityId + " not found", cause);
|
||||
this.entityType = entityType;
|
||||
this.entityId = entityId;
|
||||
public ResourceNotFoundException(final EntityType entityType, final String modelId, final Throwable cause) {
|
||||
super("Resource " + entityType + " with ID: " + modelId + " not found", cause);
|
||||
this.entityKey = new EntityKey(modelId, entityType);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -159,8 +159,10 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
@Transactional
|
||||
public Result<Exam> save(final String modelId, final Exam exam) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final Long pk = Long.parseLong(modelId);
|
||||
final ExamRecord examRecord = new ExamRecord(
|
||||
exam.id,
|
||||
pk,
|
||||
null, null, null, null,
|
||||
(exam.supporter != null)
|
||||
? StringUtils.join(exam.supporter, Constants.LIST_SEPARATOR_CHAR)
|
||||
|
@ -170,7 +172,7 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
BooleanUtils.toIntegerObject(exam.active));
|
||||
|
||||
this.examRecordMapper.updateByPrimaryKeySelective(examRecord);
|
||||
return this.examRecordMapper.selectByPrimaryKey(exam.id);
|
||||
return this.examRecordMapper.selectByPrimaryKey(pk);
|
||||
})
|
||||
.flatMap(this::toDomainModel)
|
||||
.onErrorDo(TransactionHandler::rollback);
|
||||
|
|
|
@ -146,8 +146,9 @@ public class IndicatorDAOImpl implements IndicatorDAO {
|
|||
public Result<Indicator> save(final String modelId, final Indicator modified) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final Long pk = Long.parseLong(modelId);
|
||||
final IndicatorRecord newRecord = new IndicatorRecord(
|
||||
modified.id,
|
||||
pk,
|
||||
null,
|
||||
modified.type.name(),
|
||||
modified.name,
|
||||
|
@ -157,7 +158,7 @@ public class IndicatorDAOImpl implements IndicatorDAO {
|
|||
|
||||
// update also the thresholds
|
||||
this.thresholdRecordMapper.deleteByExample()
|
||||
.where(ThresholdRecordDynamicSqlSupport.indicatorId, isEqualTo(modified.id))
|
||||
.where(ThresholdRecordDynamicSqlSupport.indicatorId, isEqualTo(pk))
|
||||
.build()
|
||||
.execute();
|
||||
|
||||
|
@ -165,12 +166,12 @@ public class IndicatorDAOImpl implements IndicatorDAO {
|
|||
.stream()
|
||||
.map(threshold -> new ThresholdRecord(
|
||||
null,
|
||||
modified.id,
|
||||
pk,
|
||||
new BigDecimal(threshold.value),
|
||||
threshold.color))
|
||||
.forEach(this.thresholdRecordMapper::insert);
|
||||
|
||||
return this.indicatorRecordMapper.selectByPrimaryKey(modified.id);
|
||||
return this.indicatorRecordMapper.selectByPrimaryKey(pk);
|
||||
})
|
||||
.flatMap(this::toDomainModel)
|
||||
.onErrorDo(TransactionHandler::rollback);
|
||||
|
|
|
@ -131,15 +131,16 @@ public class InstitutionDAOImpl implements InstitutionDAO {
|
|||
public Result<Institution> save(final String modelId, final Institution institution) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final Long pk = Long.parseLong(modelId);
|
||||
final InstitutionRecord newRecord = new InstitutionRecord(
|
||||
institution.id,
|
||||
pk,
|
||||
institution.name,
|
||||
institution.urlSuffix,
|
||||
null,
|
||||
institution.logoImage);
|
||||
|
||||
this.institutionRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
return this.institutionRecordMapper.selectByPrimaryKey(institution.id);
|
||||
return this.institutionRecordMapper.selectByPrimaryKey(pk);
|
||||
})
|
||||
.flatMap(InstitutionDAOImpl::toDomainModel)
|
||||
.onErrorDo(TransactionHandler::rollback);
|
||||
|
|
|
@ -124,8 +124,9 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
|
|||
public Result<LmsSetup> save(final String modelId, final LmsSetup lmsSetup) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final Long pk = Long.parseLong(modelId);
|
||||
final LmsSetupRecord newRecord = new LmsSetupRecord(
|
||||
lmsSetup.id,
|
||||
pk,
|
||||
lmsSetup.institutionId,
|
||||
lmsSetup.name,
|
||||
(lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null,
|
||||
|
@ -138,7 +139,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
|
|||
null);
|
||||
|
||||
this.lmsSetupRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
return this.lmsSetupRecordMapper.selectByPrimaryKey(lmsSetup.id);
|
||||
return this.lmsSetupRecordMapper.selectByPrimaryKey(pk);
|
||||
})
|
||||
.flatMap(LmsSetupDAOImpl::toDomainModel)
|
||||
.onErrorDo(TransactionHandler::rollback);
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
|
|||
import ch.ethz.seb.sebserver.gbl.model.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.model.APIMessage.APIMessageException;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PermissionDeniedException;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationException;
|
||||
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
|
@ -79,6 +80,15 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
|
|||
return new ResponseEntity<>(valErrors, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ResourceNotFoundException.class)
|
||||
public ResponseEntity<Object> handleResourceNotFoundException(
|
||||
final ResourceNotFoundException ex,
|
||||
final WebRequest request) {
|
||||
|
||||
return APIMessage.ErrorMessage.RESOURCE_NOT_FOUND
|
||||
.createErrorResponse(ex.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(UsernameNotFoundException.class)
|
||||
public ResponseEntity<Object> handleUserNotFound(
|
||||
final UsernameNotFoundException ex,
|
||||
|
|
|
@ -102,7 +102,7 @@ public abstract class ActivatableEntityController<T extends GrantEntity, M exten
|
|||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = "/{id}/activate",
|
||||
path = "/{id}/active",
|
||||
method = RequestMethod.POST,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
|
@ -112,7 +112,7 @@ public abstract class ActivatableEntityController<T extends GrantEntity, M exten
|
|||
}
|
||||
|
||||
@RequestMapping(
|
||||
value = "/{id}/deactivate",
|
||||
value = "/{id}/inactive",
|
||||
method = RequestMethod.POST,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.springframework.test.context.jdbc.Sql;
|
|||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
|
||||
import ch.ethz.seb.sebserver.webservice.weblayer.api.RestAPI;
|
||||
|
@ -78,6 +79,7 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
|
|||
assertTrue(institutions.content.size() == 1);
|
||||
assertContainsInstitution("Institution1", institutions.content);
|
||||
|
||||
// Institutional admin tries to get data from other institution
|
||||
final APIMessage errorMessage = new RestAPITestHelper()
|
||||
.withAccessToken(getAdminInstitution1Access())
|
||||
.withPath(RestAPI.ENDPOINT_INSTITUTION)
|
||||
|
@ -183,18 +185,137 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
|
|||
assertEquals("newer institution", institution.name);
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void createActivateModifyDeactivateAndDeleteInstitution() throws Exception {
|
||||
// final Institution institution = new RestAPITestHelper()
|
||||
// .withAccessToken(getSebAdminAccess())
|
||||
// .withPath(RestAPI.ENDPOINT_INSTITUTION + "/create")
|
||||
// .withMethod(HttpMethod.PUT)
|
||||
// .withBodyJson(new Institution(null, ))
|
||||
// .withExpectedStatus(HttpStatus.OK)
|
||||
//
|
||||
// .getAsObject(new TypeReference<Institution>() {
|
||||
// });
|
||||
// }
|
||||
@Test
|
||||
public void createActivateModifyDeactivateAndDeleteInstitution() throws Exception {
|
||||
// create new institution with seb-admin
|
||||
final String sebAdminAccess = getSebAdminAccess();
|
||||
Institution institution = new RestAPITestHelper()
|
||||
.withAccessToken(sebAdminAccess)
|
||||
.withPath(RestAPI.ENDPOINT_INSTITUTION)
|
||||
.withMethod(HttpMethod.POST)
|
||||
.withAttribute("name", "testInstitution")
|
||||
.withExpectedStatus(HttpStatus.OK)
|
||||
.getAsObject(new TypeReference<Institution>() {
|
||||
});
|
||||
|
||||
assertNotNull(institution);
|
||||
assertEquals("testInstitution", institution.name);
|
||||
assertFalse(institution.active);
|
||||
|
||||
// get
|
||||
institution = new RestAPITestHelper()
|
||||
.withAccessToken(sebAdminAccess)
|
||||
.withPath(RestAPI.ENDPOINT_INSTITUTION).withPath("/").withPath(String.valueOf(institution.id))
|
||||
.withMethod(HttpMethod.GET)
|
||||
.withExpectedStatus(HttpStatus.OK)
|
||||
.getAsObject(new TypeReference<Institution>() {
|
||||
});
|
||||
|
||||
assertNotNull(institution);
|
||||
assertEquals("testInstitution", institution.name);
|
||||
assertEquals(null, institution.urlSuffix);
|
||||
assertFalse(institution.active);
|
||||
|
||||
// modify
|
||||
institution = new RestAPITestHelper()
|
||||
.withAccessToken(sebAdminAccess)
|
||||
.withPath(RestAPI.ENDPOINT_INSTITUTION).withPath("/").withPath(String.valueOf(institution.id))
|
||||
.withMethod(HttpMethod.PUT)
|
||||
.withBodyJson(new Institution(null, "testInstitution", "testSuffix", null, null))
|
||||
.withExpectedStatus(HttpStatus.OK)
|
||||
.getAsObject(new TypeReference<Institution>() {
|
||||
});
|
||||
|
||||
assertNotNull(institution);
|
||||
assertEquals("testInstitution", institution.name);
|
||||
assertEquals("testSuffix", institution.urlSuffix);
|
||||
assertFalse(institution.active);
|
||||
|
||||
// activate
|
||||
EntityProcessingReport report = new RestAPITestHelper()
|
||||
.withAccessToken(sebAdminAccess)
|
||||
.withPath(RestAPI.ENDPOINT_INSTITUTION)
|
||||
.withPath("/").withPath(String.valueOf(institution.id)).withPath("/active")
|
||||
.withMethod(HttpMethod.POST)
|
||||
.withExpectedStatus(HttpStatus.OK)
|
||||
.getAsObject(new TypeReference<EntityProcessingReport>() {
|
||||
});
|
||||
|
||||
assertNotNull(report);
|
||||
assertEquals("EntityProcessingReport "
|
||||
+ "[source=[EntityKey [modelId=4, entityType=INSTITUTION]], "
|
||||
+ "dependencies=[], "
|
||||
+ "errors=[]]",
|
||||
report.toString());
|
||||
// get
|
||||
institution = new RestAPITestHelper()
|
||||
.withAccessToken(sebAdminAccess)
|
||||
.withPath(RestAPI.ENDPOINT_INSTITUTION).withPath("/").withPath(String.valueOf(institution.id))
|
||||
.withMethod(HttpMethod.GET)
|
||||
.withExpectedStatus(HttpStatus.OK)
|
||||
.getAsObject(new TypeReference<Institution>() {
|
||||
});
|
||||
|
||||
assertNotNull(institution);
|
||||
assertTrue(institution.active);
|
||||
|
||||
// deactivate
|
||||
report = new RestAPITestHelper()
|
||||
.withAccessToken(sebAdminAccess)
|
||||
.withPath(RestAPI.ENDPOINT_INSTITUTION)
|
||||
.withPath("/").withPath(String.valueOf(institution.id)).withPath("/inactive")
|
||||
.withMethod(HttpMethod.POST)
|
||||
.withExpectedStatus(HttpStatus.OK)
|
||||
.getAsObject(new TypeReference<EntityProcessingReport>() {
|
||||
});
|
||||
|
||||
assertNotNull(report);
|
||||
assertEquals("EntityProcessingReport "
|
||||
+ "[source=[EntityKey [modelId=4, entityType=INSTITUTION]], "
|
||||
+ "dependencies=[], "
|
||||
+ "errors=[]]",
|
||||
report.toString());
|
||||
// get
|
||||
institution = new RestAPITestHelper()
|
||||
.withAccessToken(sebAdminAccess)
|
||||
.withPath(RestAPI.ENDPOINT_INSTITUTION).withPath("/").withPath(String.valueOf(institution.id))
|
||||
.withMethod(HttpMethod.GET)
|
||||
.withExpectedStatus(HttpStatus.OK)
|
||||
.getAsObject(new TypeReference<Institution>() {
|
||||
});
|
||||
|
||||
assertNotNull(institution);
|
||||
assertFalse(institution.active);
|
||||
|
||||
// delete
|
||||
report = new RestAPITestHelper()
|
||||
.withAccessToken(sebAdminAccess)
|
||||
.withPath(RestAPI.ENDPOINT_INSTITUTION)
|
||||
.withPath("/").withPath(String.valueOf(institution.id))
|
||||
.withMethod(HttpMethod.DELETE)
|
||||
.withExpectedStatus(HttpStatus.OK)
|
||||
.getAsObject(new TypeReference<EntityProcessingReport>() {
|
||||
});
|
||||
|
||||
assertNotNull(report);
|
||||
assertEquals("EntityProcessingReport "
|
||||
+ "[source=[EntityKey [modelId=4, entityType=INSTITUTION]], "
|
||||
+ "dependencies=[], "
|
||||
+ "errors=[]]",
|
||||
report.toString());
|
||||
|
||||
// get
|
||||
final APIMessage error = new RestAPITestHelper()
|
||||
.withAccessToken(sebAdminAccess)
|
||||
.withPath(RestAPI.ENDPOINT_INSTITUTION).withPath("/").withPath(String.valueOf(institution.id))
|
||||
.withMethod(HttpMethod.GET)
|
||||
.withExpectedStatus(HttpStatus.NOT_FOUND)
|
||||
.getAsObject(new TypeReference<APIMessage>() {
|
||||
});
|
||||
|
||||
assertNotNull(error);
|
||||
assertEquals("Resource INSTITUTION with ID: 4 not found", error.details);
|
||||
}
|
||||
|
||||
static void assertContainsInstitution(final String name, final Collection<Institution> institutions) {
|
||||
assert institutions != null;
|
||||
|
|
|
@ -843,7 +843,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
final String timeNow = DateTime.now(DateTimeZone.UTC).toString(Constants.DATE_TIME_PATTERN_UTC_NO_MILLIS);
|
||||
// only a SEB Administrator or an Institutional administrator should be able to deactivate a user-account
|
||||
final String examAdminToken = getExamAdmin1();
|
||||
this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4/deactivate")
|
||||
this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4/inactive")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.header("Authorization", "Bearer " + examAdminToken))
|
||||
.andExpect(status().isForbidden());
|
||||
|
@ -851,7 +851,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
// With SEB Administrator it should work
|
||||
final String sebAdminToken = getSebAdminAccess();
|
||||
final EntityProcessingReport report = this.jsonMapper.readValue(
|
||||
this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4/deactivate")
|
||||
this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4/inactive")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.header("Authorization", "Bearer " + sebAdminToken))
|
||||
.andExpect(status().isOk())
|
||||
|
@ -903,7 +903,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
final String timeNow = DateTime.now(DateTimeZone.UTC).toString(Constants.DATE_TIME_PATTERN_UTC_NO_MILLIS);
|
||||
// only a SEB Administrator or an Institutional administrator should be able to deactivate a user-account
|
||||
final String examAdminToken = getExamAdmin1();
|
||||
this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user6/activate")
|
||||
this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user6/active")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.header("Authorization", "Bearer " + examAdminToken))
|
||||
.andExpect(status().isForbidden());
|
||||
|
@ -911,7 +911,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
// With SEB Administrator it should work
|
||||
final String sebAdminToken = getSebAdminAccess();
|
||||
final EntityProcessingReport report = this.jsonMapper.readValue(
|
||||
this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user6/activate")
|
||||
this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user6/active")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.header("Authorization", "Bearer " + sebAdminToken))
|
||||
.andExpect(status().isOk())
|
||||
|
|
Loading…
Add table
Reference in a new issue