Add: backlib for shared code between microservices. Started huertos microservice.

This commit is contained in:
Jose
2026-01-18 05:28:32 +01:00
parent ba5fc38b4b
commit 5f38bdc76f
50 changed files with 1191 additions and 216 deletions

View File

@@ -15,6 +15,11 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>

View File

@@ -0,0 +1,2 @@
boot.validation.initialized=true
eclipse.preferences.version=1

View File

@@ -63,6 +63,12 @@
<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

@@ -12,14 +12,14 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.validation.Valid;
import net.miarma.backend.core.dto.ChangePasswordRequest;
import net.miarma.backend.core.dto.LoginRequest;
import net.miarma.backend.core.dto.LoginResponse;
import net.miarma.backend.core.dto.RegisterRequest;
import net.miarma.backend.core.model.Credential;
import net.miarma.backend.core.service.AuthService;
import net.miarma.backend.core.service.CredentialService;
import net.miarma.backend.core.service.JwtService;
import net.miarma.backlib.dto.ChangePasswordRequest;
import net.miarma.backlib.dto.LoginRequest;
import net.miarma.backlib.dto.LoginResponse;
import net.miarma.backlib.dto.RegisterRequest;
@RestController
@RequestMapping("/auth")

View File

@@ -13,9 +13,9 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import net.miarma.backend.core.dto.CredentialDto;
import net.miarma.backend.core.model.Credential;
import net.miarma.backend.core.service.CredentialService;
import net.miarma.backlib.dto.CredentialDto;
@RestController
@RequestMapping("/credentials")

View File

@@ -14,10 +14,11 @@ import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import net.miarma.backend.core.dto.UserDto;
import net.miarma.backend.core.mapper.UserMapper;
import net.miarma.backend.core.model.User;
import net.miarma.backend.core.service.JwtService;
import net.miarma.backend.core.service.UserService;
import net.miarma.backlib.dto.UserDto;
@RestController
@RequestMapping("/users")
@@ -36,7 +37,7 @@ public class UserController {
return ResponseEntity.ok(
userService.getAll()
.stream()
.map(UserDto::fromEntity)
.map(UserMapper::toDto)
.toList()
);
}
@@ -45,13 +46,13 @@ public class UserController {
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<UserDto> getById(@PathVariable("user_id") UUID userId) {
User user = userService.getById(userId);
return ResponseEntity.ok(UserDto.fromEntity(user));
return ResponseEntity.ok(UserMapper.toDto(user));
}
@PutMapping("/{user_id}")
@PreAuthorize("hasRole('ADMIN') or #userId == principal.userId")
public ResponseEntity<UserDto> update(@PathVariable("user_id") UUID userId, @RequestBody UserDto dto) {
return ResponseEntity.ok(UserDto.fromEntity(userService.update(userId, dto)));
return ResponseEntity.ok(UserMapper.toDto(userService.update(userId, dto)));
}
@GetMapping("/{user_id}/avatar")
@@ -75,6 +76,6 @@ public class UserController {
}
User user = userService.getById(userId);
return ResponseEntity.ok(UserDto.fromEntity(user));
return ResponseEntity.ok(UserMapper.toDto(user));
}
}

View File

@@ -1,45 +0,0 @@
package net.miarma.backend.core.dto;
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;
}
}

View File

@@ -1,89 +0,0 @@
package net.miarma.backend.core.dto;
import java.time.Instant;
import java.util.UUID;
import net.miarma.backend.core.model.Credential;
public class CredentialDto {
private UUID credentialId;
private Byte serviceId;
private String username;
private String email;
private Byte status;
private Instant createdAt;
private Instant updatedAt;
public CredentialDto() {}
public CredentialDto(Credential credential) {
this.credentialId = credential.getCredentialId();
this.serviceId = credential.getServiceId();
this.username = credential.getUsername();
this.email = credential.getEmail();
this.status = credential.getStatus();
this.createdAt = credential.getCreatedAt();
this.updatedAt = credential.getUpdatedAt();
}
public static CredentialDto fromEntity(Credential credential) {
if (credential == null) return null;
return new CredentialDto(credential);
}
public UUID getCredentialId() {
return credentialId;
}
public void setCredentialId(UUID credentialId) {
this.credentialId = credentialId;
}
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;
}
}

View File

@@ -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 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;
}
}

View File

@@ -1,37 +0,0 @@
package net.miarma.backend.core.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;
}
}

View File

@@ -1,41 +0,0 @@
package net.miarma.backend.core.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;
}
}

View File

@@ -1,99 +0,0 @@
package net.miarma.backend.core.dto;
import java.time.Instant;
import java.util.UUID;
import net.miarma.backend.core.model.User;
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;
}
public static UserDto fromEntity(User user) {
if (user == null) return null;
return new UserDto(
user.getUserId(),
user.getDisplayName(),
user.getAvatar(),
user.getGlobalStatus(),
user.getGlobalRole(),
user.getCreatedAt(),
user.getUpdatedAt()
);
}
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;
}
}

View File

@@ -0,0 +1,22 @@
package net.miarma.backend.core.mapper;
import net.miarma.backend.core.model.Credential;
import net.miarma.backlib.dto.CredentialDto;
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()
);
}
}

View File

@@ -0,0 +1,20 @@
package net.miarma.backend.core.mapper;
import net.miarma.backend.core.model.User;
import net.miarma.backlib.dto.UserDto;
public class UserMapper {
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()
);
}
}

View File

@@ -3,8 +3,10 @@ package net.miarma.backend.core.model;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.util.UUID;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
@@ -17,6 +19,7 @@ import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import jakarta.persistence.UniqueConstraint;
import net.miarma.backlib.util.UuidUtil;
@Entity
@Table(name = "credentials",
@@ -59,37 +62,25 @@ public class Credential {
private User user;
@PrePersist
@PreUpdate
private void prePersist() {
if (credentialId != null) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(credentialId.getMostSignificantBits());
bb.putLong(credentialId.getLeastSignificantBits());
credentialIdBin = bb.array();
}
if (userId != null) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(userId.getMostSignificantBits());
bb.putLong(userId.getLeastSignificantBits());
userIdBin = bb.array();
}
}
@PreUpdate
private void prePersist() {
if (credentialId != null) {
credentialIdBin = UuidUtil.uuidToBin(credentialId);
}
if (userId != null) {
userIdBin = UuidUtil.uuidToBin(userId);
}
}
@PostLoad
private void postLoad() {
if (credentialIdBin != null) {
ByteBuffer bb = ByteBuffer.wrap(credentialIdBin);
long high = bb.getLong();
long low = bb.getLong();
credentialId = new UUID(high, low);
}
if (userIdBin != null) {
ByteBuffer bb = ByteBuffer.wrap(userIdBin);
long high = bb.getLong();
long low = bb.getLong();
userId = new UUID(high, low);
}
}
@PostLoad
private void postLoad() {
if (credentialIdBin != null) {
credentialId = UuidUtil.binToUUID(credentialIdBin);
}
if (userIdBin != null) {
userId = UuidUtil.binToUUID(userIdBin);
}
}
public UUID getCredentialId() {
if (credentialId == null && credentialIdBin != null) {

View File

@@ -6,9 +6,12 @@ import java.util.UUID;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.PostLoad;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import net.miarma.backlib.util.UuidUtil;
@Entity
@Table(name = "files")
@@ -43,12 +46,25 @@ public class File {
private Short context;
@PrePersist
public void prePersist() {
if (fileId == null) {
fileId = UUID.randomUUID();
@PreUpdate
private void prePersist() {
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);
}
}

View File

@@ -1,6 +1,5 @@
package net.miarma.backend.core.model;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.util.UUID;
@@ -15,6 +14,7 @@ import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import net.miarma.backlib.util.UuidUtil;
@Entity
@Table(name = "users")
@@ -48,20 +48,14 @@ public class User {
@PreUpdate
private void prePersist() {
if (userId != null) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(userId.getMostSignificantBits());
bb.putLong(userId.getLeastSignificantBits());
userIdBin = bb.array();
userIdBin = UuidUtil.uuidToBin(userId);
}
}
@PostLoad
private void postLoad() {
if (userIdBin != null) {
ByteBuffer bb = ByteBuffer.wrap(userIdBin);
long high = bb.getLong();
long low = bb.getLong();
userId = new UUID(high, low);
userId = UuidUtil.binToUUID(userIdBin);
}
}

View File

@@ -5,13 +5,15 @@ import java.util.UUID;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import net.miarma.backend.core.dto.CredentialDto;
import net.miarma.backend.core.dto.LoginRequest;
import net.miarma.backend.core.dto.LoginResponse;
import net.miarma.backend.core.dto.RegisterRequest;
import net.miarma.backend.core.dto.UserDto;
import net.miarma.backend.core.mapper.CredentialMapper;
import net.miarma.backend.core.mapper.UserMapper;
import net.miarma.backend.core.model.Credential;
import net.miarma.backend.core.model.User;
import net.miarma.backlib.dto.CredentialDto;
import net.miarma.backlib.dto.LoginRequest;
import net.miarma.backlib.dto.LoginResponse;
import net.miarma.backlib.dto.RegisterRequest;
import net.miarma.backlib.dto.UserDto;
@Service
public class AuthService {
@@ -38,9 +40,9 @@ public class AuthService {
String token = jwtService.generateToken(cred.getUserId(), request.getServiceId());
UserDto userDto = UserDto.fromEntity(cred.getUser());
UserDto userDto = UserMapper.toDto(cred.getUser());
CredentialDto credentialDto = CredentialDto.fromEntity(cred);
CredentialDto credentialDto = CredentialMapper.toDto(cred);
return new LoginResponse(token, userDto, credentialDto);
}
@@ -71,6 +73,6 @@ public class AuthService {
String token = jwtService.generateToken(user.getUserId(), request.getServiceId());
return new LoginResponse(token, UserDto.fromEntity(user), CredentialDto.fromEntity(cred));
return new LoginResponse(token, UserMapper.toDto(user), CredentialMapper.toDto(cred));
}
}

View File

@@ -7,12 +7,12 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import net.miarma.backend.core.dto.ChangePasswordRequest;
import net.miarma.backend.core.dto.CredentialDto;
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.util.UuidUtils;
import net.miarma.backlib.dto.ChangePasswordRequest;
import net.miarma.backlib.dto.CredentialDto;
import net.miarma.backlib.util.UuidUtil;
@Service
@Transactional
@@ -27,7 +27,7 @@ public class CredentialService {
}
public Credential getById(UUID credentialId) {
byte[] idBytes = UuidUtils.uuidToBin(credentialId);
byte[] idBytes = UuidUtil.uuidToBin(credentialId);
return credentialRepository.findById(idBytes)
.orElseThrow(() -> new RuntimeException("Credential not found"));
}
@@ -63,7 +63,7 @@ public class CredentialService {
}
public List<Credential> getByUserId(UUID userId) {
List<Credential> creds = credentialRepository.findByUserId(UuidUtils.uuidToBin(userId));
List<Credential> creds = credentialRepository.findByUserId(UuidUtil.uuidToBin(userId));
if (creds.isEmpty()) {
throw new RuntimeException("User has no credentials");
}
@@ -91,14 +91,14 @@ public class CredentialService {
}
public boolean isOwner(UUID credentialId, UUID userId) {
byte[] idBytes = UuidUtils.uuidToBin(credentialId);
byte[] idBytes = UuidUtil.uuidToBin(credentialId);
Credential c = credentialRepository.findById(idBytes)
.orElseThrow(() -> new RuntimeException("Credential not found"));
return c.getUserId().equals(userId);
}
public Credential update(UUID credentialId, CredentialDto dto) {
byte[] idBytes = UuidUtils.uuidToBin(credentialId);
byte[] idBytes = UuidUtil.uuidToBin(credentialId);
Credential cred = credentialRepository.findById(idBytes)
.orElseThrow(() -> new RuntimeException("Credential not found"));
@@ -122,7 +122,7 @@ public class CredentialService {
}
public Credential updatePassword(UUID credentialId, ChangePasswordRequest request) {
byte[] idBytes = UuidUtils.uuidToBin(credentialId);
byte[] idBytes = UuidUtil.uuidToBin(credentialId);
Credential cred = credentialRepository.findById(idBytes)
.orElseThrow(() -> new RuntimeException("Credential not found"));
@@ -136,7 +136,7 @@ public class CredentialService {
}
public void delete(UUID credentialId) {
byte[] idBytes = UuidUtils.uuidToBin(credentialId);
byte[] idBytes = UuidUtil.uuidToBin(credentialId);
if(!credentialRepository.existsById(idBytes))
throw new RuntimeException("Credential not found");
credentialRepository.deleteById(idBytes);

View File

@@ -14,7 +14,7 @@ import org.springframework.transaction.annotation.Transactional;
import net.miarma.backend.core.model.File;
import net.miarma.backend.core.repository.FileRepository;
import net.miarma.backend.core.util.UuidUtils;
import net.miarma.backlib.util.UuidUtil;
@Service
@Transactional
@@ -28,7 +28,7 @@ public class FileService {
}
public File getById(UUID fileId) {
byte[] idBytes = UuidUtils.uuidToBin(fileId);
byte[] idBytes = UuidUtil.uuidToBin(fileId);
return fileRepository.findById(idBytes)
.orElseThrow(() -> new RuntimeException("File not found"));
}
@@ -66,7 +66,7 @@ public class FileService {
}
public File update(File file) {
byte[] idBytes = UuidUtils.uuidToBin(file.getFileId());
byte[] idBytes = UuidUtil.uuidToBin(file.getFileId());
if (!fileRepository.existsById(idBytes)) {
throw new RuntimeException("File not found");
}
@@ -74,7 +74,7 @@ public class FileService {
}
public void delete(UUID fileId) {
byte[] idBytes = UuidUtils.uuidToBin(fileId);
byte[] idBytes = UuidUtil.uuidToBin(fileId);
if (!fileRepository.existsById(idBytes)) {
throw new RuntimeException("File not found");
}
@@ -82,7 +82,7 @@ public class FileService {
}
public boolean isOwner(UUID fileId, UUID userId) {
byte[] fileBytes = UuidUtils.uuidToBin(fileId);
byte[] fileBytes = UuidUtil.uuidToBin(fileId);
return fileRepository.findById(fileBytes)
.map(f -> f.getUploadedBy().equals(userId))
.orElse(false);

View File

@@ -6,10 +6,10 @@ import java.util.UUID;
import org.springframework.stereotype.Service;
import jakarta.transaction.Transactional;
import net.miarma.backend.core.dto.UserDto;
import net.miarma.backend.core.model.User;
import net.miarma.backend.core.repository.UserRepository;
import net.miarma.backend.core.util.UuidUtils;
import net.miarma.backlib.dto.UserDto;
import net.miarma.backlib.util.UuidUtil;
@Service
@Transactional
@@ -25,7 +25,7 @@ public class UserService {
}
public User getById(UUID userId) {
byte[] idBytes = UuidUtils.uuidToBin(userId);
byte[] idBytes = UuidUtil.uuidToBin(userId);
return userRepository.findById(idBytes)
.orElseThrow(() -> new RuntimeException("User not found"));
}
@@ -46,7 +46,7 @@ public class UserService {
}
public User update(UUID userId, UserDto dto) {
byte[] idBytes = UuidUtils.uuidToBin(userId);
byte[] idBytes = UuidUtil.uuidToBin(userId);
User user = userRepository.findById(idBytes)
.orElseThrow(() -> new RuntimeException("User not found"));
@@ -70,7 +70,7 @@ public class UserService {
}
public void delete(UUID userId) {
byte[] idBytes = UuidUtils.uuidToBin(userId);
byte[] idBytes = UuidUtil.uuidToBin(userId);
if(!userRepository.existsById(idBytes))
throw new RuntimeException("User not found");
userRepository.deleteById(idBytes);

View File

@@ -1,21 +0,0 @@
package net.miarma.backend.core.util;
import java.nio.ByteBuffer;
import java.util.UUID;
public class UuidUtils {
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);
}
}