getOrganizationsOfUser(
+ @RequestParam("user") String idOrUsername,
+ Pageable pageable
+ ) {
+ Long id = Longs.tryParse(idOrUsername);
+ User user = ofNullable((id != null)
+ ? userRepository.findOne(id)
+ : userRepository.findByUsername(idOrUsername))
+ .orElseThrow(ResourceNotFoundException::new);
+
+ return memberRepository.findByUser(user, pageable)
+ .stream()
+ .map(Member::getOrganization)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * GET /organizations/{idOrName}
+ *
+ * Доступен всем пользователям.
+ * Возвращает организацию с указанным id или name.
+ *
+ * Возможные коды состояний:
+ * 200 OK
+ * 404 Not Found
+ */
+ @GetMapping("/{idOrName:.+}")
+ public Organization getOrganization(
+ @PathVariable String idOrName
+ ) {
+ Organization organization = findOrganizationByIdOrName(idOrName);
+ if (organization == null) {
+ throw new ResourceNotFoundException();
+ }
+
+ return organization;
+ }
+
+ /**
+ * DELETE /organizations/{id}
+ *
+ * Доступен администраторам или создателю организации.
+ * Удаляет организацию с указанным id.
+ *
+ * Возможные коды состояний:
+ * 204 No Content
+ * 401 Unauthorized
+ * 403 Forbidden
+ * 404 Not Found
+ */
+ @PreAuthorize("isAuthenticated()")
+ @DeleteMapping("/{organizationId}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void deleteOrganization(
+ @PathVariable Long organizationId,
+ Authentication auth
+ ) {
+ Organization organization = organizationRepository
+ .findOne(organizationId);
+ if (organization == null) {
+ throw new ResourceNotFoundException();
+ }
+
+ Member authMember = memberRepository
+ .findByOrganizationAndUser(organization,
+ userRepository.findByEmail(auth.getName()));
+
+ if ((auth.getAuthorities().contains(UserAuthority.ADMIN))
+ || (authMember != null) && (authMember.getStatus().equals(MemberStatus.CREATOR))) {
+ organizationRepository.delete(organization);
+ } else {
+ throw new ForbiddenException();
+ }
+ }
+
+ /**
+ * POST /organizations
+ * Тело запроса:
+ * {
+ * "name": "название",
+ * "fillName": "полное название" (не обязательно)
+ * }
+ *
+ * Метод доступен всем авторизованным пользователям.
+ * Создает новую организацию с указанными данными. Устаналивает пользователя, выполнившего запрос, создателем
+ * организации. Устаналивает заголовок Location и возвращает созданную организацию.
+ *
+ * Возможные коды состояний:
+ * 201 Created
+ * 400 Bad Request
+ * 401 Unauthorized
+ */
+ @PreAuthorize("isAuthenticated()")
+ @PostMapping
+ @ResponseStatus(HttpStatus.CREATED)
+ public Organization createOrganization(
+ @RequestBody Organization organization,
+ HttpServletResponse response,
+ Authentication auth
+ ) {
+ if (organizationRepository.findByName(organization.getName()) != null) {
+ throw new BadRequestException();
+ }
+
+ organization.setCreationDate(LocalDate.now());
+ organizationRepository.saveAndFlush(organization);
+
+ Member creator = new Member();
+ creator.setAdmissionDate(LocalDate.now());
+ creator.setOrganization(organization);
+ creator.setStatus(MemberStatus.CREATOR);
+ creator.setUser(userRepository.findByEmail(auth.getName()));
+ memberRepository.save(creator);
+ organization.getMembers().add(creator);
+
+ response.setHeader(HttpHeaders.LOCATION,
+ "/organizations/" + organization.getId());
+ return organization;
+ }
+
+ /**
+ * PATCH /organizations/{id}
+ * ?[name(string)]&[fullName(string)]
+ *
+ * Доступен администраторам, создателю организации и владельцам организации.
+ * Изменяет name и fullName организации, если соответсвующие параметры указаны.
+ *
+ * Возможные коды состояний:
+ * 204 No Content
+ * 401 Unauthorized
+ * 403 Forbidden
+ * 404 Not Found
+ */
+ @PreAuthorize("isAuthenticated()")
+ @PatchMapping("/{id}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void patchOrganization(
+ @PathVariable Long id,
+ @RequestParam(required = false) String name,
+ @RequestParam(required = false) String fullName,
+ Authentication auth
+ ) {
+ Organization organization = organizationRepository.findOne(id);
+ if (organization == null) {
+ throw new ResourceNotFoundException();
+ }
+
+ Member authMember = memberRepository.findByOrganizationAndUser(organization,
+ userRepository.findByEmail(auth.getName()));
+
+ if ((auth.getAuthorities().contains(UserAuthority.ADMIN))
+ || (authMember != null) && (authMember.getStatus().equals(MemberStatus.CREATOR))
+ || (authMember != null) && (authMember.getStatus().equals(MemberStatus.OWNER))) {
+
+ if (name != null) {
+ organization.setName(name);
+ }
+ if (fullName != null) {
+ organization.setFullName(fullName);
+ }
+ organizationRepository.save(organization);
+
+ } else {
+ throw new ForbiddenException();
+ }
+ }
+
+ /**
+ * GET /organizations/{organizationId}/members
+ * ?[pageNumber(number)]&[pageSize(number)]&[offset(number)]&[sort(string)]
+ *
+ * Доступен всем пользователям.
+ * Возвращает список всех участников организации (или не всех, при указании параметров в запросе).
+ *
+ * Возможные коды состояний:
+ * 200 OK
+ * 404 Not Found
+ */
+ @GetMapping("/{organizationIdOrName}/members")
+ public List getOrganizationMembers(
+ @PathVariable String organizationIdOrName,
+ Pageable pageable
+ ) {
+ Organization organization = ofNullable(
+ findOrganizationByIdOrName(organizationIdOrName))
+ .orElseThrow(ResourceNotFoundException::new);
+
+ return memberRepository
+ .findAllByOrganization(organization, pageable)
+ .getContent();
+ }
+
+ /**
+ * GET /organizations/{organizationId}/members/{memberId}
+ *
+ *
+ * Доступен администраторам, создателю и владельцам организации.
+ * Возвращает участника memberId организации organizationId.
+ *
+ * Возможные коды состояний:
+ * 200 OK
+ * 404 Not Found
+ */
+ @GetMapping("/{organizationIdOrName}/members/{memberId}")
+ public Member getOrganizationMember(
+ @PathVariable String organizationIdOrName,
+ @PathVariable Long memberId,
+ Authentication auth
+ ) {
+
+ Organization organization = ofNullable(
+ findOrganizationByIdOrName(organizationIdOrName))
+ .orElseThrow(ResourceNotFoundException::new);
+
+ return ofNullable(memberRepository
+ .findByOrganizationAndId(organization, memberId))
+ .orElseThrow(ResourceNotFoundException::new);
+ }
+
+ /**
+ * POST /organizations/{organizationId}/members
+ * Тело запроса:
+ * {
+ * "status": "статус",
+ * "userId": 123
+ * }
+ *
+ * Доступен только администраторам.
+ * Добавляет в организацию участника с полученными данными. Нельзя добавить участника со статусом создателя, так
+ * как создатель может быть только один.
+ *
+ * Возможные коды состояний:
+ * 201 Created
+ * 400 Bad Request
+ * 401 Unauthorized
+ * 403 Forbidden
+ * 404 Not Found
+ */
+ // todo: приглашение нового участника
+ @PreAuthorize("hasRole('ADMIN')")
+ @PostMapping("/{organizationId}/members")
+ @ResponseStatus(HttpStatus.CREATED)
+ public Member addMember(
+ @PathVariable Long organizationId,
+ @RequestBody Member member,
+ HttpServletResponse response
+ ) {
+ Organization organization = ofNullable(
+ organizationRepository.findOne(organizationId))
+ .orElseThrow(ResourceNotFoundException::new);
+
+ if (memberRepository.findByOrganizationAndUser(organization,
+ member.getUser()) != null) {
+ throw new BadRequestException();
+ }
+
+ member.setAdmissionDate(LocalDate.now());
+ member.setOrganization(organization);
+ if (member.getStatus().equals(MemberStatus.CREATOR)) {
+ // нельзя добавить нового создателя организации
+ member.setStatus(MemberStatus.OWNER);
+ }
+ memberRepository.save(member);
+
+ response.setHeader(HttpHeaders.LOCATION,
+ String.format("/organizations/%d/members/%d",
+ organizationId, member.getId()));
+ return member;
+ }
+
+ /**
+ * PATCH /organizations/{organizationId}/members/{memberId}
+ * ?status(string)
+ *
+ * Доступен администраторам, создателю и владельцам организации.
+ * Изменяет статус участника. Нельзя изменить статус создателя и статус другого участника на статус создателя.
+ *
+ * Возможные коды состояний:
+ * 204 No Content
+ * 401 Unauthorized
+ * 403 Forbidden
+ * 404 Not Found
+ */
+ @PreAuthorize("isAuthenticated()")
+ @PatchMapping("/{organizationId}/members/{memberId}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void patchMember(
+ @PathVariable Long organizationId,
+ @PathVariable Long memberId,
+ @RequestParam("status") MemberStatus newStatus,
+ Authentication auth
+ ) {
+ Organization organization = ofNullable(
+ organizationRepository.findOne(organizationId))
+ .orElseThrow(ResourceNotFoundException::new);
+
+ Member member = ofNullable(memberRepository
+ .findByOrganizationAndId(organization, memberId))
+ .orElseThrow(ResourceNotFoundException::new);
+
+ Member authMember = memberRepository
+ .findByOrganizationAndUser(organization,
+ userRepository.findByEmail(auth.getName()));
+
+ if ((auth.getAuthorities().contains(UserAuthority.ADMIN))
+ || (authMember != null) && (authMember.getStatus().equals(MemberStatus.CREATOR))
+ || (authMember != null) && (authMember.getStatus().equals(MemberStatus.OWNER))) {
+
+ if (!member.getStatus().equals(MemberStatus.CREATOR)
+ && !newStatus.equals(MemberStatus.CREATOR)) {
+
+ member.setStatus(newStatus);
+ memberRepository.save(member);
+ return;
+ }
+ }
+ throw new ForbiddenException();
+ }
+
+ /**
+ * DELETE /organizations/{organizationId}/members/{memberId}
+ *
+ * Доступен администраторам, создателю и владельцам организации.
+ * Удаляет участника memberId из организации organizationId.
+ *
+ * Возможные коды состояний:
+ * 204 No Content
+ * 401 Unauthorized
+ * 403 Forbidden
+ * 404 Not Found
+ */
+ @PreAuthorize("isAuthenticated()")
+ @DeleteMapping("/{organizationId}/members/{memberId}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void deleteMember(
+ @PathVariable Long organizationId,
+ @PathVariable Long memberId,
+ Authentication auth
+ ) {
+ Organization organization = ofNullable(
+ organizationRepository.findOne(organizationId))
+ .orElseThrow(ResourceNotFoundException::new);
+
+ Member member = ofNullable(memberRepository
+ .findByOrganizationAndId(organization, memberId))
+ .orElseThrow(ResourceNotFoundException::new);
+
+ Member authMember = memberRepository
+ .findByOrganizationAndUser(organization,
+ userRepository.findByEmail(auth.getName()));
+
+ if (auth.getAuthorities().contains(UserAuthority.ADMIN)) {
+ memberRepository.delete(member);
+ return;
+
+ } else if ((authMember != null) && (authMember.getStatus().equals(MemberStatus.CREATOR))
+ || (authMember != null) && (authMember.getStatus().equals(MemberStatus.OWNER))) {
+
+ if (!member.getStatus().equals(MemberStatus.CREATOR)) {
+ memberRepository.delete(member);
+ return;
+ }
+ }
+ throw new ForbiddenException();
+ }
+}
diff --git a/src/main/java/org/teapot/backend/controller/UserController.java b/src/main/java/org/teapot/backend/controller/user/UserController.java
similarity index 98%
rename from src/main/java/org/teapot/backend/controller/UserController.java
rename to src/main/java/org/teapot/backend/controller/user/UserController.java
index 536963f..1971b3c 100644
--- a/src/main/java/org/teapot/backend/controller/UserController.java
+++ b/src/main/java/org/teapot/backend/controller/user/UserController.java
@@ -1,4 +1,4 @@
-package org.teapot.backend.controller;
+package org.teapot.backend.controller.user;
import com.google.common.primitives.Longs;
import org.springframework.beans.factory.annotation.Autowired;
@@ -13,14 +13,13 @@
import org.teapot.backend.controller.exception.BadRequestException;
import org.teapot.backend.controller.exception.ForbiddenException;
import org.teapot.backend.controller.exception.ResourceNotFoundException;
-import org.teapot.backend.model.User;
-import org.teapot.backend.model.UserAuthority;
-import org.teapot.backend.repository.UserRepository;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.model.user.UserAuthority;
+import org.teapot.backend.repository.user.UserRepository;
import org.teapot.backend.util.VerificationMailSender;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
-import java.time.LocalDateTime;
import java.util.List;
@@ -173,7 +172,7 @@ public User registerUser(@RequestBody User user,
throw new BadRequestException();
}
- user.setRegistrationDate(LocalDateTime.now());
+ user.setRegistrationDate(LocalDate.now());
user.setPassword(passwordEncoder.encode(user.getPassword()));
if (auth == null) {
diff --git a/src/main/java/org/teapot/backend/model/organization/Member.java b/src/main/java/org/teapot/backend/model/organization/Member.java
new file mode 100644
index 0000000..58e538f
--- /dev/null
+++ b/src/main/java/org/teapot/backend/model/organization/Member.java
@@ -0,0 +1,92 @@
+package org.teapot.backend.model.organization;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.util.deser.MemberDeserializer;
+import org.teapot.backend.util.ser.MemberSerializer;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.time.LocalDate;
+
+@Entity
+@Table(name = "organization_member")
+@JsonSerialize(using = MemberSerializer.class)
+@JsonDeserialize(using = MemberDeserializer.class)
+public class Member implements Serializable {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @ManyToOne(optional = false)
+ @OnDelete(action = OnDeleteAction.CASCADE)
+ private User user;
+
+ @Enumerated
+ private MemberStatus status;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ private Organization organization;
+
+ @Column(name = "admission_date")
+ private LocalDate admissionDate;
+
+ public Member() {
+ }
+
+ public Member(Long id,
+ User user,
+ MemberStatus status,
+ Organization organization,
+ LocalDate admissionDate) {
+ this.id = id;
+ this.user = user;
+ this.status = status;
+ this.organization = organization;
+ this.admissionDate = admissionDate;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+ public MemberStatus getStatus() {
+ return status;
+ }
+
+ public void setStatus(MemberStatus status) {
+ this.status = status;
+ }
+
+ public Organization getOrganization() {
+ return organization;
+ }
+
+ public void setOrganization(Organization organization) {
+ this.organization = organization;
+ }
+
+ public LocalDate getAdmissionDate() {
+ return admissionDate;
+ }
+
+ public void setAdmissionDate(LocalDate admissionDate) {
+ this.admissionDate = admissionDate;
+ }
+}
diff --git a/src/main/java/org/teapot/backend/model/organization/MemberStatus.java b/src/main/java/org/teapot/backend/model/organization/MemberStatus.java
new file mode 100644
index 0000000..dcdfb87
--- /dev/null
+++ b/src/main/java/org/teapot/backend/model/organization/MemberStatus.java
@@ -0,0 +1,8 @@
+package org.teapot.backend.model.organization;
+
+public enum MemberStatus {
+ CREATOR,
+ OWNER,
+ WORKER,
+ APPLICANT;
+}
diff --git a/src/main/java/org/teapot/backend/model/organization/Organization.java b/src/main/java/org/teapot/backend/model/organization/Organization.java
new file mode 100644
index 0000000..c6e7549
--- /dev/null
+++ b/src/main/java/org/teapot/backend/model/organization/Organization.java
@@ -0,0 +1,115 @@
+package org.teapot.backend.model.organization;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import org.teapot.backend.util.ser.OrganizationSerializer;
+
+import javax.persistence.*;
+import java.time.LocalDate;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+@Entity
+@Table(name = "organization")
+@JsonSerialize(using = OrganizationSerializer.class)
+public class Organization {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @Column(unique = true, nullable = false)
+ private String name;
+
+ @Column(name = "full_name")
+ private String fullName;
+
+ @Column(name = "creation_date")
+ private LocalDate creationDate;
+
+ @OneToMany(mappedBy = "organization", fetch = FetchType.LAZY,
+ cascade = CascadeType.ALL, orphanRemoval = true)
+ private Set members = new HashSet<>();
+
+ public Organization() {
+ }
+
+ public Organization(Long id,
+ String name,
+ String fullName,
+ LocalDate creationDate,
+ Set members) {
+ this.id = id;
+ this.name = name;
+ this.fullName = fullName;
+ this.creationDate = creationDate;
+ this.members = members;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String fullName) {
+ this.fullName = fullName;
+ }
+
+ public LocalDate getCreationDate() {
+ return creationDate;
+ }
+
+ public void setCreationDate(LocalDate creationDate) {
+ this.creationDate = creationDate;
+ }
+
+ public Set getMembers() {
+ return members;
+ }
+
+ public void setMembers(Set members) {
+ this.members = members;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ id,
+ name,
+ fullName,
+ creationDate,
+ members
+ );
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final Organization other = (Organization) obj;
+ return Objects.equals(this.id, other.id)
+ && Objects.equals(this.name, other.name)
+ && Objects.equals(this.fullName, other.fullName)
+ && Objects.equals(this.creationDate, other.creationDate)
+ && Objects.equals(this.members, other.members);
+ }
+}
diff --git a/src/main/java/org/teapot/backend/model/User.java b/src/main/java/org/teapot/backend/model/user/User.java
similarity index 74%
rename from src/main/java/org/teapot/backend/model/User.java
rename to src/main/java/org/teapot/backend/model/user/User.java
index 732fed8..4a084af 100644
--- a/src/main/java/org/teapot/backend/model/User.java
+++ b/src/main/java/org/teapot/backend/model/user/User.java
@@ -1,15 +1,17 @@
-package org.teapot.backend.model;
+package org.teapot.backend.model.user;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import org.teapot.backend.util.ser.UserSerializer;
import javax.persistence.*;
import java.time.LocalDate;
-import java.time.LocalDateTime;
import java.util.Objects;
@Entity
@Table(name = "user")
+@JsonSerialize(using = UserSerializer.class)
public class User {
@Id
@@ -41,19 +43,46 @@ public class User {
private UserAuthority authority = UserAuthority.USER;
@Column(name = "registration_date")
- private LocalDateTime registrationDate;
+ private LocalDate registrationDate;
private LocalDate birthday;
private String description;
- @JsonIgnore
@OneToOne(mappedBy = "user", fetch = FetchType.LAZY, orphanRemoval = true)
private VerificationToken verificationToken;
public User() {
}
+ public User(Long id,
+ String username,
+ String email,
+ String password,
+ Boolean isAvailable,
+ Boolean isActivated,
+ String firstName,
+ String lastName,
+ UserAuthority authority,
+ LocalDate registrationDate,
+ LocalDate birthday,
+ String description,
+ VerificationToken verificationToken) {
+ this.id = id;
+ this.username = username;
+ this.email = email;
+ this.password = password;
+ this.isAvailable = isAvailable;
+ this.isActivated = isActivated;
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.authority = authority;
+ this.registrationDate = registrationDate;
+ this.birthday = birthday;
+ this.description = description;
+ this.verificationToken = verificationToken;
+ }
+
public Long getId() {
return id;
}
@@ -126,11 +155,11 @@ public void setAuthority(UserAuthority authority) {
this.authority = authority;
}
- public LocalDateTime getRegistrationDate() {
+ public LocalDate getRegistrationDate() {
return registrationDate;
}
- public void setRegistrationDate(LocalDateTime registrationDate) {
+ public void setRegistrationDate(LocalDate registrationDate) {
this.registrationDate = registrationDate;
}
@@ -166,12 +195,14 @@ public int hashCode() {
email,
password,
isAvailable,
+ isActivated,
firstName,
lastName,
authority,
registrationDate,
birthday,
- description
+ description,
+ verificationToken
);
}
@@ -189,11 +220,13 @@ public boolean equals(Object obj) {
&& Objects.equals(this.email, other.email)
&& Objects.equals(this.password, other.password)
&& Objects.equals(this.isAvailable, other.isAvailable)
+ && Objects.equals(this.isActivated, other.isActivated)
&& Objects.equals(this.firstName, other.firstName)
&& Objects.equals(this.lastName, other.lastName)
&& Objects.equals(this.authority, other.authority)
&& Objects.equals(this.registrationDate, other.registrationDate)
&& Objects.equals(this.birthday, other.birthday)
- && Objects.equals(this.description, other.description);
+ && Objects.equals(this.description, other.description)
+ && Objects.equals(this.verificationToken, other.verificationToken);
}
}
diff --git a/src/main/java/org/teapot/backend/model/UserAuthority.java b/src/main/java/org/teapot/backend/model/user/UserAuthority.java
similarity index 85%
rename from src/main/java/org/teapot/backend/model/UserAuthority.java
rename to src/main/java/org/teapot/backend/model/user/UserAuthority.java
index 36ffcd9..10172eb 100644
--- a/src/main/java/org/teapot/backend/model/UserAuthority.java
+++ b/src/main/java/org/teapot/backend/model/user/UserAuthority.java
@@ -1,4 +1,4 @@
-package org.teapot.backend.model;
+package org.teapot.backend.model.user;
import org.springframework.security.core.GrantedAuthority;
diff --git a/src/main/java/org/teapot/backend/model/VerificationToken.java b/src/main/java/org/teapot/backend/model/user/VerificationToken.java
similarity index 96%
rename from src/main/java/org/teapot/backend/model/VerificationToken.java
rename to src/main/java/org/teapot/backend/model/user/VerificationToken.java
index 4ab6033..d2b1405 100644
--- a/src/main/java/org/teapot/backend/model/VerificationToken.java
+++ b/src/main/java/org/teapot/backend/model/user/VerificationToken.java
@@ -1,4 +1,4 @@
-package org.teapot.backend.model;
+package org.teapot.backend.model.user;
import javax.persistence.*;
import java.time.LocalDateTime;
diff --git a/src/main/java/org/teapot/backend/repository/TeapotActionRepository.java b/src/main/java/org/teapot/backend/repository/meta/TeapotActionRepository.java
similarity index 89%
rename from src/main/java/org/teapot/backend/repository/TeapotActionRepository.java
rename to src/main/java/org/teapot/backend/repository/meta/TeapotActionRepository.java
index a3a5514..5aa9dfa 100644
--- a/src/main/java/org/teapot/backend/repository/TeapotActionRepository.java
+++ b/src/main/java/org/teapot/backend/repository/meta/TeapotActionRepository.java
@@ -1,4 +1,4 @@
-package org.teapot.backend.repository;
+package org.teapot.backend.repository.meta;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
diff --git a/src/main/java/org/teapot/backend/repository/TeapotPropertyRepository.java b/src/main/java/org/teapot/backend/repository/meta/TeapotPropertyRepository.java
similarity index 89%
rename from src/main/java/org/teapot/backend/repository/TeapotPropertyRepository.java
rename to src/main/java/org/teapot/backend/repository/meta/TeapotPropertyRepository.java
index e89ac35..f1b6a32 100644
--- a/src/main/java/org/teapot/backend/repository/TeapotPropertyRepository.java
+++ b/src/main/java/org/teapot/backend/repository/meta/TeapotPropertyRepository.java
@@ -1,4 +1,4 @@
-package org.teapot.backend.repository;
+package org.teapot.backend.repository.meta;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
diff --git a/src/main/java/org/teapot/backend/repository/TeapotResourceRepository.java b/src/main/java/org/teapot/backend/repository/meta/TeapotResourceRepository.java
similarity index 85%
rename from src/main/java/org/teapot/backend/repository/TeapotResourceRepository.java
rename to src/main/java/org/teapot/backend/repository/meta/TeapotResourceRepository.java
index e9ef975..03774a4 100644
--- a/src/main/java/org/teapot/backend/repository/TeapotResourceRepository.java
+++ b/src/main/java/org/teapot/backend/repository/meta/TeapotResourceRepository.java
@@ -1,4 +1,4 @@
-package org.teapot.backend.repository;
+package org.teapot.backend.repository.meta;
import org.springframework.data.jpa.repository.JpaRepository;
import org.teapot.backend.model.meta.TeapotResource;
diff --git a/src/main/java/org/teapot/backend/repository/organization/MemberRepository.java b/src/main/java/org/teapot/backend/repository/organization/MemberRepository.java
new file mode 100644
index 0000000..fa4263f
--- /dev/null
+++ b/src/main/java/org/teapot/backend/repository/organization/MemberRepository.java
@@ -0,0 +1,25 @@
+package org.teapot.backend.repository.organization;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.teapot.backend.model.organization.Member;
+import org.teapot.backend.model.organization.Organization;
+import org.teapot.backend.model.user.User;
+
+import java.util.List;
+
+public interface MemberRepository extends JpaRepository {
+
+ Page findAllByOrganization(Organization organization, Pageable pageable);
+
+ List findAllByOrganization(Organization organization);
+
+ Member findByOrganizationAndId(Organization organization, Long id);
+
+ Member findByOrganizationAndUser(Organization organization, User user);
+
+ List findByUser(User user);
+
+ List findByUser(User user, Pageable pageable);
+}
diff --git a/src/main/java/org/teapot/backend/repository/organization/OrganizationRepository.java b/src/main/java/org/teapot/backend/repository/organization/OrganizationRepository.java
new file mode 100644
index 0000000..114a2d6
--- /dev/null
+++ b/src/main/java/org/teapot/backend/repository/organization/OrganizationRepository.java
@@ -0,0 +1,9 @@
+package org.teapot.backend.repository.organization;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.teapot.backend.model.organization.Organization;
+
+public interface OrganizationRepository extends JpaRepository {
+
+ Organization findByName(String name);
+}
diff --git a/src/main/java/org/teapot/backend/repository/UserRepository.java b/src/main/java/org/teapot/backend/repository/user/UserRepository.java
similarity index 75%
rename from src/main/java/org/teapot/backend/repository/UserRepository.java
rename to src/main/java/org/teapot/backend/repository/user/UserRepository.java
index 6f30768..3ddfa7f 100644
--- a/src/main/java/org/teapot/backend/repository/UserRepository.java
+++ b/src/main/java/org/teapot/backend/repository/user/UserRepository.java
@@ -1,7 +1,7 @@
-package org.teapot.backend.repository;
+package org.teapot.backend.repository.user;
import org.springframework.data.jpa.repository.JpaRepository;
-import org.teapot.backend.model.User;
+import org.teapot.backend.model.user.User;
import javax.transaction.Transactional;
diff --git a/src/main/java/org/teapot/backend/repository/VerificationTokenRepository.java b/src/main/java/org/teapot/backend/repository/user/VerificationTokenRepository.java
similarity index 74%
rename from src/main/java/org/teapot/backend/repository/VerificationTokenRepository.java
rename to src/main/java/org/teapot/backend/repository/user/VerificationTokenRepository.java
index 7ae77c2..73077b4 100644
--- a/src/main/java/org/teapot/backend/repository/VerificationTokenRepository.java
+++ b/src/main/java/org/teapot/backend/repository/user/VerificationTokenRepository.java
@@ -1,8 +1,8 @@
-package org.teapot.backend.repository;
+package org.teapot.backend.repository.user;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
-import org.teapot.backend.model.VerificationToken;
+import org.teapot.backend.model.user.VerificationToken;
@Transactional
public interface VerificationTokenRepository extends JpaRepository {
diff --git a/src/main/java/org/teapot/backend/service/UserDetailsServiceImpl.java b/src/main/java/org/teapot/backend/service/UserDetailsServiceImpl.java
index 0374399..ea770a3 100644
--- a/src/main/java/org/teapot/backend/service/UserDetailsServiceImpl.java
+++ b/src/main/java/org/teapot/backend/service/UserDetailsServiceImpl.java
@@ -1,19 +1,16 @@
package org.teapot.backend.service;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
-import org.teapot.backend.model.User;
-import org.teapot.backend.repository.UserRepository;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.repository.user.UserRepository;
import java.util.Collections;
-
@Service
-@Profile("security")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
diff --git a/src/main/java/org/teapot/backend/util/LinkBuilder.java b/src/main/java/org/teapot/backend/util/LinkBuilder.java
new file mode 100644
index 0000000..1fc045c
--- /dev/null
+++ b/src/main/java/org/teapot/backend/util/LinkBuilder.java
@@ -0,0 +1,24 @@
+package org.teapot.backend.util;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.teapot.backend.repository.meta.TeapotPropertyRepository;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+@Component
+public class LinkBuilder {
+
+ @Autowired
+ private TeapotPropertyRepository propertyRepository;
+
+ public String format(String relativePathFormat, Object... args) {
+ if (Arrays.stream(args).anyMatch(Objects::isNull)) {
+ return null;
+ } else {
+ return propertyRepository.findByName("site-uri").getValue()
+ + String.format(relativePathFormat, args);
+ }
+ }
+}
diff --git a/src/main/java/org/teapot/backend/util/VerificationMailSender.java b/src/main/java/org/teapot/backend/util/VerificationMailSender.java
index bdff934..a8a2148 100644
--- a/src/main/java/org/teapot/backend/util/VerificationMailSender.java
+++ b/src/main/java/org/teapot/backend/util/VerificationMailSender.java
@@ -5,10 +5,10 @@
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
-import org.teapot.backend.model.User;
-import org.teapot.backend.model.VerificationToken;
-import org.teapot.backend.repository.TeapotPropertyRepository;
-import org.teapot.backend.repository.VerificationTokenRepository;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.model.user.VerificationToken;
+import org.teapot.backend.repository.meta.TeapotPropertyRepository;
+import org.teapot.backend.repository.user.VerificationTokenRepository;
import java.util.Locale;
diff --git a/src/main/java/org/teapot/backend/util/VerificationTokenGenerator.java b/src/main/java/org/teapot/backend/util/VerificationTokenGenerator.java
index db858f4..b77a693 100644
--- a/src/main/java/org/teapot/backend/util/VerificationTokenGenerator.java
+++ b/src/main/java/org/teapot/backend/util/VerificationTokenGenerator.java
@@ -2,9 +2,9 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
-import org.teapot.backend.model.VerificationToken;
-import org.teapot.backend.repository.TeapotPropertyRepository;
-import org.teapot.backend.repository.VerificationTokenRepository;
+import org.teapot.backend.model.user.VerificationToken;
+import org.teapot.backend.repository.meta.TeapotPropertyRepository;
+import org.teapot.backend.repository.user.VerificationTokenRepository;
import java.time.LocalDateTime;
diff --git a/src/main/java/org/teapot/backend/util/deser/MemberDeserializer.java b/src/main/java/org/teapot/backend/util/deser/MemberDeserializer.java
new file mode 100644
index 0000000..571f2e5
--- /dev/null
+++ b/src/main/java/org/teapot/backend/util/deser/MemberDeserializer.java
@@ -0,0 +1,69 @@
+package org.teapot.backend.util.deser;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.fasterxml.jackson.databind.node.NullNode;
+import com.fasterxml.jackson.databind.node.ValueNode;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.teapot.backend.model.organization.Member;
+import org.teapot.backend.model.organization.MemberStatus;
+import org.teapot.backend.model.organization.Organization;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.repository.organization.OrganizationRepository;
+import org.teapot.backend.repository.user.UserRepository;
+
+import java.io.IOException;
+
+@Component
+public class MemberDeserializer extends StdDeserializer {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private OrganizationRepository organizationRepository;
+
+ public MemberDeserializer() {
+ this(null);
+ }
+
+ private MemberDeserializer(Class> vc) {
+ super(vc);
+ }
+
+ @Override
+ public Member deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+ TreeNode node = p.getCodec().readTree(p);
+
+ ValueNode idNode = (ValueNode) node.get("id");
+ Long id = (idNode instanceof NullNode) || (idNode == null)
+ ? null
+ : idNode.asLong();
+
+ ValueNode userIdNode = (ValueNode) node.get("userId");
+ User user = (userIdNode instanceof NullNode) || (userIdNode == null)
+ ? null
+ : userRepository.findOne(userIdNode.asLong());
+
+ ValueNode statusNode = (ValueNode) node.get("status");
+ MemberStatus status = (statusNode instanceof NullNode) || (statusNode == null)
+ ? null
+ : MemberStatus.valueOf(statusNode.asText());
+
+ ValueNode organizationIdNode = (ValueNode) node.get("organizationId");
+ Organization organization = (organizationIdNode instanceof NullNode) || (organizationIdNode == null)
+ ? null
+ : organizationRepository.findOne(organizationIdNode.asLong());
+
+ return new Member(
+ id,
+ user,
+ status,
+ organization,
+ null
+ );
+ }
+}
diff --git a/src/main/java/org/teapot/backend/util/ser/MemberSerializer.java b/src/main/java/org/teapot/backend/util/ser/MemberSerializer.java
new file mode 100644
index 0000000..4a8868c
--- /dev/null
+++ b/src/main/java/org/teapot/backend/util/ser/MemberSerializer.java
@@ -0,0 +1,48 @@
+package org.teapot.backend.util.ser;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.teapot.backend.model.organization.Member;
+import org.teapot.backend.util.LinkBuilder;
+
+import java.io.IOException;
+
+@Component
+public class MemberSerializer extends StdSerializer {
+
+ @Autowired
+ private LinkBuilder linkBuilder;
+
+ public MemberSerializer() {
+ this(null);
+ }
+
+ private MemberSerializer(Class t) {
+ super(t);
+ }
+
+ @Override
+ public void serialize(Member member, JsonGenerator gen, SerializerProvider provider)
+ throws IOException {
+ gen.writeStartObject();
+ gen.writeObjectField("id", member.getId());
+ if (member.getUser() == null) {
+ gen.writeNullField("user");
+ } else {
+ gen.writeStringField("user",
+ linkBuilder.format("/users/%d", member.getUser().getId()));
+ }
+ gen.writeObjectField("status", member.getStatus());
+ if (member.getOrganization() == null) {
+ gen.writeNullField("organization");
+ } else {
+ gen.writeStringField("organization",
+ linkBuilder.format("/organizations/%d", member.getOrganization().getId()));
+ }
+ gen.writeObjectField("admissionDate", member.getAdmissionDate());
+ gen.writeEndObject();
+ }
+}
diff --git a/src/main/java/org/teapot/backend/util/ser/OrganizationSerializer.java b/src/main/java/org/teapot/backend/util/ser/OrganizationSerializer.java
new file mode 100644
index 0000000..7e5f7fd
--- /dev/null
+++ b/src/main/java/org/teapot/backend/util/ser/OrganizationSerializer.java
@@ -0,0 +1,39 @@
+package org.teapot.backend.util.ser;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.teapot.backend.model.organization.Organization;
+import org.teapot.backend.util.LinkBuilder;
+
+import java.io.IOException;
+
+@Component
+public class OrganizationSerializer extends StdSerializer {
+
+ @Autowired
+ private LinkBuilder linkBuilder;
+
+ public OrganizationSerializer() {
+ this(null);
+ }
+
+ private OrganizationSerializer(Class t) {
+ super(t);
+ }
+
+ @Override
+ public void serialize(Organization org, JsonGenerator gen, SerializerProvider provider)
+ throws IOException {
+ gen.writeStartObject();
+ gen.writeObjectField("id", org.getId());
+ gen.writeObjectField("name", org.getName());
+ gen.writeObjectField("fullName", org.getFullName());
+ gen.writeObjectField("creationDate", org.getCreationDate());
+ gen.writeStringField("members",
+ linkBuilder.format("/organizations/%d/members", org.getId()));
+ gen.writeEndObject();
+ }
+}
diff --git a/src/main/java/org/teapot/backend/util/ser/UserSerializer.java b/src/main/java/org/teapot/backend/util/ser/UserSerializer.java
new file mode 100644
index 0000000..6f7fcd0
--- /dev/null
+++ b/src/main/java/org/teapot/backend/util/ser/UserSerializer.java
@@ -0,0 +1,46 @@
+package org.teapot.backend.util.ser;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.util.LinkBuilder;
+
+import java.io.IOException;
+
+@Component
+public class UserSerializer extends StdSerializer {
+
+ @Autowired
+ private LinkBuilder linkBuilder;
+
+ public UserSerializer() {
+ this(null);
+ }
+
+ private UserSerializer(Class t) {
+ super(t);
+ }
+
+ @Override
+ public void serialize(User user, JsonGenerator gen, SerializerProvider provider)
+ throws IOException {
+ gen.writeStartObject();
+ gen.writeObjectField("id", user.getId());
+ gen.writeObjectField("username", user.getUsername());
+ gen.writeObjectField("email", user.getEmail());
+ gen.writeObjectField("isAvailable", user.isAvailable());
+ gen.writeObjectField("isActivated", user.isActivated());
+ gen.writeObjectField("firstName", user.getFirstName());
+ gen.writeObjectField("lastName", user.getLastName());
+ gen.writeObjectField("authority", user.getAuthority());
+ gen.writeObjectField("registrationDate", user.getRegistrationDate());
+ gen.writeObjectField("birthday", user.getBirthday());
+ gen.writeObjectField("description", user.getDescription());
+ gen.writeObjectField("organizations",
+ linkBuilder.format("/organizations?user=%d", user.getId()));
+ gen.writeEndObject();
+ }
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index bdb6b3c..eb45dd5 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,3 +1,3 @@
spring:
profiles:
- active: development,security
+ active: development
diff --git a/src/test/java/org/teapot/backend/test/controller/AbstractControllerIT.java b/src/test/java/org/teapot/backend/test/controller/AbstractControllerIT.java
index fd0a976..faaf71e 100644
--- a/src/test/java/org/teapot/backend/test/controller/AbstractControllerIT.java
+++ b/src/test/java/org/teapot/backend/test/controller/AbstractControllerIT.java
@@ -1,14 +1,13 @@
package org.teapot.backend.test.controller;
-import org.junit.Assert;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.json.JacksonJsonParser;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
-import org.springframework.mock.http.MockHttpOutputMessage;
+import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.web.servlet.MockMvc;
@@ -16,14 +15,13 @@
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.context.WebApplicationContext;
-import org.teapot.backend.model.User;
-import org.teapot.backend.model.UserAuthority;
-import org.teapot.backend.repository.UserRepository;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.model.user.UserAuthority;
+import org.teapot.backend.repository.user.UserRepository;
import org.teapot.backend.test.AbstractIT;
import java.io.IOException;
import java.nio.charset.Charset;
-import java.util.Arrays;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@@ -45,7 +43,7 @@ public abstract class AbstractControllerIT extends AbstractIT {
protected JacksonJsonParser parser = new JacksonJsonParser();
- private HttpMessageConverter mappingJackson2HttpMessageConverter;
+ protected ObjectMapper mapper;
@Autowired
protected UserRepository userRepository;
@@ -60,30 +58,23 @@ public abstract class AbstractControllerIT extends AbstractIT {
protected String userAccessToken;
@Autowired
- private void setConverters(HttpMessageConverter>[] converters) {
- mappingJackson2HttpMessageConverter = Arrays.stream(converters)
- .filter(converter -> converter instanceof MappingJackson2HttpMessageConverter)
- .findAny().get();
- Assert.assertNotNull(mappingJackson2HttpMessageConverter);
- }
-
- @Autowired
- public void setMockMvc(WebApplicationContext wac, FilterChainProxy filter) throws Exception {
+ public void setMockMvcAndMapper(WebApplicationContext wac, FilterChainProxy filter) throws Exception {
mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.addFilters(filter)
.build();
+
+ mapper = Jackson2ObjectMapperBuilder.json()
+ .featuresToDisable(MapperFeature.USE_ANNOTATIONS)
+ .build();
}
@SuppressWarnings("unchecked")
protected String json(Object object) throws IOException {
- MockHttpOutputMessage mockHttpOutputMessage = new MockHttpOutputMessage();
- mappingJackson2HttpMessageConverter.write(
- object, MediaType.APPLICATION_JSON, mockHttpOutputMessage);
- return mockHttpOutputMessage.getBodyAsString();
+ return mapper.writeValueAsString(object);
}
- private String obtainAccessToken(String email, String password) throws Exception {
+ protected String obtainAccessToken(String email, String password) throws Exception {
MultiValueMap params = new LinkedMultiValueMap<>();
params.add("grant_type", "password");
params.add("username", email);
diff --git a/src/test/java/org/teapot/backend/test/controller/OrganizationControllerIT.java b/src/test/java/org/teapot/backend/test/controller/OrganizationControllerIT.java
new file mode 100644
index 0000000..7387ba6
--- /dev/null
+++ b/src/test/java/org/teapot/backend/test/controller/OrganizationControllerIT.java
@@ -0,0 +1,605 @@
+package org.teapot.backend.test.controller;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.teapot.backend.model.organization.Member;
+import org.teapot.backend.model.organization.MemberStatus;
+import org.teapot.backend.model.organization.Organization;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.model.user.UserAuthority;
+import org.teapot.backend.repository.organization.MemberRepository;
+import org.teapot.backend.repository.organization.OrganizationRepository;
+import org.teapot.backend.repository.user.UserRepository;
+import org.teapot.backend.util.LinkBuilder;
+
+import java.time.LocalDate;
+import java.util.List;
+
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.springframework.http.HttpHeaders.AUTHORIZATION;
+import static org.springframework.security.oauth2.common.OAuth2AccessToken.BEARER_TYPE;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+
+public class OrganizationControllerIT extends AbstractControllerIT {
+
+ private static final String ORGANIZATIONS_URL = "organizations";
+ private static final String MEMBERS_URL = "members";
+ private static final String USERS_URL = "users";
+
+ @Autowired
+ private OrganizationRepository organizationRepository;
+
+ @Autowired
+ private MemberRepository memberRepository;
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private LinkBuilder linkBuilder;
+
+ private Organization getOrganization = new Organization();
+ private User user1;
+ private User user2;
+ private Member creator;
+ private Member member2;
+ private Organization deleteOrganizationAdmin;
+ private Organization deleteOrganizationCreator;
+ private Member deleteOrganizationCreatorCreator;
+ private User user3;
+ private User user4;
+ private User user5;
+ private User user6;
+ private User user7;
+ private User user8;
+ private User user9;
+ private Member worker;
+ private Member owner1;
+ private Member owner2;
+ private Member owner3;
+ private Member worker2;
+ private Member worker3;
+ private Member postMember;
+ private Organization postOrganization;
+ private Organization repeatPostOrganization;
+
+ private String creatorAccessToken;
+ private String workerAccessToken;
+ private String owner1AccessToken;
+
+ @Before
+ public void addTestDate() throws Exception {
+ getOrganization.setName("getOrganization");
+ getOrganization.setCreationDate(LocalDate.now());
+ organizationRepository.save(getOrganization);
+
+ user1 = new User();
+ user1.setUsername("user1");
+ user1.setEmail("user1@email.com");
+ user1.setPassword(passwordEncoder.encode("pass"));
+ user1.setActivated(true);
+ user1.setFirstName("user1");
+ user1.setLastName("user1");
+ userRepository.save(user1);
+
+ creatorAccessToken = obtainAccessToken("user1@email.com", "pass");
+
+ creator = new Member();
+ creator.setOrganization(getOrganization);
+ creator.setAdmissionDate(LocalDate.now());
+ creator.setStatus(MemberStatus.CREATOR);
+ creator.setUser(user1);
+ memberRepository.save(creator);
+
+ user2 = new User();
+ user2.setUsername("user2");
+ user2.setEmail("user2@email.com");
+ user2.setPassword(passwordEncoder.encode("pass"));
+ userRepository.save(user2);
+
+ member2 = new Member();
+ member2.setOrganization(getOrganization);
+ member2.setAdmissionDate(LocalDate.now());
+ member2.setStatus(MemberStatus.WORKER);
+ member2.setUser(user2);
+ memberRepository.save(member2);
+
+ deleteOrganizationAdmin = new Organization();
+ deleteOrganizationAdmin.setName("deleteOrganizationAdmin");
+ organizationRepository.save(deleteOrganizationAdmin);
+
+ deleteOrganizationCreator = new Organization();
+ deleteOrganizationCreator.setName("deleteOrganizationCreator");
+ organizationRepository.save(deleteOrganizationCreator);
+
+ deleteOrganizationCreatorCreator = new Member();
+ deleteOrganizationCreatorCreator.setStatus(MemberStatus.CREATOR);
+ deleteOrganizationCreatorCreator.setOrganization(deleteOrganizationCreator);
+ deleteOrganizationCreatorCreator.setUser(user1);
+ memberRepository.save(member2);
+ deleteOrganizationCreator.getMembers().add(deleteOrganizationCreatorCreator);
+
+ user3 = new User();
+ user3.setUsername("user3");
+ user3.setEmail("user3@email.com");
+ user3.setPassword(passwordEncoder.encode("pass"));
+ user3.setActivated(true);
+ userRepository.save(user3);
+
+ workerAccessToken = obtainAccessToken("user3@email.com", "pass");
+
+ user4 = new User();
+ user4.setUsername("user4");
+ user4.setEmail("user4@email.com");
+ user4.setPassword(passwordEncoder.encode("pass"));
+ user4.setActivated(true);
+ userRepository.save(user4);
+
+ user5 = new User();
+ user5.setUsername("user5");
+ user5.setEmail("user5@email.com");
+ user5.setPassword(passwordEncoder.encode("pass"));
+ user5.setActivated(true);
+ userRepository.save(user5);
+
+ user6 = new User();
+ user6.setUsername("user6");
+ user6.setEmail("user6@email.com");
+ user6.setPassword(passwordEncoder.encode("pass"));
+ user6.setActivated(true);
+ userRepository.save(user6);
+
+ user7 = new User();
+ user7.setUsername("user7");
+ user7.setEmail("user7@email.com");
+ user7.setPassword(passwordEncoder.encode("pass"));
+ user7.setActivated(true);
+ userRepository.save(user7);
+
+ user8 = new User();
+ user8.setUsername("user8");
+ user8.setEmail("user8@email.com");
+ user8.setPassword(passwordEncoder.encode("pass"));
+ user8.setActivated(true);
+ userRepository.save(user8);
+
+ user9 = new User();
+ user9.setUsername("user9");
+ user9.setEmail("user9@email.com");
+ user9.setPassword(passwordEncoder.encode("pass"));
+ user9.setActivated(true);
+ userRepository.save(user9);
+
+ worker = new Member();
+ worker.setUser(user3);
+ worker.setOrganization(getOrganization);
+ worker.setStatus(MemberStatus.WORKER);
+ memberRepository.save(worker);
+
+ owner1 = new Member();
+ owner1.setUser(user4);
+ owner1.setOrganization(getOrganization);
+ owner1.setStatus(MemberStatus.OWNER);
+ memberRepository.save(owner1);
+
+ owner1AccessToken = obtainAccessToken("user4@email.com", "pass");
+
+ owner2 = new Member();
+ owner2.setUser(user5);
+ owner2.setOrganization(getOrganization);
+ owner2.setStatus(MemberStatus.OWNER);
+ memberRepository.save(owner2);
+
+ owner3 = new Member();
+ owner3.setUser(user6);
+ owner3.setOrganization(getOrganization);
+ owner3.setStatus(MemberStatus.OWNER);
+ memberRepository.save(owner3);
+
+ worker2 = new Member();
+ worker2.setUser(user7);
+ worker2.setOrganization(getOrganization);
+ worker2.setStatus(MemberStatus.WORKER);
+ memberRepository.save(worker2);
+
+ worker3 = new Member();
+ worker3.setUser(user8);
+ worker3.setOrganization(getOrganization);
+ worker3.setStatus(MemberStatus.WORKER);
+ memberRepository.save(worker3);
+
+ postOrganization = new Organization();
+ postOrganization.setName("postOrganization");
+
+ repeatPostOrganization = new Organization();
+ repeatPostOrganization.setName("repeatPostOrganization");
+ organizationRepository.save(repeatPostOrganization);
+
+ postMember = new Member();
+ postMember.setUser(user9);
+ postMember.setStatus(MemberStatus.WORKER);
+ }
+
+ // GET ORGANIZATIONS
+
+ @Test
+ public void getOrganizationsTestByUser() throws Exception {
+ List all = organizationRepository.findAll();
+ mockMvc.perform(get(String.format("/%s", ORGANIZATIONS_URL))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, userAccessToken)))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(contentType))
+ .andExpect(jsonPath("$", hasSize(all.size())))
+ .andExpect(jsonPath("$[0].id", is(all.get(0).getId().intValue())))
+ .andExpect(jsonPath("$[0].name", is(all.get(0).getName())))
+ .andExpect(jsonPath("$[0].fullName", is(all.get(0).getFullName())))
+ .andExpect(jsonPath("$[0].members",
+ is(linkBuilder.format("/%s/%d/%s", ORGANIZATIONS_URL,
+ all.get(0).getId().intValue(), MEMBERS_URL))));
+ }
+
+ @Test
+ public void getSingleOrganizationByIdTestByUser() throws Exception {
+ mockMvc.perform(get(String.format("/%s/%d", ORGANIZATIONS_URL, getOrganization.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, userAccessToken)))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(contentType))
+ .andExpect(jsonPath("$.id", is(getOrganization.getId().intValue())))
+ .andExpect(jsonPath("$.name", is(getOrganization.getName())))
+ .andExpect(jsonPath("$.fullName", is(getOrganization.getFullName())))
+ .andExpect(jsonPath("$.members",
+ is(linkBuilder.format("/%s/%d/%s", ORGANIZATIONS_URL,
+ getOrganization.getId().intValue(), MEMBERS_URL))));
+ }
+
+ @Test
+ public void getNotExistsOrganizationTestByUser() throws Exception {
+ mockMvc.perform(get(String.format("/%s/-1", ORGANIZATIONS_URL))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, userAccessToken)))
+ .andExpect(status().isNotFound());
+ }
+
+ // GET MEMBERS
+
+ @Test
+ public void getMembersInOrganizationByAdmin() throws Exception {
+ List members = memberRepository.findAllByOrganization(getOrganization);
+
+ mockMvc.perform(get(String.format("/%s/%d/%s", ORGANIZATIONS_URL, getOrganization.getId(), MEMBERS_URL))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken)))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(contentType))
+ .andExpect(jsonPath("$", hasSize(members.size())))
+ .andExpect(jsonPath("$[0].id", is(members.get(0).getId().intValue())))
+ .andExpect(jsonPath("$[0].status", is(members.get(0).getStatus().toString())))
+ .andExpect(jsonPath("$[0].user",
+ is(linkBuilder.format("/%s/%d",
+ USERS_URL, members.get(0).getUser().getId()))))
+ .andExpect(jsonPath("$[0].organization",
+ is(linkBuilder.format("/%s/%d",
+ ORGANIZATIONS_URL, members.get(0).getOrganization().getId()))));
+ }
+
+ @Test
+ public void getMembersInOrganizationByMember() throws Exception {
+ List members = memberRepository.findAllByOrganization(getOrganization);
+
+ mockMvc.perform(get(String.format("/%s/%d/%s", ORGANIZATIONS_URL, getOrganization.getId(), MEMBERS_URL))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, creatorAccessToken)))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(contentType))
+ .andExpect(jsonPath("$", hasSize(members.size())))
+ .andExpect(jsonPath("$[0].id", is(members.get(0).getId().intValue())))
+ .andExpect(jsonPath("$[0].status", is(members.get(0).getStatus().toString())))
+ .andExpect(jsonPath("$[0].user",
+ is(linkBuilder.format("/%s/%d",
+ USERS_URL, members.get(0).getUser().getId()))))
+ .andExpect(jsonPath("$[0].organization",
+ is(linkBuilder.format("/%s/%d",
+ ORGANIZATIONS_URL, members.get(0).getOrganization().getId()))));
+ }
+
+ @Test
+ public void getMemberInOrganizationByAdmin() throws Exception {
+ Member member = memberRepository.findAllByOrganization(getOrganization).get(0);
+
+ mockMvc.perform(get(String.format("/%s/%d/%s/%d",
+ ORGANIZATIONS_URL, member.getOrganization().getId(), MEMBERS_URL, member.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken)))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(contentType))
+ .andExpect(jsonPath("$.id", is(member.getId().intValue())))
+ .andExpect(jsonPath("$.status", is(member.getStatus().toString())))
+ .andExpect(jsonPath("$.user",
+ is(linkBuilder.format("/%s/%d",
+ USERS_URL, member.getUser().getId()))))
+ .andExpect(jsonPath("$.organization",
+ is(linkBuilder.format("/%s/%d",
+ ORGANIZATIONS_URL, member.getOrganization().getId()))));
+ }
+
+ @Test
+ public void getMemberInOrganizationByMember() throws Exception {
+ Member member = memberRepository.findAllByOrganization(getOrganization).get(0);
+
+ mockMvc.perform(get(String.format("/%s/%d/%s/%d",
+ ORGANIZATIONS_URL, member.getOrganization().getId(), MEMBERS_URL, member.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, creatorAccessToken)))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(contentType))
+ .andExpect(jsonPath("$.id", is(member.getId().intValue())))
+ .andExpect(jsonPath("$.status", is(member.getStatus().toString())))
+ .andExpect(jsonPath("$.user",
+ is(linkBuilder.format("/%s/%d",
+ USERS_URL, member.getUser().getId()))))
+ .andExpect(jsonPath("$.organization",
+ is(linkBuilder.format("/%s/%d",
+ ORGANIZATIONS_URL, member.getOrganization().getId()))));
+ }
+
+ @Test
+ public void getNotExistsMemberInOrganizationByAdmin() throws Exception {
+ Member member = memberRepository.findAllByOrganization(getOrganization).get(0);
+
+ mockMvc.perform(get(String.format("/%s/%d/%s/%d",
+ ORGANIZATIONS_URL, member.getOrganization().getId(), MEMBERS_URL, -1))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken)))
+ .andExpect(status().isNotFound());
+ }
+
+ // DELETE ORGANIZATIONS
+
+ @Test
+ public void deleteOrganizationTestByAnonymous() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d", ORGANIZATIONS_URL, getOrganization.getId())))
+ .andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ public void deleteOrganizationTestByUser() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d", ORGANIZATIONS_URL, getOrganization.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, userAccessToken)))
+ .andExpect(status().isForbidden());
+ }
+
+ @Test
+ public void deleteOrganizationTestByAdmin() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d", ORGANIZATIONS_URL, deleteOrganizationAdmin.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken)))
+ .andExpect(status().isNoContent());
+ }
+
+ @Test
+ public void deleteNotExistsOrganizationTestByAdmin() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/-1", ORGANIZATIONS_URL))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken)))
+ .andExpect(status().isNotFound());
+ }
+
+ @Test
+ public void deleteNotExistsOrganizationTestByCreator() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d", ORGANIZATIONS_URL, deleteOrganizationCreator.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, creatorAccessToken)))
+ .andExpect(status().isNoContent());
+ }
+
+ // DELETE MEMBERS
+
+ @Test
+ public void deleteCreatorTestByOwner() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d/%s/%d", ORGANIZATIONS_URL, getOrganization.getId(),
+ MEMBERS_URL, creator.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, owner1AccessToken)))
+ .andExpect(status().isForbidden());
+ }
+
+ @Test
+ public void deleteCreatorTestByWorker() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d/%s/%d", ORGANIZATIONS_URL, getOrganization.getId(),
+ MEMBERS_URL, creator.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, workerAccessToken)))
+ .andExpect(status().isForbidden());
+ }
+
+ @Test
+ public void deleteOwnerTestByWorker() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d/%s/%d", ORGANIZATIONS_URL, getOrganization.getId(),
+ MEMBERS_URL, owner2.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, workerAccessToken)))
+ .andExpect(status().isForbidden());
+ }
+
+ @Test
+ public void deleteOwnerTestByCreator() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d/%s/%d", ORGANIZATIONS_URL, getOrganization.getId(),
+ MEMBERS_URL, owner2.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, creatorAccessToken)))
+ .andExpect(status().isNoContent());
+ }
+
+ @Test
+ public void deleteOwnerTestByOwner() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d/%s/%d", ORGANIZATIONS_URL, getOrganization.getId(),
+ MEMBERS_URL, owner3.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, owner1AccessToken)))
+ .andExpect(status().isNoContent());
+ }
+
+ @Test
+ public void deleteWorkerTestByWorker() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d/%s/%d", ORGANIZATIONS_URL, getOrganization.getId(),
+ MEMBERS_URL, worker.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, workerAccessToken)))
+ .andExpect(status().isForbidden());
+ }
+
+ @Test
+ public void deleteWorkerTestByOwner() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d/%s/%d", ORGANIZATIONS_URL, getOrganization.getId(),
+ MEMBERS_URL, worker2.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, owner1AccessToken)))
+ .andExpect(status().isNoContent());
+ }
+
+ @Test
+ public void deleteWorkerTestByCreator() throws Exception {
+ mockMvc.perform(delete(String.format("/%s/%d/%s/%d", ORGANIZATIONS_URL, getOrganization.getId(),
+ MEMBERS_URL, worker3.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, creatorAccessToken)))
+ .andExpect(status().isNoContent());
+ }
+
+ // POST ORGANIZATIONS
+
+ @Test
+ public void createOrganizationByAdmin() throws Exception {
+ mockMvc.perform(post(String.format("/%s", ORGANIZATIONS_URL))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .content(json(postOrganization))
+ .contentType(contentType))
+ .andExpect(status().isCreated());
+ Assert.assertNotNull(organizationRepository.findByName(postOrganization.getName()));
+ }
+
+ @Test
+ public void createExistingOrganizationByAdmin() throws Exception {
+ mockMvc.perform(post(String.format("/%s", ORGANIZATIONS_URL))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .content(json(repeatPostOrganization))
+ .contentType(contentType))
+ .andExpect(status().isBadRequest());
+ }
+
+ // POST MEMBERS
+
+ @Test
+ public void addMemberToOrganizationByAdmin() throws Exception {
+ mockMvc.perform(post(String.format("/%s/%d/%s", ORGANIZATIONS_URL, getOrganization.getId(), MEMBERS_URL))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .content(String.format("{\"userId\":%d,\"status\":\"%s\"}",
+ postMember.getUser().getId(), postMember.getStatus()))
+ .contentType(contentType))
+ .andExpect(status().isCreated());
+ Assert.assertNotNull(memberRepository.findByOrganizationAndUser(getOrganization, postMember.getUser()));
+ }
+
+ @Test
+ public void addExistingMemberToOrganizationByAdmin() throws Exception {
+ mockMvc.perform(post(String.format("/%s/%d/%s", ORGANIZATIONS_URL, getOrganization.getId(), MEMBERS_URL))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .content(String.format("{\"userId\":%d,\"status\":\"%s\"}",
+ creator.getUser().getId(), creator.getStatus()))
+ .contentType(contentType))
+ .andExpect(status().isBadRequest());
+ }
+
+ // PATCH ORGANIZATIONS
+
+ @Test
+ public void changeNameTestByAdmin() throws Exception {
+ mockMvc.perform(patch(String.format("/%s/%d", ORGANIZATIONS_URL, getOrganization.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .param("name", "newName"))
+ .andExpect(status().isNoContent());
+
+ Organization org = organizationRepository.findOne(getOrganization.getId());
+ Assert.assertEquals("newName", org.getName());
+ }
+
+ @Test
+ public void changeFullNameTestByAdmin() throws Exception {
+ mockMvc.perform(patch(String.format("/%s/%d", ORGANIZATIONS_URL, getOrganization.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .param("fullName", "newFullName"))
+ .andExpect(status().isNoContent());
+
+ Organization org = organizationRepository.findOne(getOrganization.getId());
+ Assert.assertEquals("newFullName", org.getFullName());
+ }
+
+ @Test
+ public void changeNameAndFullNameTestByAdmin() throws Exception {
+ mockMvc.perform(patch(String.format("/%s/%d", ORGANIZATIONS_URL, getOrganization.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .param("name", "newName1")
+ .param("fullName", "newFullName1"))
+ .andExpect(status().isNoContent());
+
+ Organization org = organizationRepository.findOne(getOrganization.getId());
+ Assert.assertEquals("newName1", org.getName());
+ Assert.assertEquals("newFullName1", org.getFullName());
+ }
+
+ @Test
+ public void changeNameAndFullNameTestByCreator() throws Exception {
+ mockMvc.perform(patch(String.format("/%s/%d", ORGANIZATIONS_URL, getOrganization.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, creatorAccessToken))
+ .param("name", "newName1")
+ .param("fullName", "newFullName1"))
+ .andExpect(status().isNoContent());
+
+ Organization org = organizationRepository.findOne(getOrganization.getId());
+ Assert.assertEquals("newName1", org.getName());
+ Assert.assertEquals("newFullName1", org.getFullName());
+ }
+
+ @Test
+ public void changeNameAndFullNameTestByOwner() throws Exception {
+ mockMvc.perform(patch(String.format("/%s/%d", ORGANIZATIONS_URL, getOrganization.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, owner1AccessToken))
+ .param("name", "newName1")
+ .param("fullName", "newFullName1"))
+ .andExpect(status().isNoContent());
+
+ Organization org = organizationRepository.findOne(getOrganization.getId());
+ Assert.assertEquals("newName1", org.getName());
+ Assert.assertEquals("newFullName1", org.getFullName());
+ }
+
+ // PATCH MEMBERS
+
+ @Test
+ public void changeCreatorStatusToWorkerTestByAdmin() throws Exception {
+ mockMvc.perform(patch(String.format("/%s/%d/%s/%d",
+ ORGANIZATIONS_URL, getOrganization.getId(), MEMBERS_URL, creator.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .param("status", "WORKER"))
+ .andExpect(status().isForbidden());
+ }
+
+ @Test
+ public void changeOwnerStatusToCreatorTestByAdmin() throws Exception {
+ mockMvc.perform(patch(String.format("/%s/%d/%s/%d",
+ ORGANIZATIONS_URL, getOrganization.getId(), MEMBERS_URL, owner1.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .param("status", "CREATOR"))
+ .andExpect(status().isForbidden());
+ }
+
+ @Test
+ public void changeOwnerStatusToWorkerTestByAdmin() throws Exception {
+ mockMvc.perform(patch(String.format("/%s/%d/%s/%d",
+ ORGANIZATIONS_URL, getOrganization.getId(), MEMBERS_URL, owner2.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .param("status", "WORKER"))
+ .andExpect(status().isNoContent());
+ Assert.assertEquals(MemberStatus.WORKER,
+ memberRepository.findByOrganizationAndId(getOrganization, owner2.getId()).getStatus());
+ }
+
+ @Test
+ public void changeWorkerStatusToOwnerTestByAdmin() throws Exception {
+ mockMvc.perform(patch(String.format("/%s/%d/%s/%d",
+ ORGANIZATIONS_URL, getOrganization.getId(), MEMBERS_URL, worker2.getId()))
+ .header(AUTHORIZATION, String.format("%s %s", BEARER_TYPE, adminAccessToken))
+ .param("status", "OWNER"))
+ .andExpect(status().isNoContent());
+ Assert.assertEquals(MemberStatus.OWNER,
+ memberRepository.findByOrganizationAndId(getOrganization, worker2.getId()).getStatus());
+ }
+}
diff --git a/src/test/java/org/teapot/backend/test/controller/TeapotPropertyControllerIT.java b/src/test/java/org/teapot/backend/test/controller/TeapotPropertyControllerIT.java
index dd80a1f..50cc05f 100644
--- a/src/test/java/org/teapot/backend/test/controller/TeapotPropertyControllerIT.java
+++ b/src/test/java/org/teapot/backend/test/controller/TeapotPropertyControllerIT.java
@@ -3,8 +3,9 @@
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
import org.teapot.backend.model.meta.TeapotProperty;
-import org.teapot.backend.repository.TeapotPropertyRepository;
+import org.teapot.backend.repository.meta.TeapotPropertyRepository;
import java.util.Arrays;
import java.util.List;
@@ -78,7 +79,7 @@ public void addNonexistentPropertyTest() throws Exception {
mockMvc.perform(post(API_URL).content(json(nonexistentProperty))
.contentType(contentType))
.andExpect(status().isCreated())
- .andExpect(header().string("Location", containsString(API_URL)));
+ .andExpect(header().string(HttpHeaders.LOCATION, containsString(API_URL)));
}
@Test
@@ -86,7 +87,7 @@ public void addExistentPropertyTest() throws Exception {
mockMvc.perform(post(API_URL).content(json(existentProperty))
.contentType(contentType))
.andExpect(status().isBadRequest())
- .andExpect(header().doesNotExist("Location"));
+ .andExpect(header().doesNotExist(HttpHeaders.LOCATION));
}
@Test
diff --git a/src/test/java/org/teapot/backend/test/controller/UserControllerIT.java b/src/test/java/org/teapot/backend/test/controller/UserControllerIT.java
index 06fffd6..2b43593 100644
--- a/src/test/java/org/teapot/backend/test/controller/UserControllerIT.java
+++ b/src/test/java/org/teapot/backend/test/controller/UserControllerIT.java
@@ -3,10 +3,11 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
-import org.teapot.backend.model.User;
-import org.teapot.backend.model.UserAuthority;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.model.user.UserAuthority;
import java.time.LocalDate;
import java.util.List;
@@ -84,11 +85,9 @@ public void getUsersTest() throws Exception {
.andExpect(jsonPath("$[0].id", is(all.get(0).getId().intValue())))
.andExpect(jsonPath("$[0].username", is(all.get(0).getUsername())))
.andExpect(jsonPath("$[0].email", is(all.get(0).getEmail())))
- .andExpect(jsonPath("$[0].password", is(all.get(0).getPassword())))
.andExpect(jsonPath("$[1].id", is(all.get(1).getId().intValue())))
.andExpect(jsonPath("$[1].username", is(all.get(1).getUsername())))
- .andExpect(jsonPath("$[1].email", is(all.get(1).getEmail())))
- .andExpect(jsonPath("$[1].password", is(all.get(1).getPassword())));
+ .andExpect(jsonPath("$[1].email", is(all.get(1).getEmail())));
}
@Test
@@ -98,8 +97,7 @@ public void getSingleUserByIdTest() throws Exception {
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$.id", is(getUserOne.getId().intValue())))
.andExpect(jsonPath("$.username", is(getUserOne.getUsername())))
- .andExpect(jsonPath("$.email", is(getUserOne.getEmail())))
- .andExpect(jsonPath("$.password", is(getUserOne.getPassword())));
+ .andExpect(jsonPath("$.email", is(getUserOne.getEmail())));
}
@Test
@@ -116,7 +114,7 @@ public void registerUserTestByAnonymous() throws Exception {
.content(json(postUserOne))
.contentType(contentType))
.andExpect(status().isCreated())
- .andExpect(header().string("Location", containsString(API_URL)));
+ .andExpect(header().string(HttpHeaders.LOCATION, containsString(API_URL)));
}
@Test
@@ -135,7 +133,7 @@ public void registerUserTestByAdmin() throws Exception {
.content(json(postUserTwo))
.contentType(contentType))
.andExpect(status().isCreated())
- .andExpect(header().string("Location", containsString(API_URL)));
+ .andExpect(header().string(HttpHeaders.LOCATION, containsString(API_URL)));
}
@Test
@@ -145,7 +143,7 @@ public void repeatRegisterUserTestByAdmin() throws Exception {
.content(json(repeatedPostUser))
.contentType(contentType))
.andExpect(status().isBadRequest())
- .andExpect(header().doesNotExist("Location"));
+ .andExpect(header().doesNotExist(HttpHeaders.LOCATION));
}
// PUT
diff --git a/src/test/java/org/teapot/backend/test/repository/MemberRepositoryIT.java b/src/test/java/org/teapot/backend/test/repository/MemberRepositoryIT.java
new file mode 100644
index 0000000..e71e0ad
--- /dev/null
+++ b/src/test/java/org/teapot/backend/test/repository/MemberRepositoryIT.java
@@ -0,0 +1,111 @@
+package org.teapot.backend.test.repository;
+
+import org.assertj.core.util.Lists;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.teapot.backend.model.organization.Member;
+import org.teapot.backend.model.organization.MemberStatus;
+import org.teapot.backend.model.organization.Organization;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.repository.organization.MemberRepository;
+import org.teapot.backend.repository.organization.OrganizationRepository;
+import org.teapot.backend.repository.user.UserRepository;
+import org.teapot.backend.test.AbstractIT;
+
+import java.time.LocalDate;
+import java.util.Arrays;
+
+
+public class MemberRepositoryIT extends AbstractIT {
+
+ @Autowired
+ private OrganizationRepository organizationRepository;
+
+ @Autowired
+ private MemberRepository memberRepository;
+
+ @Autowired
+ private UserRepository userRepository;
+
+ private Organization memberRepositoryTestOrg = new Organization();
+ private Organization findByUserTestOrg = new Organization();
+ private User user1;
+ private User user2;
+ private Member member1;
+ private Member member2;
+ private Member member3;
+
+ @Before
+ public void setup() {
+ memberRepository.deleteAllInBatch();
+ userRepository.deleteAllInBatch();
+ organizationRepository.deleteAllInBatch();
+
+ memberRepositoryTestOrg.setName("memberRepositoryTestOrg");
+ memberRepositoryTestOrg.setCreationDate(LocalDate.now());
+ organizationRepository.save(memberRepositoryTestOrg);
+
+ findByUserTestOrg.setName("findByUserTestOrg");
+ organizationRepository.save(findByUserTestOrg);
+
+ user1 = new User();
+ user1.setUsername("u1");
+ user1.setEmail("u1@email.com");
+ user1.setPassword("pass");
+ userRepository.save(user1);
+
+ member1 = new Member();
+ member1.setOrganization(memberRepositoryTestOrg);
+ member1.setAdmissionDate(LocalDate.now());
+ member1.setStatus(MemberStatus.CREATOR);
+ member1.setUser(user1);
+ memberRepository.save(member1);
+
+ user2 = new User();
+ user2.setUsername("u2");
+ user2.setEmail("u2@email.com");
+ user2.setPassword("pass");
+ userRepository.save(user2);
+
+ member2 = new Member();
+ member2.setOrganization(memberRepositoryTestOrg);
+ member2.setAdmissionDate(LocalDate.now());
+ member2.setStatus(MemberStatus.WORKER);
+ member2.setUser(user2);
+ memberRepository.save(member2);
+
+ member3 = new Member();
+ member3.setOrganization(findByUserTestOrg);
+ member3.setAdmissionDate(LocalDate.now());
+ member3.setStatus(MemberStatus.CREATOR);
+ member3.setUser(user1);
+ memberRepository.save(member3);
+ }
+
+ @Test
+ public void findAllByOrganizationTest() {
+ Assert.assertEquals(Arrays.asList(member1, member2),
+ memberRepository.findAllByOrganization(memberRepositoryTestOrg));
+ }
+
+ @Test
+ public void findByOrganizationAndIdTest() {
+ Assert.assertEquals(member1, memberRepository
+ .findByOrganizationAndId(memberRepositoryTestOrg, member1.getId()));
+ }
+
+ @Test
+ public void findByOrganizationAndUserTest() {
+ Assert.assertEquals(member2, memberRepository
+ .findByOrganizationAndUser(memberRepositoryTestOrg, user2));
+ }
+
+ @Test
+ public void findByUserTest() {
+ Assert.assertEquals(Lists.newArrayList(member1, member3)
+ ,memberRepository.findByUser(user1)
+ );
+ }
+}
diff --git a/src/test/java/org/teapot/backend/test/repository/OrganizationRepositoryIT.java b/src/test/java/org/teapot/backend/test/repository/OrganizationRepositoryIT.java
new file mode 100644
index 0000000..a5aa074
--- /dev/null
+++ b/src/test/java/org/teapot/backend/test/repository/OrganizationRepositoryIT.java
@@ -0,0 +1,35 @@
+package org.teapot.backend.test.repository;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.teapot.backend.model.organization.Organization;
+import org.teapot.backend.repository.organization.OrganizationRepository;
+import org.teapot.backend.test.AbstractIT;
+
+import java.time.LocalDate;
+
+
+public class OrganizationRepositoryIT extends AbstractIT {
+
+ @Autowired
+ private OrganizationRepository organizationRepository;
+
+ private Organization findByNameTestOrganization = new Organization();
+
+ @Before
+ public void setup() {
+ findByNameTestOrganization.setName("findByNameTestOrganization");
+ findByNameTestOrganization.setCreationDate(LocalDate.now());
+ organizationRepository.save(findByNameTestOrganization);
+ }
+
+ @Test
+ public void findByNameTest() {
+ Organization fromDataBase = organizationRepository
+ .findByName("findByNameTestOrganization");
+ Assert.assertNotNull(fromDataBase);
+ Assert.assertEquals(findByNameTestOrganization, fromDataBase);
+ }
+}
diff --git a/src/test/java/org/teapot/backend/test/repository/TeapotPropertyRepositoryIT.java b/src/test/java/org/teapot/backend/test/repository/TeapotPropertyRepositoryIT.java
index ca0d3b1..fc34fa2 100644
--- a/src/test/java/org/teapot/backend/test/repository/TeapotPropertyRepositoryIT.java
+++ b/src/test/java/org/teapot/backend/test/repository/TeapotPropertyRepositoryIT.java
@@ -5,7 +5,7 @@
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.teapot.backend.model.meta.TeapotProperty;
-import org.teapot.backend.repository.TeapotPropertyRepository;
+import org.teapot.backend.repository.meta.TeapotPropertyRepository;
import org.teapot.backend.test.AbstractIT;
public class TeapotPropertyRepositoryIT extends AbstractIT {
diff --git a/src/test/java/org/teapot/backend/test/repository/UserRepositoryIT.java b/src/test/java/org/teapot/backend/test/repository/UserRepositoryIT.java
index a74e460..e0b2146 100644
--- a/src/test/java/org/teapot/backend/test/repository/UserRepositoryIT.java
+++ b/src/test/java/org/teapot/backend/test/repository/UserRepositoryIT.java
@@ -5,9 +5,9 @@
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
-import org.teapot.backend.model.User;
-import org.teapot.backend.model.UserAuthority;
-import org.teapot.backend.repository.UserRepository;
+import org.teapot.backend.model.user.User;
+import org.teapot.backend.model.user.UserAuthority;
+import org.teapot.backend.repository.user.UserRepository;
import org.teapot.backend.test.AbstractIT;