Merge branch 'master' of ssh://dev.hostsharing.net:29418/hsadmin/hsadmin-ng
This commit is contained in:
commit
070f321a06
41
package-lock.json
generated
41
package-lock.json
generated
@ -6025,7 +6025,8 @@
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
@ -6046,12 +6047,14 @@
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@ -6066,17 +6069,20 @@
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
@ -6193,7 +6199,8 @@
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
@ -6205,6 +6212,7 @@
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
@ -6219,6 +6227,7 @@
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
@ -6226,12 +6235,14 @@
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
@ -6250,6 +6261,7 @@
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
@ -6330,7 +6342,8 @@
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@ -6342,6 +6355,7 @@
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@ -6427,7 +6441,8 @@
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
@ -6463,6 +6478,7 @@
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
@ -6482,6 +6498,7 @@
|
||||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
@ -6525,12 +6542,14 @@
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1,11 +1,11 @@
|
||||
package org.hostsharing.hsadminng;
|
||||
|
||||
import io.github.jhipster.config.JHipsterConstants;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hostsharing.hsadminng.config.ApplicationProperties;
|
||||
import org.hostsharing.hsadminng.config.DefaultProfileUtil;
|
||||
|
||||
import io.github.jhipster.config.JHipsterConstants;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hostsharing.hsadminng.security.SecurityUtils;
|
||||
import org.hostsharing.hsadminng.service.accessfilter.Role;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@ -41,6 +41,10 @@ public class HsadminNgApp {
|
||||
*/
|
||||
@PostConstruct
|
||||
public void initApplication() {
|
||||
|
||||
// TODO: remove this hack once proper user roles are implemented
|
||||
SecurityUtils.addUserRole(null, null, Role.HOSTMASTER);
|
||||
|
||||
Collection<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
|
||||
if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
|
||||
log.error("You have misconfigured your application! It should not run " +
|
||||
|
@ -2,17 +2,16 @@ package org.hostsharing.hsadminng.domain;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import org.hostsharing.hsadminng.domain.enumeration.AssetAction;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hostsharing.hsadminng.domain.enumeration.AssetAction;
|
||||
|
||||
/**
|
||||
* A Asset.
|
||||
*/
|
||||
|
@ -1,20 +1,16 @@
|
||||
package org.hostsharing.hsadminng.domain;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.hostsharing.hsadminng.domain.enumeration.CustomerKind;
|
||||
import org.hostsharing.hsadminng.domain.enumeration.VatRegion;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hostsharing.hsadminng.domain.enumeration.CustomerKind;
|
||||
|
||||
import org.hostsharing.hsadminng.domain.enumeration.VatRegion;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A Customer.
|
||||
@ -99,13 +95,21 @@ public class Customer implements Serializable {
|
||||
|
||||
@OneToMany(mappedBy = "customer")
|
||||
private Set<Membership> memberships = new HashSet<>();
|
||||
|
||||
@OneToMany(mappedBy = "customer")
|
||||
private Set<SepaMandate> sepamandates = new HashSet<>();
|
||||
|
||||
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Customer id(long id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
@ -354,6 +358,7 @@ public class Customer implements Serializable {
|
||||
public void setSepamandates(Set<SepaMandate> sepaMandates) {
|
||||
this.sepamandates = sepaMandates;
|
||||
}
|
||||
|
||||
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
|
||||
|
||||
@Override
|
||||
|
@ -1,17 +1,16 @@
|
||||
package org.hostsharing.hsadminng.domain;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A Membership.
|
||||
@ -49,18 +48,26 @@ public class Membership implements Serializable {
|
||||
|
||||
@OneToMany(mappedBy = "membership")
|
||||
private Set<Share> shares = new HashSet<>();
|
||||
|
||||
@OneToMany(mappedBy = "membership")
|
||||
private Set<Asset> assets = new HashSet<>();
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@NotNull
|
||||
@JsonIgnoreProperties("memberships")
|
||||
private Customer customer;
|
||||
|
||||
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Membership id(Long id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
@ -192,6 +199,7 @@ public class Membership implements Serializable {
|
||||
public void setCustomer(Customer customer) {
|
||||
this.customer = customer;
|
||||
}
|
||||
|
||||
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
|
||||
|
||||
@Override
|
||||
|
@ -4,8 +4,8 @@ package org.hostsharing.hsadminng.domain;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
|
@ -2,16 +2,15 @@ package org.hostsharing.hsadminng.domain;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import org.hostsharing.hsadminng.domain.enumeration.ShareAction;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hostsharing.hsadminng.domain.enumeration.ShareAction;
|
||||
|
||||
/**
|
||||
* A Share.
|
||||
*/
|
||||
|
@ -5,8 +5,12 @@ package org.hostsharing.hsadminng.security;
|
||||
*/
|
||||
public final class AuthoritiesConstants {
|
||||
|
||||
public static final String HOSTMASTER = "ROLE_HOSTMASTER";
|
||||
|
||||
public static final String ADMIN = "ROLE_ADMIN";
|
||||
|
||||
public static final String SUPPORTER = "ROLE_SUPPORTER";
|
||||
|
||||
public static final String USER = "ROLE_USER";
|
||||
|
||||
public static final String ANONYMOUS = "ROLE_ANONYMOUS";
|
||||
|
@ -1,9 +1,12 @@
|
||||
package org.hostsharing.hsadminng.security;
|
||||
|
||||
import org.hostsharing.hsadminng.service.accessfilter.Role;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@ -11,6 +14,8 @@ import java.util.Optional;
|
||||
*/
|
||||
public final class SecurityUtils {
|
||||
|
||||
private static List<UserRoleAssignment> userRoleAssignments = new ArrayList<>();
|
||||
|
||||
private SecurityUtils() {
|
||||
}
|
||||
|
||||
@ -73,4 +78,41 @@ public final class SecurityUtils {
|
||||
.anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority)))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
public static Role getLoginUserRoleFor(final Class<?> onDtoClass, final Long onId) {
|
||||
final Role highestRole = userRoleAssignments.stream().
|
||||
map(ura ->
|
||||
matches(onDtoClass, onId, ura)
|
||||
? ura.role
|
||||
: Role.ANYBODY).
|
||||
reduce(Role.ANYBODY, (r1, r2) -> r1.covers(r2) ? r1 : r2);
|
||||
return highestRole;
|
||||
}
|
||||
|
||||
private static boolean matches(Class<?> onDtoClass, Long onId, UserRoleAssignment ura) {
|
||||
final boolean matches = (ura.onClass == null || onDtoClass == ura.onClass) && (ura.onId == null || ura.onId.equals(onId));
|
||||
return matches;
|
||||
}
|
||||
|
||||
// TODO: depends on https://plan.hostsharing.net/project/hsadmin/us/67?milestone=34
|
||||
public static void addUserRole(final Class<?> onClass, final Long onId, final Role role) {
|
||||
userRoleAssignments.add(new UserRoleAssignment(onClass, onId, role));
|
||||
|
||||
}
|
||||
|
||||
public static void clearUserRoles() {
|
||||
userRoleAssignments.clear();
|
||||
}
|
||||
|
||||
private static class UserRoleAssignment {
|
||||
final Class<?> onClass;
|
||||
final Long onId;
|
||||
final Role role;
|
||||
|
||||
UserRoleAssignment(Class<?> onClass, Long onId, Role role) {
|
||||
this.onClass = onClass;
|
||||
this.onId = onId;
|
||||
this.role = role;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import org.hostsharing.hsadminng.service.dto.AssetDTO;
|
||||
import org.hostsharing.hsadminng.service.mapper.AssetMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -1,9 +1,14 @@
|
||||
package org.hostsharing.hsadminng.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.criteria.JoinType;
|
||||
|
||||
import io.github.jhipster.service.QueryService;
|
||||
import org.hostsharing.hsadminng.domain.Customer;
|
||||
import org.hostsharing.hsadminng.domain.Customer_;
|
||||
import org.hostsharing.hsadminng.domain.Membership_;
|
||||
import org.hostsharing.hsadminng.domain.SepaMandate_;
|
||||
import org.hostsharing.hsadminng.repository.CustomerRepository;
|
||||
import org.hostsharing.hsadminng.service.dto.CustomerCriteria;
|
||||
import org.hostsharing.hsadminng.service.dto.CustomerDTO;
|
||||
import org.hostsharing.hsadminng.service.mapper.CustomerMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
@ -12,14 +17,8 @@ import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import io.github.jhipster.service.QueryService;
|
||||
|
||||
import org.hostsharing.hsadminng.domain.Customer;
|
||||
import org.hostsharing.hsadminng.domain.*; // for static metamodels
|
||||
import org.hostsharing.hsadminng.repository.CustomerRepository;
|
||||
import org.hostsharing.hsadminng.service.dto.CustomerCriteria;
|
||||
import org.hostsharing.hsadminng.service.dto.CustomerDTO;
|
||||
import org.hostsharing.hsadminng.service.mapper.CustomerMapper;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Service for executing complex queries for Customer entities in the database.
|
||||
|
@ -6,7 +6,6 @@ import org.hostsharing.hsadminng.service.dto.CustomerDTO;
|
||||
import org.hostsharing.hsadminng.service.mapper.CustomerMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -19,7 +18,7 @@ import java.util.Optional;
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class CustomerService {
|
||||
public class CustomerService implements IdToDtoResolver<CustomerDTO> {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(CustomerService.class);
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
package org.hostsharing.hsadminng.service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface IdToDtoResolver<T> {
|
||||
Optional<T> findOne(Long id);
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
package org.hostsharing.hsadminng.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.criteria.JoinType;
|
||||
|
||||
import io.github.jhipster.service.QueryService;
|
||||
import org.hostsharing.hsadminng.domain.*;
|
||||
import org.hostsharing.hsadminng.repository.MembershipRepository;
|
||||
import org.hostsharing.hsadminng.service.dto.MembershipCriteria;
|
||||
import org.hostsharing.hsadminng.service.dto.MembershipDTO;
|
||||
import org.hostsharing.hsadminng.service.mapper.MembershipMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
@ -12,14 +14,8 @@ import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import io.github.jhipster.service.QueryService;
|
||||
|
||||
import org.hostsharing.hsadminng.domain.Membership;
|
||||
import org.hostsharing.hsadminng.domain.*; // for static metamodels
|
||||
import org.hostsharing.hsadminng.repository.MembershipRepository;
|
||||
import org.hostsharing.hsadminng.service.dto.MembershipCriteria;
|
||||
import org.hostsharing.hsadminng.service.dto.MembershipDTO;
|
||||
import org.hostsharing.hsadminng.service.mapper.MembershipMapper;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Service for executing complex queries for Membership entities in the database.
|
||||
|
@ -19,7 +19,7 @@ import java.util.Optional;
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class MembershipService {
|
||||
public class MembershipService implements IdToDtoResolver<MembershipDTO> {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(MembershipService.class);
|
||||
|
||||
@ -73,6 +73,7 @@ public class MembershipService {
|
||||
* @param id the id of the entity
|
||||
* @return the entity
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Optional<MembershipDTO> findOne(Long id) {
|
||||
log.debug("Request to get Membership : {}", id);
|
||||
|
@ -1,9 +1,13 @@
|
||||
package org.hostsharing.hsadminng.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.criteria.JoinType;
|
||||
|
||||
import io.github.jhipster.service.QueryService;
|
||||
import org.hostsharing.hsadminng.domain.Customer_;
|
||||
import org.hostsharing.hsadminng.domain.SepaMandate;
|
||||
import org.hostsharing.hsadminng.domain.SepaMandate_;
|
||||
import org.hostsharing.hsadminng.repository.SepaMandateRepository;
|
||||
import org.hostsharing.hsadminng.service.dto.SepaMandateCriteria;
|
||||
import org.hostsharing.hsadminng.service.dto.SepaMandateDTO;
|
||||
import org.hostsharing.hsadminng.service.mapper.SepaMandateMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
@ -12,14 +16,8 @@ import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import io.github.jhipster.service.QueryService;
|
||||
|
||||
import org.hostsharing.hsadminng.domain.SepaMandate;
|
||||
import org.hostsharing.hsadminng.domain.*; // for static metamodels
|
||||
import org.hostsharing.hsadminng.repository.SepaMandateRepository;
|
||||
import org.hostsharing.hsadminng.service.dto.SepaMandateCriteria;
|
||||
import org.hostsharing.hsadminng.service.dto.SepaMandateDTO;
|
||||
import org.hostsharing.hsadminng.service.mapper.SepaMandateMapper;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Service for executing complex queries for SepaMandate entities in the database.
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.hostsharing.hsadminng.service;
|
||||
|
||||
import org.hostsharing.hsadminng.domain.Share;
|
||||
import org.hostsharing.hsadminng.domain.enumeration.ShareAction;
|
||||
import org.hostsharing.hsadminng.repository.ShareRepository;
|
||||
import org.hostsharing.hsadminng.service.dto.ShareDTO;
|
||||
import org.hostsharing.hsadminng.service.mapper.ShareMapper;
|
||||
@ -20,7 +19,7 @@ import java.util.Optional;
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class ShareService {
|
||||
public class ShareService implements IdToDtoResolver<ShareDTO> {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(ShareService.class);
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
package org.hostsharing.hsadminng.service.accessfilter;
|
||||
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Documented
|
||||
@Target({ElementType.FIELD, ElementType.TYPE_USE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface AccessFor {
|
||||
Role[] init() default Role.NOBODY;
|
||||
|
||||
Role[] update() default Role.NOBODY;
|
||||
|
||||
Role[] read() default Role.NOBODY;
|
||||
}
|
||||
|
@ -0,0 +1,121 @@
|
||||
package org.hostsharing.hsadminng.service.accessfilter;
|
||||
|
||||
import org.hostsharing.hsadminng.security.SecurityUtils;
|
||||
import org.hostsharing.hsadminng.service.IdToDtoResolver;
|
||||
import org.hostsharing.hsadminng.service.dto.MembershipDTO;
|
||||
import org.hostsharing.hsadminng.service.util.ReflectionUtil;
|
||||
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import static com.google.common.base.Verify.verify;
|
||||
|
||||
abstract class JSonAccessFilter<T> {
|
||||
private final ApplicationContext ctx;
|
||||
final T dto;
|
||||
final Field selfIdField;
|
||||
final Field parentIdField;
|
||||
|
||||
JSonAccessFilter(final ApplicationContext ctx, final T dto) {
|
||||
this.ctx = ctx;
|
||||
this.dto = dto;
|
||||
this.selfIdField = determineFieldWithAnnotation(dto.getClass(), SelfId.class);
|
||||
this.parentIdField = determineFieldWithAnnotation(dto.getClass(), ParentId.class);
|
||||
}
|
||||
|
||||
boolean isParentIdField(final Field field) {
|
||||
return field.equals(parentIdField);
|
||||
}
|
||||
|
||||
Long getId() {
|
||||
if (selfIdField == null) {
|
||||
return null;
|
||||
}
|
||||
return (Long) ReflectionUtil.getValue(dto, selfIdField);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param field to get a display representation for
|
||||
* @return a simplified, decently user readable, display representation of the given field
|
||||
*/
|
||||
String toDisplay(final Field field) {
|
||||
return field.getDeclaringClass().getSimpleName() + "." + field.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the role of the login user in relation to the dto, this filter is created for.
|
||||
*/
|
||||
Role getLoginUserRole() {
|
||||
final Role roleOnSelf = getLoginUserRoleOnSelf();
|
||||
if (roleOnSelf.isIndependent()) {
|
||||
return roleOnSelf;
|
||||
}
|
||||
return getLoginUserRoleOnAncestorOfDtoClassIfHigher(roleOnSelf, dto);
|
||||
}
|
||||
|
||||
private Role getLoginUserRoleOnSelf() {
|
||||
return SecurityUtils.getLoginUserRoleFor(dto.getClass(), getId());
|
||||
}
|
||||
|
||||
private Role getLoginUserRoleOnAncestorOfDtoClassIfHigher(final Role baseRole, final Object dto) {
|
||||
final Field parentIdField = determineFieldWithAnnotation(dto.getClass(), ParentId.class);
|
||||
|
||||
if (parentIdField == null) {
|
||||
return baseRole;
|
||||
}
|
||||
|
||||
final ParentId parentIdAnnot = parentIdField.getAnnotation(ParentId.class);
|
||||
final Class<? extends IdToDtoResolver> parentDtoLoader = parentIdAnnot.resolver();
|
||||
final Class<?> parentDtoClass = getGenericClassParameter(parentDtoLoader);
|
||||
final Long parentId = (Long) ReflectionUtil.getValue(dto, parentIdField);
|
||||
final Role roleOnParent = SecurityUtils.getLoginUserRoleFor(parentDtoClass, parentId);
|
||||
|
||||
final Object parentEntity = loadDto(parentDtoLoader, parentId);
|
||||
return Role.broadest(baseRole, getLoginUserRoleOnAncestorOfDtoClassIfHigher(roleOnParent, parentEntity));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<T> getGenericClassParameter(Class<? extends IdToDtoResolver> parentDtoLoader) {
|
||||
for (Type genericInterface : parentDtoLoader.getGenericInterfaces()) {
|
||||
if (genericInterface instanceof ParameterizedType) {
|
||||
final ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
|
||||
if (parameterizedType.getRawType()== IdToDtoResolver.class) {
|
||||
return (Class<T>) parameterizedType.getActualTypeArguments()[0];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
throw new AssertionError(parentDtoLoader.getSimpleName() + " expected to implement " + IdToDtoResolver.class.getSimpleName() + "<...DTO>");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object loadDto(final Class<? extends IdToDtoResolver> resolverClass, final Long id) {
|
||||
verify(id != null, "id must not be null");
|
||||
|
||||
final AutowireCapableBeanFactory beanFactory = ctx.getAutowireCapableBeanFactory();
|
||||
verify(beanFactory != null, "no bean factory found, probably missing mock configuration for ApplicationContext, e.g. given(...)");
|
||||
|
||||
final IdToDtoResolver<MembershipDTO> resolverBean = beanFactory.createBean(resolverClass);
|
||||
verify(resolverBean != null, "no " + resolverClass.getSimpleName() + " bean created, probably missing mock configuration for AutowireCapableBeanFactory, e.g. given(...)");
|
||||
|
||||
return resolverBean.findOne(id).orElseThrow(() -> new BadRequestAlertException("Can't resolve entity ID " + id + " via " + resolverClass, resolverClass.getSimpleName(), "isNotFound"));
|
||||
}
|
||||
|
||||
private static Field determineFieldWithAnnotation(final Class<?> dtoClass, final Class<? extends Annotation> idAnnotationClass) {
|
||||
Field parentIdField = null;
|
||||
for (Field field : dtoClass.getDeclaredFields()) {
|
||||
if (field.isAnnotationPresent(idAnnotationClass)) {
|
||||
if (parentIdField != null) {
|
||||
throw new AssertionError("multiple @" + idAnnotationClass.getSimpleName() + " detected in " + field.getDeclaringClass().getSimpleName());
|
||||
}
|
||||
parentIdField = field;
|
||||
}
|
||||
}
|
||||
return parentIdField;
|
||||
}
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
package org.hostsharing.hsadminng.service.accessfilter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.TreeNode;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.node.*;
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.hostsharing.hsadminng.service.util.ReflectionUtil;
|
||||
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hostsharing.hsadminng.service.util.ReflectionUtil.unchecked;
|
||||
|
||||
public class JSonDeserializerWithAccessFilter<T> extends JSonAccessFilter<T> {
|
||||
|
||||
private final TreeNode treeNode;
|
||||
private final Set<Field> writtenFields = new HashSet<>();
|
||||
|
||||
public JSonDeserializerWithAccessFilter(final ApplicationContext ctx, final JsonParser jsonParser, final DeserializationContext deserializationContext, Class<T> dtoClass) {
|
||||
super(ctx, unchecked(dtoClass::newInstance));
|
||||
this.treeNode = unchecked(() -> jsonParser.getCodec().readTree(jsonParser));
|
||||
}
|
||||
|
||||
// Jackson deserializes from the JsonParser, thus no input parameter needed.
|
||||
public T deserialize() {
|
||||
deserializeValues();
|
||||
final T currentDto = loadCurrentDto(getId());
|
||||
overwriteUnmodifiedFieldsWithCurrentValues(currentDto);
|
||||
checkAccessToWrittenFields(currentDto);
|
||||
return dto;
|
||||
}
|
||||
|
||||
private void deserializeValues() {
|
||||
treeNode.fieldNames().forEachRemaining(fieldName -> {
|
||||
try {
|
||||
final Field field = dto.getClass().getDeclaredField(fieldName);
|
||||
final Object newValue = readValue(treeNode, field);
|
||||
writeValue(dto, field, newValue);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new RuntimeException("setting field " + fieldName + " failed", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private T loadCurrentDto(final Long id) {
|
||||
if (id != null) {
|
||||
return (T) loadDto(selfIdField.getAnnotation(SelfId.class).resolver(), id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void overwriteUnmodifiedFieldsWithCurrentValues(final Object currentDto) {
|
||||
if (currentDto == null) {
|
||||
return;
|
||||
}
|
||||
for (Field field : currentDto.getClass().getDeclaredFields()) {
|
||||
if (field.isAnnotationPresent(AccessFor.class) && !writtenFields.contains(field)) {
|
||||
final Object value = ReflectionUtil.getValue(currentDto, field);
|
||||
ReflectionUtil.setValue(dto, field, value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Object readValue(final TreeNode treeNode, final Field field) {
|
||||
return readValue(treeNode, field.getName(), field.getType());
|
||||
|
||||
}
|
||||
|
||||
private Object readValue(final TreeNode treeNode, final String fieldName, final Class<?> fieldClass) {
|
||||
final TreeNode fieldNode = treeNode.get(fieldName);
|
||||
if (fieldNode instanceof NullNode) {
|
||||
return null;
|
||||
}
|
||||
if (fieldNode instanceof TextNode) {
|
||||
return ((TextNode) fieldNode).asText();
|
||||
}
|
||||
if (fieldNode instanceof IntNode) {
|
||||
return ((IntNode) fieldNode).asInt();
|
||||
}
|
||||
if (fieldNode instanceof LongNode) {
|
||||
return ((LongNode) fieldNode).asLong();
|
||||
}
|
||||
if (fieldNode instanceof ArrayNode && LocalDate.class.isAssignableFrom(fieldClass)) {
|
||||
return LocalDate.of(((ArrayNode) fieldNode).get(0).asInt(), ((ArrayNode) fieldNode).get(1).asInt(), ((ArrayNode) fieldNode).get(2).asInt());
|
||||
}
|
||||
{
|
||||
throw new NotImplementedException("property type not yet implemented: " + fieldNode + " -> " + fieldName + ": " + fieldClass);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeValue(final T dto, final Field field, final Object value) {
|
||||
if (value == null) {
|
||||
ReflectionUtil.setValue(dto, field, null);
|
||||
} else if (field.getType().isAssignableFrom(value.getClass())) {
|
||||
ReflectionUtil.setValue(dto, field, value);
|
||||
} else if (Integer.class.isAssignableFrom(field.getType()) || int.class.isAssignableFrom(field.getType())) {
|
||||
ReflectionUtil.setValue(dto, field, ((Number) value).intValue());
|
||||
} else if (Long.class.isAssignableFrom(field.getType()) || long.class.isAssignableFrom(field.getType())) {
|
||||
ReflectionUtil.setValue(dto, field, ((Number) value).longValue());
|
||||
} else if (field.getType().isEnum()) {
|
||||
ReflectionUtil.setValue(dto, field, Enum.valueOf((Class<Enum>) field.getType(), value.toString()));
|
||||
} else if (LocalDate.class.isAssignableFrom(field.getType())) {
|
||||
ReflectionUtil.setValue(dto, field, LocalDate.parse(value.toString()));
|
||||
} else {
|
||||
throw new NotImplementedException("property type not yet implemented: " + field);
|
||||
}
|
||||
writtenFields.add(field);
|
||||
}
|
||||
|
||||
private void checkAccessToWrittenFields(final T currentDto) {
|
||||
writtenFields.forEach(field -> {
|
||||
if (!field.equals(selfIdField)) {
|
||||
final Role role = getLoginUserRole();
|
||||
if (getId() == null) {
|
||||
if (!role.isAllowedToInit(field)) {
|
||||
if (!field.equals(parentIdField)) {
|
||||
throw new BadRequestAlertException("Initialization of field " + toDisplay(field) + " prohibited for current user role " + role, toDisplay(field), "initializationProhibited");
|
||||
} else {
|
||||
throw new BadRequestAlertException("Referencing field " + toDisplay(field) + " prohibited for current user role " + role, toDisplay(field), "referencingProhibited");
|
||||
}
|
||||
}
|
||||
} else if (isUpdate(field, dto, currentDto) && !getLoginUserRole().isAllowedToUpdate(field)) {
|
||||
throw new BadRequestAlertException("Update of field " + toDisplay(field) + " prohibited for current user role " + role, toDisplay(field), "updateProhibited");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isUpdate(final Field field, final T dto, T currentDto) {
|
||||
return ObjectUtils.notEqual(ReflectionUtil.getValue(dto, field), ReflectionUtil.getValue(currentDto, field));
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package org.hostsharing.hsadminng.service.accessfilter;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class JSonSerializerWithAccessFilter<T> extends JSonAccessFilter<T> {
|
||||
private final JsonGenerator jsonGenerator;
|
||||
private final SerializerProvider serializerProvider;
|
||||
|
||||
public JSonSerializerWithAccessFilter(final ApplicationContext ctx,
|
||||
final JsonGenerator jsonGenerator,
|
||||
final SerializerProvider serializerProvider,
|
||||
final T dto) {
|
||||
super(ctx, dto);
|
||||
this.jsonGenerator = jsonGenerator;
|
||||
this.serializerProvider = serializerProvider;
|
||||
}
|
||||
|
||||
// Jackson serializes into the JsonGenerator, thus no return value needed.
|
||||
public void serialize() throws IOException {
|
||||
|
||||
jsonGenerator.writeStartObject();
|
||||
for (Field field : dto.getClass().getDeclaredFields()) {
|
||||
toJSon(dto, jsonGenerator, field);
|
||||
}
|
||||
jsonGenerator.writeEndObject();
|
||||
}
|
||||
|
||||
private void toJSon(final Object dto, final JsonGenerator jsonGenerator, final Field field) throws IOException {
|
||||
if (getLoginUserRole().isAllowedToRead(field)) {
|
||||
final String fieldName = field.getName();
|
||||
// TODO: maybe replace by serializerProvider.defaultSerialize...()?
|
||||
// But that makes it difficult for parallel structure with the deserializer (clumsy API).
|
||||
// Alternatively extract the supported types to subclasses of some abstract class and
|
||||
// here as well as in the deserializer just access the matching implementation through a map.
|
||||
// Or even completely switch from Jackson to GSON?
|
||||
final Object fieldValue = get(dto, field);
|
||||
if (fieldValue == null) {
|
||||
jsonGenerator.writeNullField(fieldName);
|
||||
} else if (Integer.class.isAssignableFrom(field.getType()) || int.class.isAssignableFrom(field.getType())) {
|
||||
jsonGenerator.writeNumberField(fieldName, (int) fieldValue);
|
||||
} else if (Long.class.isAssignableFrom(field.getType()) || long.class.isAssignableFrom(field.getType())) {
|
||||
jsonGenerator.writeNumberField(fieldName, (long) fieldValue);
|
||||
} else if (LocalDate.class.isAssignableFrom(field.getType())) {
|
||||
jsonGenerator.writeStringField(fieldName, fieldValue.toString()); // TODO proper format
|
||||
} else if (Enum.class.isAssignableFrom(field.getType())) {
|
||||
jsonGenerator.writeStringField(fieldName, fieldValue.toString()); // TODO proper representation
|
||||
} else if (String.class.isAssignableFrom(field.getType())) {
|
||||
jsonGenerator.writeStringField(fieldName, (String) fieldValue);
|
||||
} else {
|
||||
throw new NotImplementedException("property type not yet implemented: " + field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object get(final Object dto, final Field field) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
return field.get(dto);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException("getting field " + field + " failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package org.hostsharing.hsadminng.service.accessfilter;
|
||||
|
||||
import org.hostsharing.hsadminng.service.IdToDtoResolver;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Used to mark a field within a DTO as containing the id of a referenced entity,
|
||||
* it's needed to determine access rights for entity creation.
|
||||
*
|
||||
* @see AccessFor
|
||||
*/
|
||||
@Documented
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ParentId {
|
||||
/// The service which can load the referenced DTO.
|
||||
Class<? extends IdToDtoResolver<?>> resolver();
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
package org.hostsharing.hsadminng.service.accessfilter;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* These enum values are on the one hand used to define the minimum role required to grant access to resources,
|
||||
* but on the other hand also for the roles users can be assigned to.
|
||||
*
|
||||
* TODO: Maybe splitting it up into UserRole and RequiredRole would make it more clear?
|
||||
* And maybe instead of a level, we could then add the comprised roles in the constructor?
|
||||
* This could also be a better way to express that the financial contact has no rights to
|
||||
* other users resources (see also ACTUAL_CUSTOMER_USEr vs. ANY_CUSTOMER_USER).
|
||||
*/
|
||||
public enum Role {
|
||||
/**
|
||||
* Default for access rights requirement. You can read it as: 'Nobody is allowed to ...'.
|
||||
* This is usually used for fields which are managed by hsadminNg itself.
|
||||
*/
|
||||
NOBODY(0),
|
||||
|
||||
/**
|
||||
* Hostmasters are initialize/update/read and field which, except where NOBODY is allowed to.
|
||||
*/
|
||||
HOSTMASTER(1),
|
||||
|
||||
/**
|
||||
* This role is for administrators, e.g. to create memberships and book shared and assets.
|
||||
*/
|
||||
ADMIN(2),
|
||||
|
||||
/**
|
||||
* This role is for members of the support team.
|
||||
*/
|
||||
SUPPORTER(3),
|
||||
|
||||
/**
|
||||
* This role is for contractual contacts of a customer, like a director of the company.
|
||||
* Who has this role, has the broadest access to all resources which belong to this customer.
|
||||
* Everything which relates to the contract with the customer, needs this role.
|
||||
*/
|
||||
CONTRACTUAL_CONTACT(20),
|
||||
|
||||
/**
|
||||
* This role is for financial contacts of a customer, e.g. for accessing billing data.
|
||||
*/
|
||||
FINANCIAL_CONTACT(22) {
|
||||
@Override
|
||||
public boolean covers(final Role role) {
|
||||
if (role == ACTUAL_CUSTOMER_USER) {
|
||||
return false;
|
||||
}
|
||||
return super.covers(role);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This role is for technical contacts of a customer.
|
||||
*/
|
||||
TECHNICAL_CONTACT(22),
|
||||
|
||||
|
||||
/**
|
||||
* This meta-role is to specify that any kind of customer contact can get access to the resource.
|
||||
*/
|
||||
ANY_CUSTOMER_CONTACT(29),
|
||||
|
||||
/**
|
||||
* Any user which belongs to a customer has at least this role.
|
||||
*/
|
||||
ACTUAL_CUSTOMER_USER(80),
|
||||
|
||||
/**
|
||||
* Use this to grant rights to any user, also special function users who have no
|
||||
* rights on other users resources.
|
||||
*/
|
||||
ANY_CUSTOMER_USER(89),
|
||||
|
||||
/**
|
||||
* This role is meant to specify that a resources can be accessed by anybody, even without login.
|
||||
* It's currently only used for technical purposes.
|
||||
*/
|
||||
ANYBODY(99);
|
||||
|
||||
private final int level;
|
||||
|
||||
Role(final int level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this role is independent of a target object, false otherwise.
|
||||
*/
|
||||
public boolean isIndependent() {
|
||||
return covers(Role.SUPPORTER);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the role with the broadest access rights
|
||||
*/
|
||||
public static Role broadest(final Role role, final Role... roles) {
|
||||
Role broadests = role;
|
||||
for ( Role r: roles ) {
|
||||
if ( r.covers(broadests)) {
|
||||
broadests = r;
|
||||
}
|
||||
}
|
||||
return broadests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the given role is covered by this role.
|
||||
*
|
||||
* Where 'this' means the Java instance itself as a role of a system user.
|
||||
*
|
||||
* {@code
|
||||
* Role.HOSTMASTER.covers(Role.ANY_CUSTOMER_USER) == true
|
||||
* }
|
||||
*
|
||||
* @param role The required role for a resource.
|
||||
*
|
||||
* @return whether this role comprises the given role
|
||||
*/
|
||||
public boolean covers(final Role role) {
|
||||
return this == role || this.level < role.level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this role of a user allows to initialize the given field when creating the resource.
|
||||
*
|
||||
* @param field a field of the DTO of a resource
|
||||
*
|
||||
* @return true if allowed
|
||||
*/
|
||||
public boolean isAllowedToInit(final Field field) {
|
||||
|
||||
final AccessFor accessFor = field.getAnnotation(AccessFor.class);
|
||||
if (accessFor == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isRoleCovered(accessFor.init());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this role of a user allows to update the given field.
|
||||
*
|
||||
* @param field a field of the DTO of a resource
|
||||
*
|
||||
* @return true if allowed
|
||||
*/
|
||||
public boolean isAllowedToUpdate(final Field field) {
|
||||
|
||||
final AccessFor accessFor = field.getAnnotation(AccessFor.class);
|
||||
if (accessFor == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isRoleCovered(accessFor.update());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this role of a user allows to read the given field.
|
||||
*
|
||||
* @param field a field of the DTO of a resource
|
||||
*
|
||||
* @return true if allowed
|
||||
*/
|
||||
public boolean isAllowedToRead(final Field field) {
|
||||
|
||||
final AccessFor accessFor = field.getAnnotation(AccessFor.class);
|
||||
if (accessFor == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isRoleCovered(accessFor.read());
|
||||
}
|
||||
|
||||
private boolean isRoleCovered(final Role[] requiredRoles) {
|
||||
for (Role accessAllowedForRole : requiredRoles) {
|
||||
if (this.covers(accessAllowedForRole)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package org.hostsharing.hsadminng.service.accessfilter;
|
||||
|
||||
import org.hostsharing.hsadminng.service.IdToDtoResolver;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Used to mark a field within a DTO as containing the own id,
|
||||