more tests

This commit is contained in:
anhefti 2019-01-27 19:07:28 +01:00
parent 2dcba3a0da
commit eccbd47d39
11 changed files with 180 additions and 38 deletions

View file

@ -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"),

View file

@ -52,4 +52,11 @@ public class EntityProcessingReport {
}
@Override
public String toString() {
return "EntityProcessingReport [source=" + this.source + ", dependencies=" + this.dependencies + ", errors="
+ this.errors
+ "]";
}
}

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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)

View file

@ -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;

View file

@ -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())