Compare commits
9 Commits
de98ed5cc5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3573f862eb | ||
|
|
39d75aecf9 | ||
|
|
6949d8e083 | ||
|
|
db27bcc1f7 | ||
|
|
e0807e4539 | ||
|
|
fbdaa35087 | ||
|
|
f579af11a7 | ||
|
|
7c70af6a8c | ||
|
|
3796e6f190 |
40
.classpath
40
.classpath
@@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<classpath>
|
|
||||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
|
||||||
</classpath>
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -24,3 +24,4 @@
|
|||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
replay_pid*
|
replay_pid*
|
||||||
|
|
||||||
|
.idea
|
||||||
|
|||||||
23
.project
23
.project
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>backend</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
eclipse.preferences.version=1
|
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
|
||||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
|
||||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
|
||||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
|
||||||
org.eclipse.jdt.core.compiler.release=disabled
|
|
||||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
activeProfiles=
|
|
||||||
eclipse.preferences.version=1
|
|
||||||
resolveWorkspaceProjects=true
|
|
||||||
version=1
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
# miarma-backend
|
# miarma-backend
|
||||||
|
|
||||||
Backend that powers all my services.
|
Backend that provides auth and management for my self-hosted microservices
|
||||||
18
TODO
Normal file
18
TODO
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
POR HACER --------------------------------
|
||||||
|
- implementar urlParams para filtros
|
||||||
|
- documentación
|
||||||
|
- mail wrapper
|
||||||
|
|
||||||
|
RESUELTO ---------------------------------
|
||||||
|
- añadir colaborador desde perfil
|
||||||
|
- apuntarse lista espera
|
||||||
|
- aceptar solicitudes LE/Colab (sobre todo por crear preusers)
|
||||||
|
- mejorar queries para no filtrar en memoria -> IMPOSIBLE CON ENDPOINTS INTERNOS DE CORE: RESUELTO CON CACHING
|
||||||
|
- normalizar el uso de services y repositories desde otros services y repositories
|
||||||
|
- sistema comun de errores en back & front
|
||||||
|
- nombre del requester
|
||||||
|
- cambiar contraseña (?)
|
||||||
|
- todos los socios en dropdown ingresos
|
||||||
|
- validacion LE/COlab
|
||||||
|
- createdAt custom en ing,gastos
|
||||||
|
- editar createdAt
|
||||||
9
backend.iml
Normal file
9
backend.iml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module version="4">
|
||||||
|
<component name="AdditionalModuleElements">
|
||||||
|
<content url="file://$MODULE_DIR$" dumb="true">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||||
|
</content>
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
9
backlib/backlib.iml
Normal file
9
backlib/backlib.iml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module version="4">
|
||||||
|
<component name="AdditionalModuleElements">
|
||||||
|
<content url="file://$MODULE_DIR$" dumb="true">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||||
|
</content>
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
91
backlib/pom.xml
Normal file
91
backlib/pom.xml
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>backlib</artifactId>
|
||||||
|
<groupId>net.miarma</groupId>
|
||||||
|
<version>1.1.1</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>25</java.version>
|
||||||
|
<spring.boot.version>4.0.1</spring.boot.version>
|
||||||
|
<maven.compiler.source>25</maven.compiler.source>
|
||||||
|
<maven.compiler.target>25</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>MiarmaGit</id>
|
||||||
|
<url>https://git.miarma.net/api/packages/Gallardo7761/maven</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>MiarmaGit</id>
|
||||||
|
<url>https://git.miarma.net/api/packages/Gallardo7761/maven</url>
|
||||||
|
</repository>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>MiarmaGit</id>
|
||||||
|
<url>https://git.miarma.net/api/packages/Gallardo7761/maven</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>${spring.boot.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mariadb.jdbc</groupId>
|
||||||
|
<artifactId>mariadb-java-client</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JWT -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-api</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-impl</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package net.miarma.backlib.config;
|
||||||
|
|
||||||
|
import net.miarma.backlib.security.JwtService;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SecurityCommonConfig {
|
||||||
|
@Bean
|
||||||
|
public AuthenticationManager authManager(HttpSecurity http) throws Exception {
|
||||||
|
return http.getSharedObject(AuthenticationManagerBuilder.class)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JwtService jwtService() {
|
||||||
|
return new JwtService();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
import tools.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public class ApiErrorDto {
|
||||||
|
private int status;
|
||||||
|
private String error;
|
||||||
|
private String message;
|
||||||
|
private String path;
|
||||||
|
private Instant timestamp;
|
||||||
|
|
||||||
|
public ApiErrorDto(int status, String error, String message, String path) {
|
||||||
|
this.status = status;
|
||||||
|
this.error = error;
|
||||||
|
this.message = message;
|
||||||
|
this.path = path;
|
||||||
|
this.timestamp = Instant.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(int status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getError() {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setError(String error) {
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPath(String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(Instant timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJson() {
|
||||||
|
return new ObjectMapper().writeValueAsString(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
import tools.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ApiValidationErrorDto {
|
||||||
|
private int status;
|
||||||
|
private Map<String,String> errors;
|
||||||
|
private String path;
|
||||||
|
private Instant timestamp;
|
||||||
|
|
||||||
|
public ApiValidationErrorDto(Map<String,String> errors, String path) {
|
||||||
|
this.status = 422;
|
||||||
|
this.errors = errors;
|
||||||
|
this.path = path;
|
||||||
|
this.timestamp = Instant.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String,String> getErrors() {
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(int status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPath(String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrors(Map<String,String> errors) {
|
||||||
|
this.errors = errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(Instant timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJson() {
|
||||||
|
return new ObjectMapper().writeValueAsString(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
public record ChangeAvatarRequest(String avatar) {}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public record ChangePasswordRequest(@NotBlank String oldPassword,
|
||||||
|
@NotBlank String newPassword,
|
||||||
|
@NotBlank Byte serviceId) {}
|
||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
public record ChangeRoleRequest(Byte role) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
public record ChangeStatusRequest(Byte status) {}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class CreateCredentialDto {
|
||||||
|
private UUID userId;
|
||||||
|
private Byte serviceId;
|
||||||
|
private String username;
|
||||||
|
private String email;
|
||||||
|
private String password;
|
||||||
|
private Byte status;
|
||||||
|
|
||||||
|
public CreateCredentialDto() {}
|
||||||
|
|
||||||
|
public CreateCredentialDto(UUID userId, Byte serviceId, String username, String email,
|
||||||
|
String password, Byte status) {
|
||||||
|
this.userId = userId;
|
||||||
|
this.serviceId = serviceId;
|
||||||
|
this.username = username;
|
||||||
|
this.email = email;
|
||||||
|
this.password = password;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters y setters
|
||||||
|
public UUID getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
public void setUserId(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
public Byte getServiceId() {
|
||||||
|
return serviceId;
|
||||||
|
}
|
||||||
|
public void setServiceId(Byte serviceId) {
|
||||||
|
this.serviceId = serviceId;
|
||||||
|
}
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
public String getPassword() { return password; }
|
||||||
|
public void setPassword(String password) { this.password = password; }
|
||||||
|
public Byte getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
public void setStatus(Byte status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
public record CreateUserDto(String displayName,
|
||||||
|
String avatar) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class CredentialDto {
|
||||||
|
private UUID credentialId;
|
||||||
|
private UUID userId;
|
||||||
|
private Byte serviceId;
|
||||||
|
private String username;
|
||||||
|
private String email;
|
||||||
|
private Byte status;
|
||||||
|
private Instant createdAt;
|
||||||
|
private Instant updatedAt;
|
||||||
|
|
||||||
|
public CredentialDto() {}
|
||||||
|
|
||||||
|
public CredentialDto(UUID credentialId, UUID userId, Byte serviceId, String username, String email,
|
||||||
|
Byte status, Instant createdAt, Instant updatedAt) {
|
||||||
|
this.credentialId = credentialId;
|
||||||
|
this.userId = userId;
|
||||||
|
this.serviceId = serviceId;
|
||||||
|
this.username = username;
|
||||||
|
this.email = email;
|
||||||
|
this.status = status;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters y setters
|
||||||
|
public UUID getCredentialId() {
|
||||||
|
return credentialId;
|
||||||
|
}
|
||||||
|
public void setCredentialId(UUID credentialId) {
|
||||||
|
this.credentialId = credentialId;
|
||||||
|
}
|
||||||
|
public UUID getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
public void setUserId(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
public Byte getServiceId() {
|
||||||
|
return serviceId;
|
||||||
|
}
|
||||||
|
public void setServiceId(Byte serviceId) {
|
||||||
|
this.serviceId = serviceId;
|
||||||
|
}
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
public Byte getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
public void setStatus(Byte status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
public Instant getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
public void setCreatedAt(Instant createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
public Instant getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
public void setUpdatedAt(Instant updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
123
backlib/src/main/java/net/miarma/backlib/dto/FileDto.java
Normal file
123
backlib/src/main/java/net/miarma/backlib/dto/FileDto.java
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class FileDto {
|
||||||
|
|
||||||
|
private FileDto() {}
|
||||||
|
|
||||||
|
public static class Request {
|
||||||
|
private String fileName;
|
||||||
|
private String filePath;
|
||||||
|
private String mimeType;
|
||||||
|
private Byte context;
|
||||||
|
private UUID uploadedBy;
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileName(String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilePath() {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilePath(String filePath) {
|
||||||
|
this.filePath = filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeType() {
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMimeType(String mimeType) {
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Byte getContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContext(Byte context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUploadedBy() {
|
||||||
|
return uploadedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUploadedBy(UUID uploadedBy) {
|
||||||
|
this.uploadedBy = uploadedBy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Response {
|
||||||
|
private UUID fileId;
|
||||||
|
private String fileName;
|
||||||
|
private String filePath;
|
||||||
|
private String mimeType;
|
||||||
|
private UUID uploadedBy;
|
||||||
|
private Instant uploadedAt;
|
||||||
|
private Byte context;
|
||||||
|
|
||||||
|
public UUID getFileId() {
|
||||||
|
return fileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileId(UUID fileId) {
|
||||||
|
this.fileId = fileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileName(String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilePath() {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilePath(String filePath) {
|
||||||
|
this.filePath = filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeType() {
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMimeType(String mimeType) {
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUploadedBy() {
|
||||||
|
return uploadedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUploadedBy(UUID uploadedBy) {
|
||||||
|
this.uploadedBy = uploadedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getUploadedAt() {
|
||||||
|
return uploadedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUploadedAt(Instant uploadedAt) {
|
||||||
|
this.uploadedAt = uploadedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Byte getContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContext(Byte context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import tools.jackson.databind.JsonNode;
|
||||||
|
|
||||||
|
public record LoginRequest(@NotBlank String username,
|
||||||
|
@NotBlank String password,
|
||||||
|
Byte serviceId) {}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
public record LoginResponse(@JsonProperty("token") String token,
|
||||||
|
UserDto user,
|
||||||
|
CredentialDto account) {}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
public record RegisterRequest(String displayName,
|
||||||
|
@NotBlank String username,
|
||||||
|
@NotBlank String email,
|
||||||
|
@NotBlank String password,
|
||||||
|
Byte serviceId) {}
|
||||||
71
backlib/src/main/java/net/miarma/backlib/dto/UserDto.java
Normal file
71
backlib/src/main/java/net/miarma/backlib/dto/UserDto.java
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UserDto {
|
||||||
|
private UUID userId;
|
||||||
|
private String displayName;
|
||||||
|
private String avatar;
|
||||||
|
private Byte globalStatus;
|
||||||
|
private Byte globalRole;
|
||||||
|
private Instant createdAt;
|
||||||
|
private Instant updatedAt;
|
||||||
|
|
||||||
|
public UserDto() {}
|
||||||
|
|
||||||
|
public UserDto(UUID userId, String displayName, String avatar, Byte globalStatus, Byte globalRole,
|
||||||
|
Instant createdAt, Instant updatedAt) {
|
||||||
|
this.userId = userId;
|
||||||
|
this.displayName = displayName;
|
||||||
|
this.avatar = avatar;
|
||||||
|
this.globalStatus = globalStatus;
|
||||||
|
this.globalRole = globalRole;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters y setters
|
||||||
|
public UUID getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
public void setUserId(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
public String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
public void setDisplayName(String displayName) {
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
public String getAvatar() {
|
||||||
|
return avatar;
|
||||||
|
}
|
||||||
|
public void setAvatar(String avatar) {
|
||||||
|
this.avatar = avatar;
|
||||||
|
}
|
||||||
|
public Byte getGlobalStatus() {
|
||||||
|
return globalStatus;
|
||||||
|
}
|
||||||
|
public void setGlobalStatus(Byte globalStatus) {
|
||||||
|
this.globalStatus = globalStatus;
|
||||||
|
}
|
||||||
|
public Byte getGlobalRole() {
|
||||||
|
return globalRole;
|
||||||
|
}
|
||||||
|
public void setGlobalRole(Byte globalRole) {
|
||||||
|
this.globalRole = globalRole;
|
||||||
|
}
|
||||||
|
public Instant getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
public void setCreatedAt(Instant createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
public Instant getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
public void setUpdatedAt(Instant updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
public record UserExistsResponse(boolean exists) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package net.miarma.backlib.dto;
|
||||||
|
|
||||||
|
public record UserWithCredentialDto(UserDto user, CredentialDto account) {}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.miarma.backlib.exception;
|
||||||
|
|
||||||
|
public class BadRequestException extends RuntimeException {
|
||||||
|
public BadRequestException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.miarma.backlib.exception;
|
||||||
|
|
||||||
|
public class ConflictException extends RuntimeException {
|
||||||
|
public ConflictException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.miarma.backlib.exception;
|
||||||
|
|
||||||
|
public class ForbiddenException extends RuntimeException {
|
||||||
|
public ForbiddenException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package net.miarma.backlib.exception;
|
||||||
|
|
||||||
|
public class NotFoundException extends RuntimeException {
|
||||||
|
public NotFoundException(String message) { super(message); }
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.miarma.backlib.exception;
|
||||||
|
|
||||||
|
public class UnauthorizedException extends RuntimeException {
|
||||||
|
public UnauthorizedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package net.miarma.backlib.exception;
|
||||||
|
|
||||||
|
public class ValidationException extends RuntimeException {
|
||||||
|
private final String field;
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
public ValidationException(String field, String message) {
|
||||||
|
super(message);
|
||||||
|
this.field = field;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getField() {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package net.miarma.backlib.filter;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class RequestLoggingFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(RequestLoggingFilter.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(
|
||||||
|
HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
FilterChain filterChain
|
||||||
|
) throws ServletException, IOException {
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
|
||||||
|
long duration = System.currentTimeMillis() - start;
|
||||||
|
|
||||||
|
log.info("({}) {} {} -> {} ({} ms)",
|
||||||
|
request.getRemoteAddr(),
|
||||||
|
request.getMethod(),
|
||||||
|
request.getRequestURI(),
|
||||||
|
response.getStatus(),
|
||||||
|
duration
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package net.miarma.backlib.http;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Profile("dev") // esto asegura que solo se cargue en dev
|
||||||
|
public class DevCorsConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public WebMvcConfigurer corsConfigurer() {
|
||||||
|
return new WebMvcConfigurer() {
|
||||||
|
@Override
|
||||||
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
|
registry.addMapping("/**")
|
||||||
|
.allowedOrigins("http://localhost:3000") // tu frontend React
|
||||||
|
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||||
|
.allowCredentials(true)
|
||||||
|
.allowedHeaders("*");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package net.miarma.backlib.http;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import net.miarma.backlib.dto.ApiErrorDto;
|
||||||
|
import net.miarma.backlib.dto.ApiValidationErrorDto;
|
||||||
|
import net.miarma.backlib.exception.*;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
@ExceptionHandler(NotFoundException.class)
|
||||||
|
public ResponseEntity<ApiErrorDto> handleNotFound(
|
||||||
|
NotFoundException ex, HttpServletRequest req) {
|
||||||
|
|
||||||
|
ApiErrorDto error = new ApiErrorDto(
|
||||||
|
HttpStatus.NOT_FOUND.value(),
|
||||||
|
HttpStatus.NOT_FOUND.getReasonPhrase(),
|
||||||
|
ex.getMessage(),
|
||||||
|
req.getRequestURI()
|
||||||
|
);
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(BadRequestException.class)
|
||||||
|
public ResponseEntity<ApiErrorDto> handleBadRequest(
|
||||||
|
BadRequestException ex, HttpServletRequest req) {
|
||||||
|
|
||||||
|
ApiErrorDto error = new ApiErrorDto(
|
||||||
|
HttpStatus.BAD_REQUEST.value(),
|
||||||
|
HttpStatus.BAD_REQUEST.getReasonPhrase(),
|
||||||
|
ex.getMessage(),
|
||||||
|
req.getRequestURI()
|
||||||
|
);
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(UnauthorizedException.class)
|
||||||
|
public ResponseEntity<ApiErrorDto> handleUnauthorized(
|
||||||
|
UnauthorizedException ex, HttpServletRequest req) {
|
||||||
|
|
||||||
|
ApiErrorDto error = new ApiErrorDto(
|
||||||
|
HttpStatus.UNAUTHORIZED.value(),
|
||||||
|
HttpStatus.UNAUTHORIZED.getReasonPhrase(),
|
||||||
|
ex.getMessage(),
|
||||||
|
req.getRequestURI()
|
||||||
|
);
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ForbiddenException.class)
|
||||||
|
public ResponseEntity<ApiErrorDto> handleForbidden(
|
||||||
|
ForbiddenException ex, HttpServletRequest req) {
|
||||||
|
|
||||||
|
ApiErrorDto error = new ApiErrorDto(
|
||||||
|
HttpStatus.FORBIDDEN.value(),
|
||||||
|
HttpStatus.FORBIDDEN.getReasonPhrase(),
|
||||||
|
ex.getMessage(),
|
||||||
|
req.getRequestURI()
|
||||||
|
);
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ConflictException.class)
|
||||||
|
public ResponseEntity<ApiErrorDto> handleConflict(
|
||||||
|
ConflictException ex, HttpServletRequest req) {
|
||||||
|
|
||||||
|
ApiErrorDto error = new ApiErrorDto(
|
||||||
|
HttpStatus.CONFLICT.value(),
|
||||||
|
HttpStatus.CONFLICT.getReasonPhrase(),
|
||||||
|
ex.getMessage(),
|
||||||
|
req.getRequestURI()
|
||||||
|
);
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.CONFLICT).body(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ValidationException.class)
|
||||||
|
public ResponseEntity<ApiValidationErrorDto> handleValidation(
|
||||||
|
ValidationException ex, HttpServletRequest req) {
|
||||||
|
Map<String, String> errors = Map.of(ex.getField(), ex.getMessage());
|
||||||
|
return ResponseEntity.status(HttpStatus.UNPROCESSABLE_CONTENT).body(new ApiValidationErrorDto(errors, req.getRequestURI()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public ResponseEntity<ApiErrorDto> handleAll(
|
||||||
|
Exception ex, HttpServletRequest req) {
|
||||||
|
|
||||||
|
ApiErrorDto error = new ApiErrorDto(
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR.value(),
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(),
|
||||||
|
"Internal server error",
|
||||||
|
req.getRequestURI()
|
||||||
|
);
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package net.miarma.backlib.http;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import net.miarma.backlib.dto.ApiErrorDto;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class RestAccessDeniedHandler implements AccessDeniedHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(HttpServletRequest request, HttpServletResponse response,
|
||||||
|
AccessDeniedException accessDeniedException) throws IOException {
|
||||||
|
|
||||||
|
ApiErrorDto error = new ApiErrorDto(
|
||||||
|
HttpStatus.FORBIDDEN.value(),
|
||||||
|
HttpStatus.FORBIDDEN.getReasonPhrase(),
|
||||||
|
"Forbidden",
|
||||||
|
request.getRequestURI()
|
||||||
|
);
|
||||||
|
|
||||||
|
response.setStatus(HttpStatus.FORBIDDEN.value());
|
||||||
|
response.setContentType("application/json");
|
||||||
|
response.getWriter().write(error.toJson());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package net.miarma.backlib.http;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import net.miarma.backlib.dto.ApiErrorDto;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class RestAuthEntryPoint implements AuthenticationEntryPoint {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||||
|
AuthenticationException authException) throws IOException {
|
||||||
|
|
||||||
|
ApiErrorDto error = new ApiErrorDto(
|
||||||
|
HttpStatus.UNAUTHORIZED.value(),
|
||||||
|
HttpStatus.UNAUTHORIZED.getReasonPhrase(),
|
||||||
|
"Unauthorized",
|
||||||
|
request.getRequestURI()
|
||||||
|
);
|
||||||
|
|
||||||
|
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||||
|
response.setContentType("application/json");
|
||||||
|
response.getWriter().write(error.toJson());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package net.miarma.backlib.security;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CoreAuthTokenHolder {
|
||||||
|
private volatile String token;
|
||||||
|
private volatile Instant expiresAt;
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExpired() {
|
||||||
|
return expiresAt == null || Instant.now().isAfter(expiresAt.minusSeconds(30));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token, Instant expiresAt) {
|
||||||
|
this.token = token;
|
||||||
|
this.expiresAt = expiresAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package net.miarma.backlib.security;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.*;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class JwtService {
|
||||||
|
|
||||||
|
@Value("${jwt.private-key-path}")
|
||||||
|
private String privateKeyPath;
|
||||||
|
|
||||||
|
@Value("${jwt.public-key-path}")
|
||||||
|
private String publicKeyPath;
|
||||||
|
|
||||||
|
@Value("${jwt.expiration-ms}")
|
||||||
|
private long expiration;
|
||||||
|
|
||||||
|
private PrivateKey privateKey;
|
||||||
|
private PublicKey publicKey;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() throws Exception {
|
||||||
|
this.privateKey = loadPrivateKey(privateKeyPath);
|
||||||
|
this.publicKey = loadPublicKey(publicKeyPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PrivateKey loadPrivateKey(String path) throws Exception {
|
||||||
|
String pem = Files.readString(Path.of(path));
|
||||||
|
pem = pem.replace("-----BEGIN PRIVATE KEY-----", "")
|
||||||
|
.replace("-----END PRIVATE KEY-----", "")
|
||||||
|
.replaceAll("\\s", "");
|
||||||
|
|
||||||
|
byte[] decoded = Base64.getDecoder().decode(pem);
|
||||||
|
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
|
||||||
|
KeyFactory kf = KeyFactory.getInstance("RSA");
|
||||||
|
return kf.generatePrivate(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PublicKey loadPublicKey(String path) throws Exception {
|
||||||
|
String pem = Files.readString(Path.of(path));
|
||||||
|
pem = pem.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||||
|
.replace("-----END PUBLIC KEY-----", "")
|
||||||
|
.replaceAll("\\s", "");
|
||||||
|
|
||||||
|
byte[] decoded = Base64.getDecoder().decode(pem);
|
||||||
|
X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
|
||||||
|
KeyFactory kf = KeyFactory.getInstance("RSA");
|
||||||
|
return kf.generatePublic(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateToken(UUID userId, Byte serviceId) {
|
||||||
|
Date now = new Date();
|
||||||
|
Date exp = new Date(now.getTime() + expiration);
|
||||||
|
|
||||||
|
return Jwts.builder()
|
||||||
|
.setSubject(userId.toString())
|
||||||
|
.claim("service", serviceId)
|
||||||
|
.setIssuedAt(now)
|
||||||
|
.setExpiration(exp)
|
||||||
|
.signWith(privateKey, SignatureAlgorithm.RS256)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validateToken(String token) {
|
||||||
|
try {
|
||||||
|
Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(token);
|
||||||
|
return true;
|
||||||
|
} catch (JwtException | IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUserId(String token) {
|
||||||
|
Claims claims = Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(token).getBody();
|
||||||
|
return UUID.fromString(claims.getSubject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Byte getServiceId(String token) {
|
||||||
|
Claims claims = Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(token).getBody();
|
||||||
|
return ((Number) claims.get("service")).byteValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getExpiration(String token) {
|
||||||
|
Claims claims = Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(token).getBody();
|
||||||
|
return claims.getExpiration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package net.miarma.backlib.security;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PasswordGenerator {
|
||||||
|
|
||||||
|
private static final String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
private static final String LOWER = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
private static final String DIGITS = "0123456789";
|
||||||
|
private static final String SYMBOLS = "!@#$%^&*"; // compatibles con bcrypt
|
||||||
|
private static final String ALL = UPPER + LOWER + DIGITS + SYMBOLS;
|
||||||
|
|
||||||
|
private static final SecureRandom random = new SecureRandom();
|
||||||
|
|
||||||
|
public static String generate(int length) {
|
||||||
|
if (length < 8) length = 8;
|
||||||
|
|
||||||
|
List<Character> password = new ArrayList<>();
|
||||||
|
|
||||||
|
password.add(getRandChar(UPPER));
|
||||||
|
password.add(getRandChar(LOWER));
|
||||||
|
password.add(getRandChar(DIGITS));
|
||||||
|
password.add(getRandChar(SYMBOLS));
|
||||||
|
|
||||||
|
while (password.size() < length) {
|
||||||
|
password.add(getRandChar(ALL));
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.shuffle(password, random);
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (char c : password) {
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char getRandChar(String chars) {
|
||||||
|
return chars.charAt(random.nextInt(chars.length()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package net.miarma.backlib.security;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ServiceAuthFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
private final JwtService jwtService;
|
||||||
|
|
||||||
|
public ServiceAuthFilter(JwtService jwtService) {
|
||||||
|
this.jwtService = jwtService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
FilterChain filterChain)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
|
||||||
|
String path = request.getRequestURI();
|
||||||
|
|
||||||
|
if (path.startsWith("/users/service")) {
|
||||||
|
String authHeader = request.getHeader("Authorization");
|
||||||
|
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String token = authHeader.substring(7);
|
||||||
|
if (!jwtService.validateToken(token)) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
backlib/src/main/java/net/miarma/backlib/util/UuidUtil.java
Normal file
21
backlib/src/main/java/net/miarma/backlib/util/UuidUtil.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package net.miarma.backlib.util;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UuidUtil {
|
||||||
|
public static byte[] uuidToBin(UUID uuid) {
|
||||||
|
ByteBuffer bb = ByteBuffer.allocate(16);
|
||||||
|
bb.putLong(uuid.getMostSignificantBits());
|
||||||
|
bb.putLong(uuid.getLeastSignificantBits());
|
||||||
|
return bb.array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUID binToUUID(byte[] bin) {
|
||||||
|
ByteBuffer bb = ByteBuffer.wrap(bin);
|
||||||
|
long high = bb.getLong();
|
||||||
|
long low = bb.getLong();
|
||||||
|
return new UUID(high, low);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
3
backlib/target/maven-archiver/pom.properties
Normal file
3
backlib/target/maven-archiver/pom.properties
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
artifactId=backlib
|
||||||
|
groupId=net.miarma
|
||||||
|
version=1.1.0
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
net/miarma/backlib/dto/LoginResponse.class
|
||||||
|
net/miarma/backlib/dto/CreateUserDto.class
|
||||||
|
net/miarma/backlib/http/DevCorsConfig$1.class
|
||||||
|
net/miarma/backlib/dto/ApiErrorDto.class
|
||||||
|
net/miarma/backlib/dto/ChangeStatusRequest.class
|
||||||
|
net/miarma/backlib/exception/ConflictException.class
|
||||||
|
net/miarma/backlib/http/RestAuthEntryPoint.class
|
||||||
|
net/miarma/backlib/exception/NotFoundException.class
|
||||||
|
net/miarma/backlib/http/RestAccessDeniedHandler.class
|
||||||
|
net/miarma/backlib/dto/ChangeAvatarRequest.class
|
||||||
|
net/miarma/backlib/dto/FileDto$Response.class
|
||||||
|
net/miarma/backlib/dto/CredentialDto.class
|
||||||
|
net/miarma/backlib/util/UuidUtil.class
|
||||||
|
net/miarma/backlib/dto/FileDto$Request.class
|
||||||
|
net/miarma/backlib/dto/ApiValidationErrorDto.class
|
||||||
|
net/miarma/backlib/security/JwtService.class
|
||||||
|
net/miarma/backlib/dto/UserDto.class
|
||||||
|
net/miarma/backlib/dto/LoginRequest.class
|
||||||
|
net/miarma/backlib/exception/BadRequestException.class
|
||||||
|
net/miarma/backlib/security/CoreAuthTokenHolder.class
|
||||||
|
net/miarma/backlib/dto/CreateCredentialDto.class
|
||||||
|
net/miarma/backlib/dto/UserWithCredentialDto.class
|
||||||
|
net/miarma/backlib/dto/RegisterRequest.class
|
||||||
|
net/miarma/backlib/dto/ChangePasswordRequest.class
|
||||||
|
net/miarma/backlib/http/GlobalExceptionHandler.class
|
||||||
|
net/miarma/backlib/dto/UserExistsResponse.class
|
||||||
|
net/miarma/backlib/dto/ChangeRoleRequest.class
|
||||||
|
net/miarma/backlib/exception/ForbiddenException.class
|
||||||
|
net/miarma/backlib/exception/UnauthorizedException.class
|
||||||
|
net/miarma/backlib/dto/FileDto.class
|
||||||
|
net/miarma/backlib/security/PasswordGenerator.class
|
||||||
|
net/miarma/backlib/config/SecurityCommonConfig.class
|
||||||
|
net/miarma/backlib/filter/RequestLoggingFilter.class
|
||||||
|
net/miarma/backlib/exception/ValidationException.class
|
||||||
|
net/miarma/backlib/security/ServiceAuthFilter.class
|
||||||
|
net/miarma/backlib/http/DevCorsConfig.class
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/config/SecurityCommonConfig.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/ApiErrorDto.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/ApiValidationErrorDto.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/ChangeAvatarRequest.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/ChangePasswordRequest.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/ChangeRoleRequest.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/ChangeStatusRequest.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/CreateCredentialDto.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/CreateUserDto.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/CredentialDto.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/FileDto.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/LoginRequest.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/LoginResponse.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/RegisterRequest.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/UserDto.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/UserExistsResponse.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/dto/UserWithCredentialDto.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/exception/BadRequestException.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/exception/ConflictException.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/exception/ForbiddenException.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/exception/NotFoundException.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/exception/UnauthorizedException.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/exception/ValidationException.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/filter/RequestLoggingFilter.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/http/DevCorsConfig.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/http/GlobalExceptionHandler.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/http/RestAccessDeniedHandler.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/http/RestAuthEntryPoint.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/security/CoreAuthTokenHolder.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/security/JwtService.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/security/PasswordGenerator.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/security/ServiceAuthFilter.java
|
||||||
|
/home/jomaa/git/miarma-backend/backlib/src/main/java/net/miarma/backlib/util/UuidUtil.java
|
||||||
10
build-upload.sh
Executable file
10
build-upload.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd core/ || exit
|
||||||
|
mvn clean package
|
||||||
|
cd ..
|
||||||
|
cd mpaste/ || exit
|
||||||
|
mvn clean package
|
||||||
|
cd ..
|
||||||
|
scp core/target/core-*.jar jomaa@10.0.0.254:/home/jomaa/transfer
|
||||||
|
scp mpaste/target/mpaste-*.jar jomaa@10.0.0.254:/home/jomaa/transfer
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<classpath>
|
|
||||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
|
||||||
</classpath>
|
|
||||||
1
cine/.gitignore
vendored
1
cine/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
/target/
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>cine</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
eclipse.preferences.version=1
|
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
|
||||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
|
||||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
|
||||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
|
||||||
org.eclipse.jdt.core.compiler.release=disabled
|
|
||||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
activeProfiles=
|
|
||||||
eclipse.preferences.version=1
|
|
||||||
resolveWorkspaceProjects=true
|
|
||||||
version=1
|
|
||||||
52
cine/pom.xml
52
cine/pom.xml
@@ -1,52 +0,0 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>net.miarma</groupId>
|
|
||||||
<artifactId>backend</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
</parent>
|
|
||||||
<artifactId>cine</artifactId>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<!-- Spring Boot -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mariadb.jdbc</groupId>
|
|
||||||
<artifactId>mariadb-java-client</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- JWT -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-api</artifactId>
|
|
||||||
<version>0.11.5</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-impl</artifactId>
|
|
||||||
<version>0.11.5</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-jackson</artifactId>
|
|
||||||
<version>0.11.5</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</project>
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<classpath>
|
|
||||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
|
||||||
</classpath>
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>core</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
eclipse.preferences.version=1
|
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
|
||||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
|
||||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
|
||||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
|
||||||
org.eclipse.jdt.core.compiler.release=disabled
|
|
||||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
activeProfiles=
|
|
||||||
eclipse.preferences.version=1
|
|
||||||
resolveWorkspaceProjects=true
|
|
||||||
version=1
|
|
||||||
9
core/core.iml
Normal file
9
core/core.iml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module version="4">
|
||||||
|
<component name="AdditionalModuleElements">
|
||||||
|
<content url="file://$MODULE_DIR$" dumb="true">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||||
|
</content>
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
39
core/pom.xml
39
core/pom.xml
@@ -9,6 +9,18 @@
|
|||||||
</parent>
|
</parent>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>25</maven.compiler.source>
|
||||||
|
<maven.compiler.target>25</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>gitea</id>
|
||||||
|
<url>https://git.miarma.net/api/packages/Gallardo7761/maven</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- Spring Boot -->
|
<!-- Spring Boot -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -44,6 +56,10 @@
|
|||||||
<version>1.18.42</version>
|
<version>1.18.42</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- JWT -->
|
<!-- JWT -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -63,6 +79,29 @@
|
|||||||
<version>0.11.5</version>
|
<version>0.11.5</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.miarma</groupId>
|
||||||
|
<artifactId>backlib</artifactId>
|
||||||
|
<version>1.1.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>${spring.boot.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
package net.miarma.backend.core;
|
package net.miarma.backend.core;
|
||||||
|
|
||||||
|
import net.miarma.backlib.config.SecurityCommonConfig;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication(scanBasePackages = {
|
||||||
|
"net.miarma.backend.core",
|
||||||
|
"net.miarma.backlib"
|
||||||
|
})
|
||||||
public class CoreApplication {
|
public class CoreApplication {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(CoreApplication.class, args);
|
SpringApplication.run(CoreApplication.class, args);
|
||||||
|
|||||||
@@ -1,31 +1,62 @@
|
|||||||
package net.miarma.backend.core.config;
|
package net.miarma.backend.core.config;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.security.JwtFilter;
|
||||||
|
import net.miarma.backlib.http.RestAccessDeniedHandler;
|
||||||
|
import net.miarma.backlib.http.RestAuthEntryPoint;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
import org.springframework.web.cors.CorsConfigurationSource;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
|
@EnableMethodSecurity(prePostEnabled = true)
|
||||||
public class SecurityConfig {
|
public class SecurityConfig {
|
||||||
private final JwtFilter jwtFilter;
|
private final JwtFilter jwtFilter;
|
||||||
|
private final RestAuthEntryPoint authEntryPoint;
|
||||||
|
private final RestAccessDeniedHandler accessDeniedHandler;
|
||||||
|
private final CorsConfigurationSource corsConfigurationSource;
|
||||||
|
|
||||||
public SecurityConfig(JwtFilter jwtFilter) {
|
public SecurityConfig(
|
||||||
|
JwtFilter jwtFilter,
|
||||||
|
RestAuthEntryPoint authEntryPoint,
|
||||||
|
RestAccessDeniedHandler accessDeniedHandler,
|
||||||
|
Optional<CorsConfigurationSource> corsConfigurationSource
|
||||||
|
) {
|
||||||
this.jwtFilter = jwtFilter;
|
this.jwtFilter = jwtFilter;
|
||||||
|
this.authEntryPoint = authEntryPoint;
|
||||||
|
this.accessDeniedHandler = accessDeniedHandler;
|
||||||
|
this.corsConfigurationSource = corsConfigurationSource.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
if (corsConfigurationSource != null) {
|
||||||
|
http.cors(Customizer.withDefaults());
|
||||||
|
}
|
||||||
|
|
||||||
http
|
http
|
||||||
.csrf(csrf -> csrf.disable())
|
.csrf(csrf -> csrf.disable())
|
||||||
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
|
.exceptionHandling(ex -> ex
|
||||||
|
.authenticationEntryPoint(authEntryPoint)
|
||||||
|
.accessDeniedHandler(accessDeniedHandler)
|
||||||
|
)
|
||||||
.authorizeHttpRequests(auth -> auth
|
.authorizeHttpRequests(auth -> auth
|
||||||
.requestMatchers("/auth/**").permitAll()
|
.requestMatchers("/auth/login").permitAll()
|
||||||
|
.requestMatchers("/auth/refresh").permitAll()
|
||||||
|
.requestMatchers("/auth/change-password").permitAll()
|
||||||
|
.requestMatchers("/auth/register").permitAll()
|
||||||
|
.requestMatchers("/test").permitAll()
|
||||||
|
.requestMatchers("/screenshot").permitAll()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -33,9 +64,4 @@ public class SecurityConfig {
|
|||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return new BCryptPasswordEncoder(12);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package net.miarma.backend.core.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class WebClientConfig {
|
||||||
|
@Bean
|
||||||
|
public WebClient.Builder webClientBuilder() {
|
||||||
|
return WebClient.builder();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,60 +1,122 @@
|
|||||||
package net.miarma.backend.core.controller;
|
package net.miarma.backend.core.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import net.miarma.backlib.dto.*;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.web.bind.annotation.RequestHeader;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import net.miarma.backend.core.dto.LoginRequest;
|
import net.miarma.backend.core.model.Credential;
|
||||||
import net.miarma.backend.core.dto.LoginResponse;
|
|
||||||
import net.miarma.backend.core.service.AuthService;
|
import net.miarma.backend.core.service.AuthService;
|
||||||
import net.miarma.backend.core.service.JwtService;
|
import net.miarma.backend.core.service.CredentialService;
|
||||||
|
import net.miarma.backlib.security.JwtService;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/auth")
|
@RequestMapping("/auth")
|
||||||
public class AuthController {
|
public class AuthController {
|
||||||
|
|
||||||
private final AuthService authService;
|
|
||||||
private final JwtService jwtService;
|
private final JwtService jwtService;
|
||||||
|
private final AuthService authService;
|
||||||
|
|
||||||
public AuthController(AuthService authService, JwtService jwtService) {
|
public AuthController(JwtService jwtService, AuthService authService) {
|
||||||
this.authService = authService;
|
|
||||||
this.jwtService = jwtService;
|
this.jwtService = jwtService;
|
||||||
|
this.authService = authService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
public ResponseEntity<LoginResponse> login(@Valid @RequestBody LoginRequest request) {
|
public ResponseEntity<LoginResponse> login(@Valid @RequestBody LoginRequest request) {
|
||||||
LoginResponse response = authService.login(request);
|
LoginResponse response = authService.login(request);
|
||||||
return ResponseEntity.ok(response);
|
return ResponseEntity.ok(
|
||||||
|
new LoginResponse(response.token(), response.user(), response.account())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/refresh")
|
@PostMapping("/register")
|
||||||
|
public ResponseEntity<LoginResponse> register(@RequestBody RegisterRequest request) {
|
||||||
|
return ResponseEntity.ok(authService.register(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/refresh")
|
||||||
public ResponseEntity<?> refreshToken(@RequestHeader("Authorization") String authHeader) {
|
public ResponseEntity<?> refreshToken(@RequestHeader("Authorization") String authHeader) {
|
||||||
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
||||||
return ResponseEntity.status(401).body("Token missing");
|
return ResponseEntity.status(401).body(
|
||||||
|
new ApiErrorDto(
|
||||||
|
401,
|
||||||
|
"Unauthorized",
|
||||||
|
"No hay token",
|
||||||
|
"/v2/core/auth/change-password"
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String token = authHeader.substring(7);
|
String token = authHeader.substring(7);
|
||||||
if (!jwtService.validateToken(token)) {
|
if (!jwtService.validateToken(token)) {
|
||||||
return ResponseEntity.status(401).body("Invalid token");
|
return ResponseEntity.status(401).body(
|
||||||
|
new ApiErrorDto(
|
||||||
|
401,
|
||||||
|
"Unauthorized",
|
||||||
|
"Invalid token",
|
||||||
|
"/v2/core/auth/change-password"
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID userId = jwtService.getUserId(token);
|
UUID userId = jwtService.getUserId(token);
|
||||||
short serviceId = jwtService.getServiceId(token);
|
Byte serviceId = jwtService.getServiceId(token);
|
||||||
|
|
||||||
String newToken = jwtService.generateToken(userId, serviceId);
|
String newToken = jwtService.generateToken(userId, serviceId);
|
||||||
|
|
||||||
return ResponseEntity.ok(Map.of(
|
return ResponseEntity.ok(Map.of(
|
||||||
"token", newToken,
|
"token", newToken,
|
||||||
"userId", userId,
|
"userId", userId,
|
||||||
"serviceId", serviceId
|
"serviceId", serviceId
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/change-password")
|
||||||
|
public ResponseEntity<?> changePassword(
|
||||||
|
@RequestHeader("Authorization") String authHeader,
|
||||||
|
@RequestBody ChangePasswordRequest request
|
||||||
|
) {
|
||||||
|
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
||||||
|
return ResponseEntity.status(401).body(
|
||||||
|
new ApiErrorDto(
|
||||||
|
401,
|
||||||
|
"Unauthorized",
|
||||||
|
"No hay token",
|
||||||
|
"/v2/core/auth/change-password"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String token = authHeader.substring(7);
|
||||||
|
if (!jwtService.validateToken(token)) {
|
||||||
|
return ResponseEntity.status(401).body(
|
||||||
|
new ApiErrorDto(
|
||||||
|
401,
|
||||||
|
"Unauthorized",
|
||||||
|
"Invalid token",
|
||||||
|
"/v2/core/auth/change-password"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID userId = jwtService.getUserId(token);
|
||||||
|
|
||||||
|
authService.changePassword(userId, request);
|
||||||
|
return ResponseEntity.ok(Map.of("message", "Contraseña cambiada correctamente"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/validate")
|
||||||
|
public ResponseEntity<Boolean> validate(@RequestHeader("Authorization") String authHeader) {
|
||||||
|
String token = authHeader.substring(7);
|
||||||
|
return ResponseEntity.ok(jwtService.validateToken(token));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,102 @@
|
|||||||
package net.miarma.backend.core.controller;
|
package net.miarma.backend.core.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.dto.UpdateCredentialDto;
|
||||||
|
import net.miarma.backend.core.mapper.CredentialMapper;
|
||||||
|
import net.miarma.backend.core.mapper.UserMapper;
|
||||||
|
import net.miarma.backend.core.security.CorePrincipal;
|
||||||
|
import net.miarma.backend.core.service.UserService;
|
||||||
|
import net.miarma.backlib.dto.*;
|
||||||
|
import net.miarma.backlib.exception.ForbiddenException;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.model.Credential;
|
||||||
|
import net.miarma.backend.core.service.CredentialService;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/credentials")
|
||||||
public class CredentialController {
|
public class CredentialController {
|
||||||
|
|
||||||
|
private final CredentialService credentialService;
|
||||||
|
|
||||||
|
public CredentialController(CredentialService credentialService) {
|
||||||
|
this.credentialService = credentialService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<List<Credential>> getAll() {
|
||||||
|
return ResponseEntity.ok(credentialService.getAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<CredentialDto> create(@RequestBody CreateCredentialDto dto) {
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
CredentialMapper.toDto(
|
||||||
|
credentialService.create(
|
||||||
|
CredentialMapper.toEntity(dto)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/user/{userId}")
|
||||||
|
public ResponseEntity<List<CredentialDto>> getByUserId(@PathVariable("userId") UUID userId) {
|
||||||
|
CorePrincipal principal = (CorePrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
|
if (!principal.getRole().equals((byte)1) && !principal.getUserId().equals(userId)) {
|
||||||
|
throw new ForbiddenException("No tienes permiso");
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(credentialService.getByUserId(userId).stream()
|
||||||
|
.map(CredentialMapper::toDto)
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{credential_id}")
|
||||||
|
public ResponseEntity<CredentialDto> getById(@PathVariable("credential_id") UUID credentialId) {
|
||||||
|
CorePrincipal principal = (CorePrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
|
Credential cred = credentialService.getById(credentialId);
|
||||||
|
if (!principal.getRole().equals((byte)1) && !cred.getUserId().equals(principal.getUserId())) {
|
||||||
|
throw new ForbiddenException("No tienes permiso");
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(CredentialMapper.toDto(cred));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{credential_id}")
|
||||||
|
public ResponseEntity<CredentialDto> update(
|
||||||
|
@PathVariable("credential_id") UUID credentialId,
|
||||||
|
@RequestBody UpdateCredentialDto dto
|
||||||
|
) {
|
||||||
|
CorePrincipal principal = (CorePrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
|
Credential cred = credentialService.getById(credentialId);
|
||||||
|
if (!principal.getRole().equals((byte)1) && !cred.getUserId().equals(principal.getUserId())) {
|
||||||
|
throw new ForbiddenException("No tienes permiso");
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
CredentialMapper.toDto(
|
||||||
|
credentialService.update(credentialId, CredentialMapper.toEntity(dto))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{credential_id}/full")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<CredentialDto> updateFull(
|
||||||
|
@PathVariable("credential_id") UUID credentialId,
|
||||||
|
@RequestBody CredentialDto dto
|
||||||
|
) {
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
CredentialMapper.toDto(
|
||||||
|
credentialService.update(credentialId, CredentialMapper.toEntity(dto))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{service_id}/{user_id}/status")
|
||||||
|
public ResponseEntity<Byte> getStatus(@PathVariable("user_id") UUID userId, @PathVariable("service_id") Byte serviceId) {
|
||||||
|
return ResponseEntity.ok(credentialService.getStatus(userId, serviceId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,90 @@
|
|||||||
package net.miarma.backend.core.controller;
|
package net.miarma.backend.core.controller;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.mapper.FileMapper;
|
||||||
|
import net.miarma.backlib.dto.FileDto;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RequestPart;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.model.File;
|
||||||
|
import net.miarma.backend.core.service.FileService;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/files")
|
||||||
public class FileController {
|
public class FileController {
|
||||||
|
|
||||||
|
private final FileService fileService;
|
||||||
|
|
||||||
|
public FileController(FileService fileService) {
|
||||||
|
this.fileService = fileService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<List<File>> getAll() {
|
||||||
|
List<File> files = fileService.getAll();
|
||||||
|
return ResponseEntity.ok(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{file_id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or @fileService.isOwner(#file_id, authentication.principal.userId)")
|
||||||
|
public ResponseEntity<File> getById(@PathVariable("file_id") UUID fileId) {
|
||||||
|
File file = fileService.getById(fileId);
|
||||||
|
return ResponseEntity.ok(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(consumes = "multipart/form-data")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or #uploadedBy == authentication.principal.userId")
|
||||||
|
public ResponseEntity<FileDto.Response> create(
|
||||||
|
@RequestPart("file") MultipartFile file,
|
||||||
|
@RequestPart("fileName") String fileName,
|
||||||
|
@RequestPart("mimeType") String mimeType,
|
||||||
|
@RequestPart("uploadedBy") UUID uploadedBy,
|
||||||
|
@RequestPart("context") Integer context
|
||||||
|
) throws IOException {
|
||||||
|
|
||||||
|
File entity = new File();
|
||||||
|
entity.setFileName(fileName);
|
||||||
|
entity.setMimeType(mimeType);
|
||||||
|
entity.setUploadedBy(uploadedBy);
|
||||||
|
entity.setContext(context.byteValue());
|
||||||
|
|
||||||
|
File created = fileService.create(entity, file.getBytes());
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED)
|
||||||
|
.body(FileMapper.toResponse(created));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{file_id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or @fileService.isOwner(#file_id, authentication.principal.userId)")
|
||||||
|
public ResponseEntity<File> update(@PathVariable("file_id") UUID fileId, @RequestBody FileDto.Request request) {
|
||||||
|
File updated = fileService.update(fileId, FileMapper.toEntity(request));
|
||||||
|
return ResponseEntity.ok(updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{file_id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or @fileService.isOwner(#file_id, authentication.principal.userId)")
|
||||||
|
public ResponseEntity<Void> delete(@PathVariable("file_id") UUID fileId, @RequestBody Map<String,String> body) throws IOException {
|
||||||
|
String filePath = body.get("file_path");
|
||||||
|
Files.deleteIfExists(Paths.get(filePath));
|
||||||
|
fileService.delete(fileId);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,174 @@
|
|||||||
package net.miarma.backend.core.controller;
|
package net.miarma.backend.core.controller;
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import java.util.List;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.mapper.CredentialMapper;
|
||||||
|
import net.miarma.backend.core.model.Credential;
|
||||||
|
import net.miarma.backend.core.service.CredentialService;
|
||||||
|
import net.miarma.backlib.dto.*;
|
||||||
|
import org.apache.coyote.Response;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.mapper.UserMapper;
|
||||||
|
import net.miarma.backend.core.model.User;
|
||||||
|
import net.miarma.backlib.security.JwtService;
|
||||||
|
import net.miarma.backend.core.service.UserService;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/users")
|
@RequestMapping("/users")
|
||||||
public class UserController {
|
public class UserController {
|
||||||
|
private UserService userService;
|
||||||
|
private CredentialService credentialService;
|
||||||
|
private JwtService jwtService;
|
||||||
|
|
||||||
|
public UserController(UserService userService, CredentialService credentialService, JwtService jwtService) {
|
||||||
|
this.userService = userService;
|
||||||
|
this.credentialService = credentialService;
|
||||||
|
this.jwtService = jwtService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<List<UserDto>> getAll() {
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
userService.getAll()
|
||||||
|
.stream()
|
||||||
|
.map(UserMapper::toDto)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<UserDto> create(@RequestBody CreateUserDto dto) {
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
UserMapper.toDto(
|
||||||
|
userService.create(
|
||||||
|
UserMapper.fromCreateDto(dto)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{user_id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<UserDto> getById(@PathVariable("user_id") UUID userId) {
|
||||||
|
User user = userService.getById(userId);
|
||||||
|
return ResponseEntity.ok(UserMapper.toDto(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/service/{service_id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<List<UserWithCredentialDto>> getAllWithCredentials(
|
||||||
|
@PathVariable("service_id") Byte serviceId
|
||||||
|
) {
|
||||||
|
List<Credential> credentials = credentialService.getByServiceIdFetchUser(serviceId);
|
||||||
|
|
||||||
|
List<UserWithCredentialDto> result = credentials.stream()
|
||||||
|
.map(cred -> new UserWithCredentialDto(
|
||||||
|
UserMapper.toDto(cred.getUser()),
|
||||||
|
CredentialMapper.toDto(cred)
|
||||||
|
))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{user_id}/service/{service_id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<UserWithCredentialDto> getByIdWithCredentials(
|
||||||
|
@PathVariable("user_id") UUID userId,
|
||||||
|
@PathVariable("service_id") Byte serviceId
|
||||||
|
) {
|
||||||
|
User user = userService.getById(userId);
|
||||||
|
Credential credential = credentialService.getByUserIdAndService(userId, serviceId);
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
UserMapper.toDtoWithCredentials(
|
||||||
|
UserMapper.toDto(user),
|
||||||
|
CredentialMapper.toDto(credential)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{user_id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or #userId == principal.userId")
|
||||||
|
public ResponseEntity<UserDto> update(
|
||||||
|
@PathVariable("user_id") UUID userId,
|
||||||
|
@RequestBody UserDto dto
|
||||||
|
) {
|
||||||
|
User updated = userService.update(userId, UserMapper.fromDto(dto));
|
||||||
|
return ResponseEntity.ok(UserMapper.toDto(updated));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{user_id}/avatar")
|
||||||
|
public ResponseEntity<String> getAvatar(@PathVariable("user_id") UUID userId) {
|
||||||
|
return ResponseEntity.ok(userService.getById(userId).getAvatar());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{user_id}/avatar")
|
||||||
|
public ResponseEntity<UserDto> updateAvatar(@PathVariable("user_id") UUID userId, @RequestBody ChangeAvatarRequest avatar) {
|
||||||
|
return ResponseEntity.ok(userService.updateAvatar(userId, avatar));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{user_id}/status")
|
||||||
|
public ResponseEntity<Byte> getStatus(@PathVariable("user_id") UUID userId) {
|
||||||
|
return ResponseEntity.ok(userService.getStatus(userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{user_id}/status")
|
||||||
|
public ResponseEntity<Void> updateStatus(
|
||||||
|
@PathVariable("user_id") UUID userId,
|
||||||
|
@RequestBody ChangeStatusRequest req
|
||||||
|
) {
|
||||||
|
userService.updateStatus(userId, req.status());
|
||||||
|
return ResponseEntity.noContent().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{user_id}/role")
|
||||||
|
public ResponseEntity<Byte> getRole(@PathVariable("user_id") UUID userId) {
|
||||||
|
return ResponseEntity.ok(userService.getRole(userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{user_id}/role")
|
||||||
|
public ResponseEntity<Void> updateRole(
|
||||||
|
@PathVariable("user_id") UUID userid,
|
||||||
|
@RequestBody ChangeRoleRequest req
|
||||||
|
) {
|
||||||
|
userService.updateRole(userid, req.role());
|
||||||
|
return ResponseEntity.noContent().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{user_id}/exists")
|
||||||
|
public ResponseEntity<UserExistsResponse> exists(@PathVariable("user_id") UUID userId) {
|
||||||
|
boolean exists = userService.exists(userId);
|
||||||
|
return ResponseEntity.ok(new UserExistsResponse(exists));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/me")
|
||||||
|
public ResponseEntity<UserDto> getMe(@RequestHeader("Authorization") String authHeader) {
|
||||||
|
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
String token = authHeader.substring(7);
|
||||||
|
|
||||||
|
UUID userId;
|
||||||
|
try {
|
||||||
|
userId = jwtService.getUserId(token);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = userService.getById(userId);
|
||||||
|
return ResponseEntity.ok(UserMapper.toDto(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{user_id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseEntity<Void> delete(@PathVariable("user_id") UUID userId) {
|
||||||
|
userService.delete(userId);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
package net.miarma.backend.core.dto;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
|
|
||||||
public class LoginRequest {
|
|
||||||
@NotBlank
|
|
||||||
private String username;
|
|
||||||
|
|
||||||
@NotBlank
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
private short serviceId;
|
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUsername(String username) {
|
|
||||||
this.username = username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getServiceId() {
|
|
||||||
return serviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setServiceId(short serviceId) {
|
|
||||||
this.serviceId = serviceId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package net.miarma.backend.core.dto;
|
|
||||||
|
|
||||||
public class LoginResponse {
|
|
||||||
private String token;
|
|
||||||
private short serviceId;
|
|
||||||
private UserDto user;
|
|
||||||
|
|
||||||
public LoginResponse(String token, short serviceId, UserDto user) {
|
|
||||||
this.token = token;
|
|
||||||
this.serviceId = serviceId;
|
|
||||||
this.user = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToken() {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToken(String token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getServiceId() {
|
|
||||||
return serviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setServiceId(short serviceId) {
|
|
||||||
this.serviceId = serviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserDto getUser() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUser(UserDto user) {
|
|
||||||
this.user = user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package net.miarma.backend.core.dto;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UpdateCredentialDto {
|
||||||
|
private String email;
|
||||||
|
private String username;
|
||||||
|
private Byte status;
|
||||||
|
|
||||||
|
public UpdateCredentialDto() { }
|
||||||
|
|
||||||
|
public UpdateCredentialDto(String email, String username, Byte status) {
|
||||||
|
this.email = email;
|
||||||
|
this.username = username;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Byte getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Byte status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
package net.miarma.backend.core.dto;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class UserDto {
|
|
||||||
private UUID userId;
|
|
||||||
private String displayName;
|
|
||||||
private String avatar;
|
|
||||||
private Byte globalStatus;
|
|
||||||
private Byte globalRole;
|
|
||||||
private Instant createdAt;
|
|
||||||
private Instant updatedAt;
|
|
||||||
|
|
||||||
public UserDto(UUID userId, String displayName, String avatar, Byte globalStatus, Byte globalRole,
|
|
||||||
Instant createdAt, Instant updatedAt) {
|
|
||||||
this.userId = userId;
|
|
||||||
this.displayName = displayName;
|
|
||||||
this.avatar = avatar;
|
|
||||||
this.globalStatus = globalStatus;
|
|
||||||
this.globalRole = globalRole;
|
|
||||||
this.createdAt = createdAt;
|
|
||||||
this.updatedAt = updatedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UUID getUserId() {
|
|
||||||
return userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserId(UUID userId) {
|
|
||||||
this.userId = userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDisplayName() {
|
|
||||||
return displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDisplayName(String displayName) {
|
|
||||||
this.displayName = displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAvatar() {
|
|
||||||
return avatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAvatar(String avatar) {
|
|
||||||
this.avatar = avatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Byte getGlobalStatus() {
|
|
||||||
return globalStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGlobalStatus(Byte globalStatus) {
|
|
||||||
this.globalStatus = globalStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Byte getGlobalRole() {
|
|
||||||
return globalRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGlobalRole(Byte globalRole) {
|
|
||||||
this.globalRole = globalRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Instant getCreatedAt() {
|
|
||||||
return createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCreatedAt(Instant createdAt) {
|
|
||||||
this.createdAt = createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Instant getUpdatedAt() {
|
|
||||||
return updatedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdatedAt(Instant updatedAt) {
|
|
||||||
this.updatedAt = updatedAt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package net.miarma.backend.core.mapper;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.dto.UpdateCredentialDto;
|
||||||
|
import net.miarma.backend.core.model.Credential;
|
||||||
|
import net.miarma.backlib.dto.CreateCredentialDto;
|
||||||
|
import net.miarma.backlib.dto.CredentialDto;
|
||||||
|
import org.hibernate.sql.Update;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class CredentialMapper {
|
||||||
|
|
||||||
|
public static CredentialDto toDto(Credential c) {
|
||||||
|
if (c == null) return null;
|
||||||
|
|
||||||
|
return new CredentialDto(
|
||||||
|
c.getCredentialId(),
|
||||||
|
c.getUserId(),
|
||||||
|
c.getServiceId(),
|
||||||
|
c.getUsername(),
|
||||||
|
c.getEmail(),
|
||||||
|
c.getStatus(),
|
||||||
|
c.getCreatedAt(),
|
||||||
|
c.getUpdatedAt()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CreateCredentialDto toCreateDto(Credential c) {
|
||||||
|
if (c == null) return null;
|
||||||
|
|
||||||
|
return new CreateCredentialDto(
|
||||||
|
c.getUserId(),
|
||||||
|
c.getServiceId(),
|
||||||
|
c.getUsername(),
|
||||||
|
c.getEmail(),
|
||||||
|
c.getPassword(),
|
||||||
|
c.getStatus()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Credential toEntity(CredentialDto dto) {
|
||||||
|
if (dto == null) return null;
|
||||||
|
|
||||||
|
Credential c = new Credential();
|
||||||
|
c.setCredentialId(dto.getCredentialId());
|
||||||
|
c.setUserId(dto.getUserId());
|
||||||
|
c.setServiceId(dto.getServiceId());
|
||||||
|
c.setUsername(dto.getUsername());
|
||||||
|
c.setEmail(dto.getEmail());
|
||||||
|
c.setStatus(dto.getStatus());
|
||||||
|
c.setCreatedAt(dto.getCreatedAt());
|
||||||
|
c.setUpdatedAt(dto.getUpdatedAt());
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Credential toEntity(CreateCredentialDto dto) {
|
||||||
|
if (dto == null) return null;
|
||||||
|
|
||||||
|
Credential c = new Credential();
|
||||||
|
c.setUserId(dto.getUserId());
|
||||||
|
c.setServiceId(dto.getServiceId());
|
||||||
|
c.setUsername(dto.getUsername());
|
||||||
|
c.setEmail(dto.getEmail());
|
||||||
|
c.setPassword(dto.getPassword());
|
||||||
|
c.setStatus(dto.getStatus());
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Credential toEntity(UpdateCredentialDto dto) {
|
||||||
|
if (dto == null) return null;
|
||||||
|
|
||||||
|
Credential c = new Credential();
|
||||||
|
c.setEmail(dto.getEmail());
|
||||||
|
c.setUsername(dto.getUsername());
|
||||||
|
c.setStatus(dto.getStatus());
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package net.miarma.backend.core.mapper;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.model.File;
|
||||||
|
import net.miarma.backlib.dto.FileDto;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class FileMapper {
|
||||||
|
|
||||||
|
private FileMapper() {}
|
||||||
|
|
||||||
|
public static FileDto.Response toResponse(File file) {
|
||||||
|
FileDto.Response res = new FileDto.Response();
|
||||||
|
|
||||||
|
res.setFileId(file.getFileId());
|
||||||
|
res.setFileName(file.getFileName());
|
||||||
|
res.setFilePath(file.getFilePath());
|
||||||
|
res.setMimeType(file.getMimeType());
|
||||||
|
res.setUploadedBy(file.getUploadedBy());
|
||||||
|
res.setUploadedAt(file.getUploadedAt());
|
||||||
|
res.setContext(file.getContext());
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File toEntity(FileDto.Request req) {
|
||||||
|
File file = new File();
|
||||||
|
|
||||||
|
file.setFileId(UUID.randomUUID());
|
||||||
|
file.setFileName(req.getFileName());
|
||||||
|
file.setFilePath(req.getFilePath());
|
||||||
|
file.setMimeType(req.getMimeType());
|
||||||
|
file.setUploadedBy(req.getUploadedBy());
|
||||||
|
file.setContext(req.getContext());
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package net.miarma.backend.core.mapper;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.model.User;
|
||||||
|
import net.miarma.backlib.dto.CreateUserDto;
|
||||||
|
import net.miarma.backlib.dto.CredentialDto;
|
||||||
|
import net.miarma.backlib.dto.UserDto;
|
||||||
|
import net.miarma.backlib.dto.UserWithCredentialDto;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UserMapper {
|
||||||
|
public static User fromDto(UserDto dto) {
|
||||||
|
if (dto == null) return null;
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
user.setDisplayName(dto.getDisplayName());
|
||||||
|
user.setAvatar(dto.getAvatar());
|
||||||
|
user.setGlobalRole(dto.getGlobalRole());
|
||||||
|
user.setGlobalStatus(dto.getGlobalStatus());
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static User fromCreateDto(CreateUserDto dto) {
|
||||||
|
User user = new User();
|
||||||
|
user.setUserId(UUID.randomUUID());
|
||||||
|
user.setDisplayName(dto.displayName());
|
||||||
|
user.setAvatar(dto.avatar() != null ? dto.avatar() : null);
|
||||||
|
user.setGlobalRole((byte)0);
|
||||||
|
user.setGlobalStatus((byte)1);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserDto toDto(User u) {
|
||||||
|
if (u == null) return null;
|
||||||
|
|
||||||
|
return new UserDto(
|
||||||
|
u.getUserId(),
|
||||||
|
u.getDisplayName(),
|
||||||
|
u.getAvatar(),
|
||||||
|
u.getGlobalStatus(),
|
||||||
|
u.getGlobalRole(),
|
||||||
|
u.getCreatedAt(),
|
||||||
|
u.getUpdatedAt()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserWithCredentialDto toDtoWithCredentials(UserDto user, CredentialDto account){
|
||||||
|
if (user == null || account == null) return null;
|
||||||
|
|
||||||
|
return new UserWithCredentialDto(user, account);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,79 +19,66 @@ import jakarta.persistence.PreUpdate;
|
|||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import jakarta.persistence.Transient;
|
import jakarta.persistence.Transient;
|
||||||
import jakarta.persistence.UniqueConstraint;
|
import jakarta.persistence.UniqueConstraint;
|
||||||
|
import net.miarma.backlib.util.UuidUtil;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(
|
@Table(name = "credentials",
|
||||||
name = "credentials",
|
uniqueConstraints = {
|
||||||
uniqueConstraints = {
|
@UniqueConstraint(columnNames = { "service_id", "username" }),
|
||||||
@UniqueConstraint(columnNames = {"service_id", "username"}),
|
@UniqueConstraint(columnNames = { "service_id", "email" })
|
||||||
@UniqueConstraint(columnNames = {"service_id", "email"})
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
public class Credential {
|
public class Credential {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@Column(columnDefinition = "BINARY(16)")
|
@Column(name = "credential_id", columnDefinition = "BINARY(16)")
|
||||||
private byte[] credentialIdBin;
|
private byte[] credentialIdBin;
|
||||||
|
|
||||||
@Column(name = "user_id", columnDefinition = "BINARY(16)")
|
@Column(name = "user_id", columnDefinition = "BINARY(16)")
|
||||||
private byte[] userIdBin;
|
private byte[] userIdBin;
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private UUID credentialId;
|
private UUID credentialId;
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private UUID userId;
|
private UUID userId;
|
||||||
|
|
||||||
@Column(name = "service_id")
|
@Column(name = "service_id")
|
||||||
private Byte serviceId;
|
private Byte serviceId;
|
||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
private String email;
|
private String email;
|
||||||
private String password;
|
private String password;
|
||||||
|
private Byte status;
|
||||||
|
|
||||||
private Byte status;
|
@CreationTimestamp
|
||||||
|
private Instant createdAt;
|
||||||
|
|
||||||
@CreationTimestamp
|
@UpdateTimestamp
|
||||||
private Instant createdAt;
|
private Instant updatedAt;
|
||||||
|
|
||||||
@UpdateTimestamp
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
private Instant updatedAt;
|
@JoinColumn(name = "user_id", insertable = false, updatable = false)
|
||||||
|
private User user;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@PrePersist
|
||||||
@JoinColumn(name = "user_id", insertable = false, updatable = false)
|
|
||||||
private User user;
|
|
||||||
|
|
||||||
@PrePersist
|
|
||||||
@PreUpdate
|
@PreUpdate
|
||||||
private void prePersist() {
|
private void prePersist() {
|
||||||
if (credentialId != null) {
|
if (credentialId != null) {
|
||||||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
credentialIdBin = UuidUtil.uuidToBin(credentialId);
|
||||||
bb.putLong(credentialId.getMostSignificantBits());
|
|
||||||
bb.putLong(credentialId.getLeastSignificantBits());
|
|
||||||
credentialIdBin = bb.array();
|
|
||||||
}
|
}
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
userIdBin = UuidUtil.uuidToBin(userId);
|
||||||
bb.putLong(userId.getMostSignificantBits());
|
|
||||||
bb.putLong(userId.getLeastSignificantBits());
|
|
||||||
userIdBin = bb.array();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostLoad
|
@PostLoad
|
||||||
private void postLoad() {
|
private void postLoad() {
|
||||||
if (credentialIdBin != null) {
|
if (credentialIdBin != null) {
|
||||||
ByteBuffer bb = ByteBuffer.wrap(credentialIdBin);
|
credentialId = UuidUtil.binToUUID(credentialIdBin);
|
||||||
long high = bb.getLong();
|
|
||||||
long low = bb.getLong();
|
|
||||||
credentialId = new UUID(high, low);
|
|
||||||
}
|
}
|
||||||
if (userIdBin != null) {
|
if (userIdBin != null) {
|
||||||
ByteBuffer bb = ByteBuffer.wrap(userIdBin);
|
userId = UuidUtil.binToUUID(userIdBin);
|
||||||
long high = bb.getLong();
|
|
||||||
long low = bb.getLong();
|
|
||||||
userId = new UUID(high, low);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,12 @@ import java.util.UUID;
|
|||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.PostLoad;
|
||||||
import jakarta.persistence.PrePersist;
|
import jakarta.persistence.PrePersist;
|
||||||
|
import jakarta.persistence.PreUpdate;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import jakarta.persistence.Transient;
|
import jakarta.persistence.Transient;
|
||||||
|
import net.miarma.backlib.util.UuidUtil;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "files")
|
@Table(name = "files")
|
||||||
@@ -40,15 +43,28 @@ public class File {
|
|||||||
private Instant uploadedAt;
|
private Instant uploadedAt;
|
||||||
|
|
||||||
@Column(name = "context", nullable = false)
|
@Column(name = "context", nullable = false)
|
||||||
private Short context;
|
private Byte context;
|
||||||
|
|
||||||
@PrePersist
|
@PrePersist
|
||||||
public void prePersist() {
|
@PreUpdate
|
||||||
if (fileId == null) {
|
private void prePersist() {
|
||||||
fileId = UUID.randomUUID();
|
if (fileId != null) {
|
||||||
|
fileIdBin = UuidUtil.uuidToBin(fileId);
|
||||||
}
|
}
|
||||||
if (uploadedAt == null) {
|
|
||||||
uploadedAt = Instant.now();
|
if (uploadedBy != null) {
|
||||||
|
uploadedByBin = UuidUtil.uuidToBin(uploadedBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostLoad
|
||||||
|
private void postLoad() {
|
||||||
|
if (fileIdBin != null) {
|
||||||
|
fileId = UuidUtil.binToUUID(fileIdBin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uploadedByBin != null) {
|
||||||
|
uploadedBy = UuidUtil.binToUUID(uploadedByBin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,11 +112,11 @@ public class File {
|
|||||||
return uploadedAt;
|
return uploadedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Short getContext() {
|
public Byte getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContext(Short context) {
|
public void setContext(Byte context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package net.miarma.backend.core.model;
|
package net.miarma.backend.core.model;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -15,6 +14,7 @@ import jakarta.persistence.PrePersist;
|
|||||||
import jakarta.persistence.PreUpdate;
|
import jakarta.persistence.PreUpdate;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import jakarta.persistence.Transient;
|
import jakarta.persistence.Transient;
|
||||||
|
import net.miarma.backlib.util.UuidUtil;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "users")
|
@Table(name = "users")
|
||||||
@@ -48,20 +48,14 @@ public class User {
|
|||||||
@PreUpdate
|
@PreUpdate
|
||||||
private void prePersist() {
|
private void prePersist() {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
userIdBin = UuidUtil.uuidToBin(userId);
|
||||||
bb.putLong(userId.getMostSignificantBits());
|
|
||||||
bb.putLong(userId.getLeastSignificantBits());
|
|
||||||
userIdBin = bb.array();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostLoad
|
@PostLoad
|
||||||
private void postLoad() {
|
private void postLoad() {
|
||||||
if (userIdBin != null) {
|
if (userIdBin != null) {
|
||||||
ByteBuffer bb = ByteBuffer.wrap(userIdBin);
|
userId = UuidUtil.binToUUID(userIdBin);
|
||||||
long high = bb.getLong();
|
|
||||||
long low = bb.getLong();
|
|
||||||
userId = new UUID(high, low);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,60 @@ import java.util.List;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
import net.miarma.backend.core.model.Credential;
|
import net.miarma.backend.core.model.Credential;
|
||||||
|
|
||||||
public interface CredentialRepository extends JpaRepository<Credential, UUID> {
|
public interface CredentialRepository extends JpaRepository<Credential, byte[]> {
|
||||||
|
|
||||||
Optional<Credential> findByServiceIdAndUsername(short serviceId, String username);
|
@Query("""
|
||||||
|
SELECT c FROM Credential c
|
||||||
|
JOIN FETCH c.user
|
||||||
|
WHERE c.serviceId = :serviceId
|
||||||
|
AND c.username = :username
|
||||||
|
""")
|
||||||
|
Optional<Credential> findByServiceIdAndUsername(@Param("serviceId") Byte serviceId,
|
||||||
|
@Param("username") String username);
|
||||||
|
|
||||||
Optional<Credential> findByServiceIdAndEmail(short serviceId, String email);
|
List<Credential> findAllByServiceId(Byte serviceId);
|
||||||
|
|
||||||
Optional<Credential> findByUserIdAndServiceId(UUID userId, short serviceId);
|
@Query("SELECT c FROM Credential c JOIN FETCH c.user WHERE c.serviceId = :serviceId")
|
||||||
|
List<Credential> getByServiceIdFetchUser(@Param("serviceId") Byte serviceId);
|
||||||
|
|
||||||
List<Credential> findByUserId(UUID userId);
|
Optional<Credential> findByServiceIdAndEmail(Byte serviceId, String email);
|
||||||
|
|
||||||
|
@Query("SELECT c FROM Credential c WHERE c.userIdBin = :userIdBin AND c.serviceId = :serviceId")
|
||||||
|
Optional<Credential> findByUserIdAndServiceId(@Param("userIdBin") byte[] userIdBin, @Param("serviceId") Byte serviceId);
|
||||||
|
|
||||||
|
Optional<Credential> findByUsernameAndServiceId(String username, Byte serviceId);
|
||||||
|
|
||||||
|
@Query("SELECT c FROM Credential c WHERE c.userIdBin = :userIdBin")
|
||||||
|
List<Credential> findByUserId(@Param("userIdBin") byte[] userIdBin);
|
||||||
|
|
||||||
|
@Query("SELECT c FROM Credential c WHERE c.email = :email")
|
||||||
|
List<Credential> findByEmail(@Param("email") String email);
|
||||||
|
|
||||||
|
boolean existsByUsernameAndServiceId(String username, Byte serviceId);
|
||||||
|
|
||||||
|
boolean existsByEmailAndServiceId(String email, Byte serviceId);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("""
|
||||||
|
UPDATE Credential c
|
||||||
|
SET c.username = :username,
|
||||||
|
c.email = :email,
|
||||||
|
c.status = :status
|
||||||
|
WHERE c.credentialIdBin = :credentialIdBin
|
||||||
|
""")
|
||||||
|
int update(@Param("credentialIdBin") byte[] credentialIdBin,
|
||||||
|
@Param("username") String username,
|
||||||
|
@Param("email") String email,
|
||||||
|
@Param("status") Byte status);
|
||||||
|
|
||||||
|
List<Credential> findByUsername(@NotBlank String username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,16 @@
|
|||||||
package net.miarma.backend.core.repository;
|
package net.miarma.backend.core.repository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
import net.miarma.backend.core.model.File;
|
import net.miarma.backend.core.model.File;
|
||||||
|
|
||||||
public interface FileRepository extends JpaRepository<File, UUID> {
|
public interface FileRepository extends JpaRepository<File, byte[]> {
|
||||||
|
|
||||||
Optional<File> findById(UUID fileId);
|
|
||||||
|
|
||||||
List<File> findByUploadedBy(UUID uploadedBy);
|
List<File> findByUploadedBy(UUID uploadedBy);
|
||||||
|
|
||||||
List<File> findByContext(short context);
|
List<File> findByContext(Byte context);
|
||||||
|
|
||||||
List<File> findByUploadedByAndContext(UUID uploadedBy, short context);
|
List<File> findByUploadedByAndContext(UUID uploadedBy, Byte context);
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
package net.miarma.backend.core.repository;
|
package net.miarma.backend.core.repository;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
import net.miarma.backend.core.model.User;
|
import net.miarma.backend.core.model.User;
|
||||||
|
|
||||||
public interface UserRepository extends JpaRepository<User, UUID> {
|
public interface UserRepository extends JpaRepository<User, byte[]> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package net.miarma.backend.core.security;
|
||||||
|
|
||||||
|
import net.miarma.backlib.security.CoreAuthTokenHolder;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class CorePrincipal implements UserDetails {
|
||||||
|
private final UUID userId;
|
||||||
|
private final Byte role;
|
||||||
|
|
||||||
|
public CorePrincipal(UUID userId, Byte role) {
|
||||||
|
this.userId = userId;
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUserId() { return userId; }
|
||||||
|
public Byte getRole() { return role; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
List<GrantedAuthority> auth = new ArrayList<>();
|
||||||
|
|
||||||
|
String roleName = switch(role) {
|
||||||
|
case 0 -> "USER";
|
||||||
|
case 1 -> "ADMIN";
|
||||||
|
default -> "GUEST";
|
||||||
|
};
|
||||||
|
|
||||||
|
auth.add(new SimpleGrantedAuthority("ROLE_" + roleName));
|
||||||
|
|
||||||
|
return auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public String getPassword() { return ""; }
|
||||||
|
@Override public String getUsername() { return userId.toString(); }
|
||||||
|
@Override public boolean isAccountNonExpired() { return true; }
|
||||||
|
@Override public boolean isAccountNonLocked() { return true; }
|
||||||
|
@Override public boolean isCredentialsNonExpired() { return true; }
|
||||||
|
@Override public boolean isEnabled() { return true; }
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.miarma.backend.core.config;
|
package net.miarma.backend.core.security;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -8,7 +8,6 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
|||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
@@ -17,7 +16,7 @@ import jakarta.servlet.ServletException;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import net.miarma.backend.core.model.User;
|
import net.miarma.backend.core.model.User;
|
||||||
import net.miarma.backend.core.service.JwtService;
|
import net.miarma.backlib.security.JwtService;
|
||||||
import net.miarma.backend.core.service.UserService;
|
import net.miarma.backend.core.service.UserService;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -36,7 +35,6 @@ public class JwtFilter extends OncePerRequestFilter {
|
|||||||
protected void doFilterInternal(HttpServletRequest request,
|
protected void doFilterInternal(HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
FilterChain filterChain) throws ServletException, IOException {
|
FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
|
||||||
String authHeader = request.getHeader("Authorization");
|
String authHeader = request.getHeader("Authorization");
|
||||||
if (authHeader != null && authHeader.startsWith("Bearer ")) {
|
if (authHeader != null && authHeader.startsWith("Bearer ")) {
|
||||||
String token = authHeader.substring(7);
|
String token = authHeader.substring(7);
|
||||||
@@ -44,17 +42,11 @@ public class JwtFilter extends OncePerRequestFilter {
|
|||||||
try {
|
try {
|
||||||
if (jwtService.validateToken(token)) {
|
if (jwtService.validateToken(token)) {
|
||||||
UUID userId = jwtService.getUserId(token);
|
UUID userId = jwtService.getUserId(token);
|
||||||
short serviceId = jwtService.getServiceId(token);
|
Byte serviceId = jwtService.getServiceId(token);
|
||||||
|
|
||||||
User user = userService.getById(userId);
|
User user = userService.getById(userId);
|
||||||
|
CorePrincipal principal = new CorePrincipal(userId, user.getGlobalRole());
|
||||||
List<GrantedAuthority> authorities = List.of(
|
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities());
|
||||||
new SimpleGrantedAuthority("ROLE_" + user.getGlobalRole())
|
|
||||||
);
|
|
||||||
|
|
||||||
UsernamePasswordAuthenticationToken auth =
|
|
||||||
new UsernamePasswordAuthenticationToken(user, null, authorities);
|
|
||||||
auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
|
||||||
long timeLeft = jwtService.getExpiration(token).getTime() - System.currentTimeMillis();
|
long timeLeft = jwtService.getExpiration(token).getTime() - System.currentTimeMillis();
|
||||||
@@ -1,46 +1,114 @@
|
|||||||
package net.miarma.backend.core.service;
|
package net.miarma.backend.core.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import net.miarma.backlib.dto.*;
|
||||||
|
import net.miarma.backlib.exception.*;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import net.miarma.backend.core.dto.LoginRequest;
|
import net.miarma.backend.core.mapper.CredentialMapper;
|
||||||
import net.miarma.backend.core.dto.LoginResponse;
|
import net.miarma.backend.core.mapper.UserMapper;
|
||||||
import net.miarma.backend.core.dto.UserDto;
|
|
||||||
import net.miarma.backend.core.model.Credential;
|
import net.miarma.backend.core.model.Credential;
|
||||||
|
import net.miarma.backend.core.model.User;
|
||||||
|
import tools.jackson.databind.JsonNode;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class AuthService {
|
public class AuthService {
|
||||||
|
|
||||||
private final CredentialService credentialService;
|
private final CredentialService credentialService;
|
||||||
private final JwtService jwtService;
|
private final UserService userService;
|
||||||
|
private final net.miarma.backlib.security.JwtService jwtService;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
public AuthService(CredentialService credentialService, JwtService jwtService,
|
public AuthService(CredentialService credentialService, UserService userService,
|
||||||
PasswordEncoder passwordEncoder) {
|
net.miarma.backlib.security.JwtService jwtService, PasswordEncoder passwordEncoder) {
|
||||||
this.credentialService = credentialService;
|
this.credentialService = credentialService;
|
||||||
|
this.userService = userService;
|
||||||
this.jwtService = jwtService;
|
this.jwtService = jwtService;
|
||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoginResponse login(LoginRequest request) {
|
public LoginResponse login(LoginRequest request) {
|
||||||
Credential cred = credentialService.getByUserIdAndService(request.getServiceId(), request.getUsername());
|
Credential cred = credentialService.getForLogin(request.serviceId(), request.username());
|
||||||
|
|
||||||
if (!passwordEncoder.matches(request.getPassword(), cred.getPassword())) {
|
if (!passwordEncoder.matches(request.password(), cred.getPassword())) {
|
||||||
throw new RuntimeException("Invalid credentials");
|
throw new UnauthorizedException("Credenciales no válidas");
|
||||||
}
|
}
|
||||||
|
|
||||||
String token = jwtService.generateToken(cred.getUserId(), request.getServiceId());
|
if (cred.getStatus() == 0) {
|
||||||
|
throw new ForbiddenException("Esa cuenta está desactivada");
|
||||||
|
}
|
||||||
|
|
||||||
UserDto userDto = new UserDto(
|
String token = jwtService.generateToken(cred.getUserId(), request.serviceId());
|
||||||
cred.getUser().getUserId(),
|
UserDto userDto = UserMapper.toDto(cred.getUser());
|
||||||
cred.getUser().getDisplayName(),
|
CredentialDto credentialDto = CredentialMapper.toDto(cred);
|
||||||
cred.getUser().getAvatar(),
|
|
||||||
cred.getUser().getGlobalStatus(),
|
|
||||||
cred.getUser().getGlobalRole(),
|
|
||||||
cred.getUser().getCreatedAt(),
|
|
||||||
cred.getUser().getUpdatedAt()
|
|
||||||
);
|
|
||||||
|
|
||||||
return new LoginResponse(token, request.getServiceId(), userDto);
|
return new LoginResponse(token, userDto, credentialDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginResponse register(RegisterRequest request) {
|
||||||
|
UUID userIdByUsername = null;
|
||||||
|
UUID userIdByEmail = null;
|
||||||
|
|
||||||
|
Optional<Credential> credByUsername = credentialService.getByUsername(request.username()).stream().findFirst();
|
||||||
|
if(credByUsername.isPresent()) {
|
||||||
|
userIdByUsername = credByUsername.get().getUserId();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Credential> accountsByEmail = credentialService.getByEmail(request.email());
|
||||||
|
if (!accountsByEmail.isEmpty()) {
|
||||||
|
userIdByEmail = accountsByEmail.getFirst().getUserId();
|
||||||
|
}
|
||||||
|
|
||||||
|
User user;
|
||||||
|
if (userIdByUsername != null && userIdByEmail != null) {
|
||||||
|
if (!userIdByUsername.equals(userIdByEmail)) {
|
||||||
|
throw new ConflictException("Username y email ya existen pero pertenecen a usuarios distintos");
|
||||||
|
}
|
||||||
|
user = userService.getById(userIdByUsername);
|
||||||
|
} else if (userIdByUsername != null) {
|
||||||
|
user = userService.getById(userIdByUsername);
|
||||||
|
} else if (userIdByEmail != null) {
|
||||||
|
user = userService.getById(userIdByEmail);
|
||||||
|
} else {
|
||||||
|
CreateUserDto dto = new CreateUserDto(request.displayName(), null);
|
||||||
|
user = userService.create(UserMapper.fromCreateDto(dto));
|
||||||
|
}
|
||||||
|
|
||||||
|
Credential cred = new Credential();
|
||||||
|
cred.setCredentialId(UUID.randomUUID());
|
||||||
|
cred.setUserId(user.getUserId());
|
||||||
|
cred.setUser(user);
|
||||||
|
cred.setServiceId(request.serviceId());
|
||||||
|
cred.setUsername(request.username());
|
||||||
|
cred.setEmail(request.email());
|
||||||
|
cred.setPassword(request.password());
|
||||||
|
cred.setStatus((byte)1);
|
||||||
|
credentialService.create(cred);
|
||||||
|
|
||||||
|
String token = jwtService.generateToken(user.getUserId(), request.serviceId());
|
||||||
|
|
||||||
|
return new LoginResponse(token, UserMapper.toDto(user), CredentialMapper.toDto(cred));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changePassword(UUID userId, ChangePasswordRequest request) {
|
||||||
|
Credential cred = credentialService.getByUserId(userId)
|
||||||
|
.stream()
|
||||||
|
.filter(c -> c.getServiceId().equals(request.serviceId()))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new NotFoundException("Cuenta no encontrada"));
|
||||||
|
|
||||||
|
if (!passwordEncoder.matches(request.oldPassword(), cred.getPassword())) {
|
||||||
|
throw new ValidationException("oldPassword", "La contraseña actual es incorrecta");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.newPassword().length() < 8) {
|
||||||
|
throw new ValidationException("newPassword", "La nueva contraseña debe tener al menos 8 caracteres");
|
||||||
|
}
|
||||||
|
|
||||||
|
credentialService.updatePassword(cred.getCredentialId(), request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,47 +3,163 @@ package net.miarma.backend.core.service;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import net.miarma.backlib.exception.*;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import net.miarma.backend.core.model.Credential;
|
import net.miarma.backend.core.model.Credential;
|
||||||
|
import net.miarma.backend.core.model.User;
|
||||||
import net.miarma.backend.core.repository.CredentialRepository;
|
import net.miarma.backend.core.repository.CredentialRepository;
|
||||||
|
import net.miarma.backlib.dto.ChangePasswordRequest;
|
||||||
|
import net.miarma.backlib.dto.CredentialDto;
|
||||||
|
import net.miarma.backlib.util.UuidUtil;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
public class CredentialService {
|
public class CredentialService {
|
||||||
|
|
||||||
private final CredentialRepository credentialRepository;
|
private final CredentialRepository credentialRepository;
|
||||||
|
private final UserService userService;
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
public CredentialService(CredentialRepository credentialRepository) {
|
public CredentialService(CredentialRepository credentialRepository, UserService userService, PasswordEncoder passwordEncoder) {
|
||||||
this.credentialRepository = credentialRepository;
|
this.credentialRepository = credentialRepository;
|
||||||
|
this.userService = userService;
|
||||||
|
this.passwordEncoder = passwordEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Credential getById(UUID id) {
|
public Credential getById(UUID credentialId) {
|
||||||
return credentialRepository.findById(id)
|
byte[] idBytes = UuidUtil.uuidToBin(credentialId);
|
||||||
.orElseThrow(() -> new RuntimeException("Credential not found"));
|
return credentialRepository.findById(idBytes)
|
||||||
|
.orElseThrow(() -> new NotFoundException("Cuenta no encontrada"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Credential create(Credential credential) {
|
public Credential create(Credential credential) {
|
||||||
// TODO: validate duplicates here
|
if (credential.getUsername() == null || credential.getUsername().isBlank()) {
|
||||||
|
throw new ValidationException("userName", "El usuario no puede estar vacío");
|
||||||
|
}
|
||||||
|
if (credential.getEmail() == null || !credential.getEmail().matches("^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$")) {
|
||||||
|
throw new ValidationException("email", "Formato de email no válido");
|
||||||
|
}
|
||||||
|
if (credential.getPassword() == null || credential.getPassword().length() < 6) {
|
||||||
|
throw new ValidationException("password", "La contraseña tiene que tener al menos 6 caracteres");
|
||||||
|
}
|
||||||
|
if (credential.getServiceId() == null || credential.getServiceId() < 0) {
|
||||||
|
throw new ValidationException("serviceId", "El identificador de servicio debe ser positivo");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean existsUsername = credentialRepository.existsByUsernameAndServiceId(
|
||||||
|
credential.getUsername(), credential.getServiceId());
|
||||||
|
if (existsUsername) throw new ConflictException("El usuario ya existe para este servicio");
|
||||||
|
|
||||||
|
boolean existsEmail = credentialRepository.existsByEmailAndServiceId(
|
||||||
|
credential.getEmail(), credential.getServiceId());
|
||||||
|
if (existsEmail) throw new ConflictException("El email ya existe para este servicio");
|
||||||
|
|
||||||
|
credential.setCredentialId(UUID.randomUUID());
|
||||||
|
credential.setPassword(passwordEncoder.encode(credential.getPassword()));
|
||||||
return credentialRepository.save(credential);
|
return credentialRepository.save(credential);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Credential> getAll() {
|
||||||
|
return credentialRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Credential> getByServiceId(Byte serviceId) {
|
||||||
|
return credentialRepository.findAllByServiceId(serviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Credential> getByServiceIdFetchUser(Byte serviceId) {
|
||||||
|
return credentialRepository.getByServiceIdFetchUser(serviceId);
|
||||||
|
}
|
||||||
|
|
||||||
public List<Credential> getByUserId(UUID userId) {
|
public List<Credential> getByUserId(UUID userId) {
|
||||||
List<Credential> creds = credentialRepository.findByUserId(userId);
|
List<Credential> creds = credentialRepository.findByUserId(UuidUtil.uuidToBin(userId));
|
||||||
if (creds.isEmpty()) {
|
if (creds.isEmpty()) {
|
||||||
throw new RuntimeException("User has no credentials");
|
throw new NotFoundException("El usuario no tiene cuenta");
|
||||||
}
|
}
|
||||||
return creds;
|
return creds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Credential getByUserIdAndService(short serviceId, String username) {
|
public List<Credential> getByUsername(@NotBlank String username) {
|
||||||
return credentialRepository.findByServiceIdAndUsername(serviceId, username)
|
return credentialRepository.findByUsername(username);
|
||||||
.orElseThrow(() -> new RuntimeException("Credential not found in this site"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Credential getForLogin(short serviceId, String username) {
|
public List<Credential> getByEmail(String email) {
|
||||||
|
return credentialRepository.findByEmail(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Credential getByUserIdAndService(UUID userId, Byte serviceId) {
|
||||||
|
return credentialRepository.findByUserIdAndServiceId(UuidUtil.uuidToBin(userId), serviceId)
|
||||||
|
.orElseThrow(() -> new NotFoundException("El usuario no tiene cuenta en este sitio"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Credential getForLogin(Byte serviceId, String username) {
|
||||||
return credentialRepository.findByServiceIdAndUsername(serviceId, username)
|
return credentialRepository.findByServiceIdAndUsername(serviceId, username)
|
||||||
.orElseThrow(() -> new RuntimeException("Invalid credentials"));
|
.orElseThrow(() -> new BadRequestException("Credenciales no válidas"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean existsByUsernameAndService(String username, Byte serviceId) {
|
||||||
|
return credentialRepository.findByUsernameAndServiceId(username, serviceId).isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOwner(UUID credentialId, UUID userId) {
|
||||||
|
byte[] idBytes = UuidUtil.uuidToBin(credentialId);
|
||||||
|
|
||||||
|
return credentialRepository.findById(idBytes)
|
||||||
|
.map(c -> c.getUserId().equals(userId))
|
||||||
|
.orElse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Credential update(UUID credentialId, Credential changes) {
|
||||||
|
Credential cred = getById(credentialId);
|
||||||
|
|
||||||
|
if (cred.getStatus() == (byte)0) {
|
||||||
|
throw new ForbiddenException("La cuenta está inactiva, contacta con un administrador");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changes.getUsername() != null) cred.setUsername(changes.getUsername());
|
||||||
|
if (changes.getEmail() != null) cred.setEmail(changes.getEmail());
|
||||||
|
if (changes.getStatus() != null) cred.setStatus(changes.getStatus());
|
||||||
|
|
||||||
|
int updated = credentialRepository.update(
|
||||||
|
UuidUtil.uuidToBin(cred.getCredentialId()),
|
||||||
|
cred.getUsername(),
|
||||||
|
cred.getEmail(),
|
||||||
|
cred.getStatus()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (updated == 0)
|
||||||
|
throw new RuntimeException("No se pudo actualizar la cuenta");
|
||||||
|
|
||||||
|
return getById(credentialId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Credential updatePassword(UUID credentialId, ChangePasswordRequest request) {
|
||||||
|
byte[] idBytes = UuidUtil.uuidToBin(credentialId);
|
||||||
|
|
||||||
|
Credential cred = credentialRepository.findById(idBytes)
|
||||||
|
.orElseThrow(() -> new NotFoundException("Cuenta no encontrada"));
|
||||||
|
|
||||||
|
if (!passwordEncoder.matches(request.oldPassword(), cred.getPassword())) {
|
||||||
|
throw new ValidationException("oldPassword", "La contraseña actual es incorrecta");
|
||||||
|
}
|
||||||
|
|
||||||
|
cred.setPassword(passwordEncoder.encode(request.newPassword()));
|
||||||
|
return credentialRepository.save(cred);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(UUID credentialId) {
|
||||||
|
byte[] idBytes = UuidUtil.uuidToBin(credentialId);
|
||||||
|
if(!credentialRepository.existsById(idBytes))
|
||||||
|
throw new NotFoundException("Cuenta no encontrada");
|
||||||
|
credentialRepository.deleteById(idBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Byte getStatus(UUID userId, Byte serviceId) {
|
||||||
|
Credential credential = getByUserIdAndService(userId, serviceId);
|
||||||
|
return credential.getStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,24 @@
|
|||||||
package net.miarma.backend.core.service;
|
package net.miarma.backend.core.service;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.mapper.FileMapper;
|
||||||
|
import net.miarma.backlib.dto.FileDto;
|
||||||
|
import net.miarma.backlib.exception.NotFoundException;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import net.miarma.backend.core.model.File;
|
import net.miarma.backend.core.model.File;
|
||||||
import net.miarma.backend.core.repository.FileRepository;
|
import net.miarma.backend.core.repository.FileRepository;
|
||||||
|
import net.miarma.backlib.util.UuidUtil;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -15,32 +26,65 @@ public class FileService {
|
|||||||
|
|
||||||
private final FileRepository fileRepository;
|
private final FileRepository fileRepository;
|
||||||
|
|
||||||
|
@Value("${filesDir}")
|
||||||
|
private String filesDir;
|
||||||
|
|
||||||
public FileService(FileRepository fileRepository) {
|
public FileService(FileRepository fileRepository) {
|
||||||
this.fileRepository = fileRepository;
|
this.fileRepository = fileRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public File get(UUID fileId) {
|
public File getById(UUID fileId) {
|
||||||
return fileRepository.findById(fileId)
|
byte[] idBytes = UuidUtil.uuidToBin(fileId);
|
||||||
.orElseThrow(() -> new RuntimeException("File not found"));
|
return fileRepository.findById(idBytes)
|
||||||
|
.orElseThrow(() -> new NotFoundException("Archivo no encontrado"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<File> listByUser(UUID userId) {
|
public List<File> getAll() {
|
||||||
|
return fileRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<File> getByUserId(UUID userId) {
|
||||||
return fileRepository.findByUploadedBy(userId);
|
return fileRepository.findByUploadedBy(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<File> listByContext(short context) {
|
public File create(File file, byte[] fileBinary) throws IOException {
|
||||||
return fileRepository.findByContext(context);
|
Path dirPath = Paths.get(filesDir, String.valueOf(file.getContext()));
|
||||||
}
|
if (!Files.exists(dirPath)) {
|
||||||
|
Files.createDirectories(dirPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Path filePath = dirPath.resolve(file.getFileName());
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(filePath.toFile())) {
|
||||||
|
fos.write(fileBinary);
|
||||||
|
}
|
||||||
|
|
||||||
|
file.setFilePath(filePath.toString());
|
||||||
|
|
||||||
public File create(File file) {
|
|
||||||
return fileRepository.save(file);
|
return fileRepository.save(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete(UUID fileId) {
|
public File update(UUID fileId, File file) {
|
||||||
if (!fileRepository.existsById(fileId)) {
|
byte[] idBytes = UuidUtil.uuidToBin(fileId);
|
||||||
throw new RuntimeException("File not found");
|
if (!fileRepository.existsById(idBytes)) {
|
||||||
|
throw new NotFoundException("Archivo no encontrado");
|
||||||
}
|
}
|
||||||
fileRepository.deleteById(fileId);
|
return fileRepository.save(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void delete(UUID fileId) {
|
||||||
|
byte[] idBytes = UuidUtil.uuidToBin(fileId);
|
||||||
|
if (!fileRepository.existsById(idBytes)) {
|
||||||
|
throw new NotFoundException("Archivo no encontrado");
|
||||||
|
}
|
||||||
|
fileRepository.deleteById(idBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOwner(UUID fileId, UUID userId) {
|
||||||
|
byte[] fileBytes = UuidUtil.uuidToBin(fileId);
|
||||||
|
return fileRepository.findById(fileBytes)
|
||||||
|
.map(f -> f.getUploadedBy().equals(userId))
|
||||||
|
.orElse(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
package net.miarma.backend.core.service;
|
|
||||||
|
|
||||||
import io.jsonwebtoken.*;
|
|
||||||
import io.jsonwebtoken.security.Keys;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.security.Key;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class JwtService {
|
|
||||||
|
|
||||||
private final String secret = "miarma-esto-es-un-secreto-super-largo-para-jwt-1234567890";
|
|
||||||
private final Key key = Keys.hmacShaKeyFor(secret.getBytes());
|
|
||||||
|
|
||||||
private final long expiration = 3600_000;
|
|
||||||
|
|
||||||
public String generateToken(UUID userId, short serviceId) {
|
|
||||||
Date now = new Date();
|
|
||||||
Date exp = new Date(now.getTime() + expiration);
|
|
||||||
|
|
||||||
return Jwts.builder()
|
|
||||||
.setSubject(userId.toString())
|
|
||||||
.claim("service", serviceId)
|
|
||||||
.setIssuedAt(now)
|
|
||||||
.setExpiration(exp)
|
|
||||||
.signWith(key, SignatureAlgorithm.HS256)
|
|
||||||
.compact();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validateToken(String token) {
|
|
||||||
try {
|
|
||||||
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
|
|
||||||
return true;
|
|
||||||
} catch (JwtException | IllegalArgumentException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UUID getUserId(String token) {
|
|
||||||
Claims claims = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
|
|
||||||
return UUID.fromString(claims.getSubject());
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getServiceId(String token) {
|
|
||||||
Claims claims = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
|
|
||||||
return ((Number) claims.get("service")).shortValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getExpiration(String token) {
|
|
||||||
Claims claims = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
|
|
||||||
return claims.getExpiration();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,12 +1,21 @@
|
|||||||
package net.miarma.backend.core.service;
|
package net.miarma.backend.core.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import net.miarma.backend.core.mapper.UserMapper;
|
||||||
|
import net.miarma.backend.core.security.CorePrincipal;
|
||||||
|
import net.miarma.backlib.dto.ChangeAvatarRequest;
|
||||||
|
import net.miarma.backlib.exception.NotFoundException;
|
||||||
|
import net.miarma.backlib.exception.ValidationException;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
import net.miarma.backend.core.model.User;
|
import net.miarma.backend.core.model.User;
|
||||||
import net.miarma.backend.core.repository.UserRepository;
|
import net.miarma.backend.core.repository.UserRepository;
|
||||||
|
import net.miarma.backlib.dto.UserDto;
|
||||||
|
import net.miarma.backlib.util.UuidUtil;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -17,25 +26,88 @@ public class UserService {
|
|||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<User> getAll() {
|
||||||
|
return userRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
public User getById(UUID userId) {
|
public User getById(UUID userId) {
|
||||||
return userRepository.findById(userId)
|
byte[] idBytes = UuidUtil.uuidToBin(userId);
|
||||||
.orElseThrow(() -> new RuntimeException("User not found"));
|
return userRepository.findById(idBytes)
|
||||||
|
.orElseThrow(() -> new NotFoundException("Usuario no encontrado"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public User create(User user) {
|
public User create(User user) {
|
||||||
// TODO: basic validation
|
if(user.getDisplayName() == null || user.getDisplayName().isBlank()) {
|
||||||
return userRepository.save(user);
|
throw new ValidationException("displayName", "El nombre a mostrar es necesario");
|
||||||
|
}
|
||||||
|
return userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public User update(UUID userId, User changes) {
|
||||||
|
User user = userRepository.findById(UuidUtil.uuidToBin(userId))
|
||||||
|
.orElseThrow(() -> new NotFoundException("Usuario no encontrado"));
|
||||||
|
|
||||||
|
if (changes.getDisplayName() != null) {
|
||||||
|
String dn = changes.getDisplayName().trim();
|
||||||
|
if (dn.isEmpty()) throw new ValidationException("displayName", "No puede estar vacío");
|
||||||
|
if (dn.length() > 50) throw new ValidationException("displayName", "Máx 50 caracteres");
|
||||||
|
user.setDisplayName(dn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changes.getAvatar() != null)
|
||||||
|
user.setAvatar(changes.getAvatar());
|
||||||
|
|
||||||
|
if (changes.getGlobalRole() != null)
|
||||||
|
user.setGlobalRole(changes.getGlobalRole());
|
||||||
|
|
||||||
|
if (changes.getGlobalStatus() != null)
|
||||||
|
user.setGlobalStatus(changes.getGlobalStatus());
|
||||||
|
|
||||||
|
return userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(UUID userId) {
|
||||||
|
byte[] idBytes = UuidUtil.uuidToBin(userId);
|
||||||
|
if(!userRepository.existsById(idBytes))
|
||||||
|
throw new NotFoundException("Usuario no encontrado");
|
||||||
|
userRepository.deleteById(idBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public User update(User user) {
|
public UserDto updateAvatar(UUID userId, ChangeAvatarRequest req) {
|
||||||
if(!userRepository.existsById(user.getUserId()))
|
User user = userRepository.findById(UuidUtil.uuidToBin(userId))
|
||||||
throw new RuntimeException("User not found");
|
.orElseThrow(() -> new NotFoundException("Usuario no encontrado"));
|
||||||
return userRepository.save(user);
|
user.setAvatar(req.avatar());
|
||||||
}
|
userRepository.save(user);
|
||||||
|
return UserMapper.toDto(user);
|
||||||
|
}
|
||||||
|
|
||||||
public void delete(UUID userId) {
|
public Byte getStatus(UUID userId) {
|
||||||
if(!userRepository.existsById(userId))
|
User user = userRepository.findById(UuidUtil.uuidToBin(userId))
|
||||||
throw new RuntimeException("User not found");
|
.orElseThrow(() -> new NotFoundException("Usuario no encontrado"));;
|
||||||
userRepository.deleteById(userId);
|
return user.getGlobalStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateStatus(UUID userId, Byte status) {
|
||||||
|
User user = userRepository.findById(UuidUtil.uuidToBin(userId))
|
||||||
|
.orElseThrow(() -> new NotFoundException("Usuario no encontrado"));;
|
||||||
|
user.setGlobalStatus(status);
|
||||||
|
userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Byte getRole(UUID userId) {
|
||||||
|
User user = userRepository.findById(UuidUtil.uuidToBin(userId))
|
||||||
|
.orElseThrow(() -> new NotFoundException("Usuario no encontrado"));;
|
||||||
|
return user.getGlobalRole();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateRole(UUID userId, Byte role) {
|
||||||
|
User user = userRepository.findById(UuidUtil.uuidToBin(userId))
|
||||||
|
.orElseThrow(() -> new NotFoundException("Usuario no encontrado"));;
|
||||||
|
user.setGlobalRole(role);
|
||||||
|
userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exists(UUID userId) {
|
||||||
|
return userRepository.existsById(UuidUtil.uuidToBin(userId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
core/src/main/resources/application-dev.yml
Normal file
23
core/src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
server:
|
||||||
|
port: 8080
|
||||||
|
servlet:
|
||||||
|
context-path: /v2/core
|
||||||
|
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
url: jdbc:mariadb://localhost:3306/miarma_v2
|
||||||
|
username: admin
|
||||||
|
password: ${DB_PASS}
|
||||||
|
driver-class-name: org.mariadb.jdbc.Driver
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
org.hibernate.SQL: DEBUG
|
||||||
|
org.hibernate.orm.jdbc.bind: TRACE
|
||||||
|
org.springframework.security: DEBUG
|
||||||
|
|
||||||
|
filesDir: "/home/jomaa/.config/miarma-backend/files"
|
||||||
|
|
||||||
|
jwt:
|
||||||
|
private-key-path: /home/jomaa/.config/miarma-backend/private.pem
|
||||||
|
public-key-path: /home/jomaa/.config/miarma-backend/public.pem
|
||||||
22
core/src/main/resources/application-prod.yml
Normal file
22
core/src/main/resources/application-prod.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
server:
|
||||||
|
port: 8080
|
||||||
|
servlet:
|
||||||
|
context-path: /v2/core
|
||||||
|
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
url: jdbc:mariadb://mariadb:3306/miarma_v2
|
||||||
|
username: ${DB_USER}
|
||||||
|
password: ${DB_PASS}
|
||||||
|
driver-class-name: org.mariadb.jdbc.Driver
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
org.springframework.security: INFO
|
||||||
|
org.hibernate.SQL: WARN
|
||||||
|
|
||||||
|
filesDir: "/files"
|
||||||
|
|
||||||
|
jwt:
|
||||||
|
private-key-path: ${JWT_PRIVATE_KEY}
|
||||||
|
public-key-path: ${JWT_PUBLIC_KEY}
|
||||||
@@ -1,12 +1,25 @@
|
|||||||
spring:
|
spring:
|
||||||
datasource:
|
application:
|
||||||
url: jdbc:mariadb://localhost:3306/miarma_v2
|
name: core-service
|
||||||
username: USER
|
|
||||||
password: PASS
|
|
||||||
jpa:
|
jpa:
|
||||||
|
open-in-view: false
|
||||||
hibernate:
|
hibernate:
|
||||||
ddl-auto: update
|
ddl-auto: validate
|
||||||
show-sql: true
|
|
||||||
properties:
|
properties:
|
||||||
hibernate:
|
hibernate:
|
||||||
format_sql: true
|
jdbc:
|
||||||
|
time_zone: UTC
|
||||||
|
|
||||||
|
jackson:
|
||||||
|
default-property-inclusion: non_null
|
||||||
|
time-zone: Europe/Madrid
|
||||||
|
|
||||||
|
jwt:
|
||||||
|
expiration-ms: 3600000
|
||||||
|
|
||||||
|
management:
|
||||||
|
endpoints:
|
||||||
|
web:
|
||||||
|
exposure:
|
||||||
|
include: health,info
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<classpath>
|
|
||||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
|
||||||
</classpath>
|
|
||||||
1
huertos/.gitignore
vendored
1
huertos/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
/target/
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>huertos</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
eclipse.preferences.version=1
|
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
|
||||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
|
||||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
|
||||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
|
||||||
org.eclipse.jdt.core.compiler.release=disabled
|
|
||||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
activeProfiles=
|
|
||||||
eclipse.preferences.version=1
|
|
||||||
resolveWorkspaceProjects=true
|
|
||||||
version=1
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>net.miarma</groupId>
|
|
||||||
<artifactId>backend</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
</parent>
|
|
||||||
<artifactId>huertos</artifactId>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<!-- Spring Boot -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mariadb.jdbc</groupId>
|
|
||||||
<artifactId>mariadb-java-client</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- JWT -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-api</artifactId>
|
|
||||||
<version>0.11.5</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-impl</artifactId>
|
|
||||||
<version>0.11.5</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-jackson</artifactId>
|
|
||||||
<version>0.11.5</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</project>
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<classpath>
|
|
||||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
|
||||||
</classpath>
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>minecraft</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
eclipse.preferences.version=1
|
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
|
||||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
|
||||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
|
||||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
|
||||||
org.eclipse.jdt.core.compiler.release=disabled
|
|
||||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user