Description brève : Je veux que spring-data-rest ne génère que des points de terminaison comme "/users/{userId}/settings", "/users/{userId}/values" et non pas "/settings" ou "/values".
Plus de détails :
J'ai commencé à être ennuyé de vérifier dans chaque fonction du contrôleur si l'utilisateur connecté a accès à la ressource demandée et j'ai eu l'idée suivante pour automatiser cela (si quelqu'un a une meilleure idée qui ne cause pas les problèmes ci-dessous, je serais heureux de l'entendre)
Dans mon application, l'utilisateur n'a accès qu'à sa propre ressource et ne peut pas voir les données des autres utilisateurs.
Ainsi, j'ai pensé à restreindre (avec la configuration de Websecurity) tous les chemins commençant par "/users/{id}**" pour permettre uniquement l'accès lorsque l'utilisateur connecté possède l'identifiant donné. De cette manière, si mes points de terminaison sont par exemple "/users/{userId}/userValues" ou "/users/{userId}/settings", etc., chaque utilisateur ne peut accéder qu'à ses propres données en raison de la règle de permission
Pour automatiser davantage le processus et pour m'assurer que je n'oublie pas de vérifier l'userId dans le contrôleur, j'ai essayé d'utiliser spring-data-rest qui est génial sauf un problème :
spring-data-rest génère un point d'API pour chaque objet. Ils ressemblent à ceci :
"/settings", "/users", "/values".
Les chemins que je souhaite sont également générés : "/users/{userId}/values" et "/users/{userId}/values" et il vérifie correctement l'userId, donc mon idée semble fonctionner en principe.
Cependant, je n'arrive pas à comprendre comment désactiver les points de terminaison où le chemin commence par l'enfant ("/settings", "/values".) puisque je veux seulement que les points de terminaison commençant par "/users/{userId}" soient disponibles.
Est-ce possible ? Ou y a-t-il un meilleur moyen d'assurer que les utilisateurs ne peuvent voir et modifier que leurs propres données ?
Voici les classes de mon projet pour tester ce scénario (Je sais que le nommage est horrible, je vais mettre en place un nouveau projet si je sais que je peux faire fonctionner cela, c'est juste pour tester) :
Dépendances Gradle :
dependencies {
compile("org.springframework.boot:spring-boot-starter")
//web frontend
compile("org.springframework.boot:spring-boot-starter-web")
//rest endpoint generator
compile("org.springframework.boot:spring-boot-starter-data-rest")
//database connection
compile("mysql:mysql-connector-java")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
//Swagger (/v2/api-docs)
compile("io.springfox:springfox-swagger2:2.9.2")
//pretty swagger (/swagger-ui.html)
compile("io.springfox:springfox-swagger-ui:2.9.2")
//Lombok (automatic getter / setter)
compile("org.projectlombok:lombok:1.18.6")
}
Utilisateur :
@Entity
@Getter
@Setter
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String firstName;
private String lastName;
@OneToMany(mappedBy="user", cascade= CascadeType.ALL)
private List values;
@OneToOne
@RestResource(path = "settings", rel = "SettingsRel")
private Settings settings;
}
UserValue
@Entity
public class UserValue {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Integer id;
String value;
@ManyToOne
@JoinColumn(name = "user_id")
@JsonIgnore
private User user;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
Paramètres :
@Entity
@Getter
@Setter
public class Settings {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Integer id;
private HashMap settings;
}
UserValueRepository :
public interface UserValueRepository extends CrudRepository {
}
UserRepository :
public interface UserRepository extends CrudRepository {
}
SettingsRepository :
public interface SettingsRepository extends CrudRepository {
}
Deux problèmes supplémentaires que j'ai avec spring-data-rest sont qu'il semble ne pas fonctionner avec Swagger et Lombok. Je suis donc encore plus ouvert à des moyens alternatifs pour atteindre mon objectif.