Add: all of Huertos but controllers (jwt verification, MSR model, etc). Add: RS256 to global JWT handling

This commit is contained in:
Jose
2026-01-20 03:08:53 +01:00
parent eaeb0c4f4f
commit 21281b10cc
100 changed files with 3036 additions and 387 deletions

View File

@@ -1,2 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=false

View File

@@ -1,9 +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.processAnnotations=disabled
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

View File

@@ -1,4 +0,0 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@@ -9,11 +9,74 @@
</parent>
<artifactId>backlib</artifactId>
<properties>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
</properties>
<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>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.42</version>
<scope>compile</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>
<dependency>
<groupId>net.miarma</groupId>
<artifactId>backlib</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,23 @@
package net.miarma.backlib.config;
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);
}
}

View File

@@ -0,0 +1,3 @@
package net.miarma.backlib.dto;
public record ChangeAvatarRequest(String avatar) {}

View File

@@ -4,42 +4,7 @@ import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
public class ChangePasswordRequest {
@NotBlank
private String oldPassword;
@NotBlank
private String newPassword;
@NotNull
@Min(0)
private Byte serviceId;
public String getOldPassword() {
return oldPassword;
}
public void setOldPassword(String oldPassword) {
this.oldPassword = oldPassword;
}
public String getNewPassword() {
return newPassword;
}
public void setNewPassword(String newPassword) {
this.newPassword = newPassword;
}
public Byte getServiceId() {
return serviceId;
}
public void setServiceId(Byte serviceId) {
this.serviceId = serviceId;
}
}
public record ChangePasswordRequest(@NotBlank String oldPassword,
@NotBlank String newPassword,
@NotBlank Byte serviceId) {}

View File

@@ -0,0 +1,4 @@
package net.miarma.backlib.dto;
public record ChangeRoleRequest(Byte role) {
}

View File

@@ -0,0 +1,3 @@
package net.miarma.backlib.dto;
public record ChangeStatusRequest(Byte status) {}

View File

@@ -2,36 +2,6 @@ package net.miarma.backlib.dto;
import jakarta.validation.constraints.NotBlank;
public class LoginRequest {
@NotBlank
private String username;
@NotBlank
private String password;
private Byte 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 Byte getServiceId() {
return serviceId;
}
public void setServiceId(Byte serviceId) {
this.serviceId = serviceId;
}
}
public record LoginRequest(@NotBlank String username,
@NotBlank String password,
Byte serviceId) {}

View File

@@ -1,37 +1,5 @@
package net.miarma.backlib.dto;
public class LoginResponse {
private String token;
private UserDto user;
private CredentialDto account;
public LoginResponse(String token, UserDto user, CredentialDto account) {
this.token = token;
this.user = user;
this.account = account;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public UserDto getUser() {
return user;
}
public void setUser(UserDto user) {
this.user = user;
}
public CredentialDto getAccount() {
return account;
}
public void setAccount(CredentialDto account) {
this.account = account;
}
}
public record LoginResponse(String token,
UserDto user,
CredentialDto account) {}

View File

@@ -1,41 +1,9 @@
package net.miarma.backlib.dto;
public class RegisterRequest {
private String username;
private String email;
private String password;
private String displayName;
private Byte 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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public Byte getServiceId() {
return serviceId;
}
public void setServiceId(Byte serviceId) {
this.serviceId = serviceId;
}
}
import jakarta.validation.constraints.NotBlank;
public record RegisterRequest(@NotBlank String username,
String email,
@NotBlank String password,
@NotBlank String displayName,
Byte serviceId) {}

View File

@@ -0,0 +1,4 @@
package net.miarma.backlib.dto;
public record UserExistsResponse(boolean exists) {
}

View File

@@ -0,0 +1,105 @@
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.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 {
System.out.println("user.name = " + System.getProperty("user.name"));
System.out.println("user.home = " + System.getProperty("user.home"));
System.out.println("privateKeyPath = " + privateKeyPath);
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();
}
}

View File

@@ -1,4 +0,0 @@
Manifest-Version: 1.0
Build-Jdk-Spec: 21
Created-By: Maven Integration for Eclipse

View File

@@ -1,7 +0,0 @@
#Generated by Maven Integration for Eclipse
#Sun Jan 18 04:49:28 CET 2026
artifactId=backlib
groupId=net.miarma
m2e.projectLocation=/home/jomaa/git/miarma-backend/backlib
m2e.projectName=backlib
version=1.0.0

View File

@@ -1,19 +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>backlib</artifactId>
<dependencies>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
</project>