From f0f4361b7323041541fb10cee149e4f3927f50d4 Mon Sep 17 00:00:00 2001 From: Bennett Date: Wed, 2 Sep 2026 21:04:19 +0300 Subject: [PATCH 1/2] release: Remove guards for users in UI --- .../flextuma/core/dtos/ProfileUpdateDto.java | 11 ++++++++++ .../helpers/TenantAwareSpecification.java | 1 - .../auth/controllers/AuthController.java | 11 ++++++++++ .../modules/auth/services/UserService.java | 20 +++++++++++++++++++ .../services/ConnectorConfigService.java | 6 ++---- .../contact/services/ContactService.java | 4 +--- .../WhatsAppWebhookConfigService.java | 10 ++++++---- 7 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/flexcodelabs/flextuma/core/dtos/ProfileUpdateDto.java diff --git a/src/main/java/com/flexcodelabs/flextuma/core/dtos/ProfileUpdateDto.java b/src/main/java/com/flexcodelabs/flextuma/core/dtos/ProfileUpdateDto.java new file mode 100644 index 0000000..a436661 --- /dev/null +++ b/src/main/java/com/flexcodelabs/flextuma/core/dtos/ProfileUpdateDto.java @@ -0,0 +1,11 @@ +package com.flexcodelabs.flextuma.core.dtos; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; + +public record ProfileUpdateDto( + @NotBlank String name, + @NotBlank String username, + @Email String email, + @NotBlank String phoneNumber) { +} diff --git a/src/main/java/com/flexcodelabs/flextuma/core/helpers/TenantAwareSpecification.java b/src/main/java/com/flexcodelabs/flextuma/core/helpers/TenantAwareSpecification.java index 86177bd..c4ff8f7 100644 --- a/src/main/java/com/flexcodelabs/flextuma/core/helpers/TenantAwareSpecification.java +++ b/src/main/java/com/flexcodelabs/flextuma/core/helpers/TenantAwareSpecification.java @@ -54,7 +54,6 @@ public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuild } List predicates = new ArrayList<>(); - predicates.add(cb.equal(root.get(CREATED_BY), currentUser)); Organisation organisation = currentUser.getOrganisation(); diff --git a/src/main/java/com/flexcodelabs/flextuma/modules/auth/controllers/AuthController.java b/src/main/java/com/flexcodelabs/flextuma/modules/auth/controllers/AuthController.java index 7a354af..ba52101 100644 --- a/src/main/java/com/flexcodelabs/flextuma/modules/auth/controllers/AuthController.java +++ b/src/main/java/com/flexcodelabs/flextuma/modules/auth/controllers/AuthController.java @@ -11,12 +11,14 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.flexcodelabs.flextuma.core.dtos.LoginDto; import com.flexcodelabs.flextuma.core.dtos.RegisterDto; +import com.flexcodelabs.flextuma.core.dtos.ProfileUpdateDto; import com.flexcodelabs.flextuma.core.dtos.PasswordChangeDto; import com.flexcodelabs.flextuma.core.dto.ApiResponse; import com.flexcodelabs.flextuma.core.dtos.UserResponseDto; @@ -136,6 +138,15 @@ public ResponseEntity me() { .body(user); } + @PatchMapping("/me") + public ResponseEntity updateProfile(@Valid @RequestBody ProfileUpdateDto request) { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null || !auth.isAuthenticated() || auth instanceof AnonymousAuthenticationToken) { + return ResponseEntity.status(401).body(ErrorResponse.unauthorized("Unauthorized")); + } + return ResponseEntity.ok(userService.updateProfile(auth.getName(), request)); + } + @PostMapping("/verify") public ResponseEntity verify(@Valid @RequestBody VerificationRequestDto request, HttpServletRequest httpRequest) { diff --git a/src/main/java/com/flexcodelabs/flextuma/modules/auth/services/UserService.java b/src/main/java/com/flexcodelabs/flextuma/modules/auth/services/UserService.java index b2fbfe8..4112329 100644 --- a/src/main/java/com/flexcodelabs/flextuma/modules/auth/services/UserService.java +++ b/src/main/java/com/flexcodelabs/flextuma/modules/auth/services/UserService.java @@ -20,6 +20,7 @@ import com.flexcodelabs.flextuma.core.entities.auth.User; import com.flexcodelabs.flextuma.core.dtos.RegisterDto; +import com.flexcodelabs.flextuma.core.dtos.ProfileUpdateDto; import com.flexcodelabs.flextuma.core.repositories.UserRepository; import com.flexcodelabs.flextuma.core.services.BaseService; @@ -151,6 +152,25 @@ public User register(RegisterDto request) { return repository.save(user); } + @org.springframework.transaction.annotation.Transactional + public User updateProfile(String currentUsername, ProfileUpdateDto request) { + User user = findByUsername(currentUsername); + repository.findByUsername(request.username()) + .filter(existing -> !existing.getId().equals(user.getId())) + .ifPresent(existing -> { throw new ResponseStatusException(HttpStatus.CONFLICT, "Username already exists"); }); + repository.findByEmail(request.email()) + .filter(existing -> !existing.getId().equals(user.getId())) + .ifPresent(existing -> { throw new ResponseStatusException(HttpStatus.CONFLICT, "Email already exists"); }); + repository.findByPhoneNumber(request.phoneNumber()) + .filter(existing -> !existing.getId().equals(user.getId())) + .ifPresent(existing -> { throw new ResponseStatusException(HttpStatus.CONFLICT, "Phone number already exists"); }); + user.setName(request.name()); + user.setUsername(request.username()); + user.setEmail(request.email()); + user.setPhoneNumber(request.phoneNumber()); + return repository.save(user); + } + public User changePassword(User user, String newPassword) { User managedUser = repository.findById(user.getId()) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found")); diff --git a/src/main/java/com/flexcodelabs/flextuma/modules/connector/services/ConnectorConfigService.java b/src/main/java/com/flexcodelabs/flextuma/modules/connector/services/ConnectorConfigService.java index 0ce78f2..cd87a76 100644 --- a/src/main/java/com/flexcodelabs/flextuma/modules/connector/services/ConnectorConfigService.java +++ b/src/main/java/com/flexcodelabs/flextuma/modules/connector/services/ConnectorConfigService.java @@ -78,9 +78,7 @@ protected void validateDelete(ConnectorConfig entity) { @Override public ConnectorConfig update(UUID id, ConnectorConfig entity) { checkPermission(getUpdatePermission()); - ConnectorConfig existing = getRepository().findById(id) - .orElseThrow(() -> new org.springframework.web.server.ResponseStatusException( - org.springframework.http.HttpStatus.NOT_FOUND, getEntitySingular() + " not found")); + ConnectorConfig existing = findAccessibleById(id); if (entity.getTenantId() != null && entity.getTenantId().contains("****")) { entity.setTenantId(existing.getTenantId()); @@ -103,4 +101,4 @@ public ConnectorConfig update(UUID id, ConnectorConfig entity) { return super.update(id, entity); } -} \ No newline at end of file +} diff --git a/src/main/java/com/flexcodelabs/flextuma/modules/contact/services/ContactService.java b/src/main/java/com/flexcodelabs/flextuma/modules/contact/services/ContactService.java index d787355..03ea1fa 100644 --- a/src/main/java/com/flexcodelabs/flextuma/modules/contact/services/ContactService.java +++ b/src/main/java/com/flexcodelabs/flextuma/modules/contact/services/ContactService.java @@ -84,9 +84,7 @@ protected void validateDelete(Contact entity) { public java.util.Map delete(UUID id) { checkPermission(getDeletePermission()); - Contact entity = getRepository().findById(id) - .orElseThrow(() -> new org.springframework.web.server.ResponseStatusException( - org.springframework.http.HttpStatus.NOT_FOUND, getEntitySingular() + " not found")); + Contact entity = findAccessibleById(id); validateDelete(entity); diff --git a/src/main/java/com/flexcodelabs/flextuma/modules/whatsapp/services/WhatsAppWebhookConfigService.java b/src/main/java/com/flexcodelabs/flextuma/modules/whatsapp/services/WhatsAppWebhookConfigService.java index 189ef14..ea86503 100644 --- a/src/main/java/com/flexcodelabs/flextuma/modules/whatsapp/services/WhatsAppWebhookConfigService.java +++ b/src/main/java/com/flexcodelabs/flextuma/modules/whatsapp/services/WhatsAppWebhookConfigService.java @@ -18,10 +18,12 @@ public class WhatsAppWebhookConfigService extends BaseService getRepository() { return repository; } protected JpaSpecificationExecutor getRepositoryAsExecutor() { return repository; } - protected String getReadPermission() { return WhatsAppWebhookConfig.READ; } - protected String getAddPermission() { return WhatsAppWebhookConfig.ADD; } - protected String getUpdatePermission() { return WhatsAppWebhookConfig.UPDATE; } - protected String getDeletePermission() { return WhatsAppWebhookConfig.DELETE; } + // Each configuration is tenant-scoped by BaseService, so every signed-in + // user can manage only their own WhatsApp webhook configurations. + protected String getReadPermission() { return "ALL"; } + protected String getAddPermission() { return "ALL"; } + protected String getUpdatePermission() { return "ALL"; } + protected String getDeletePermission() { return "ALL"; } public String getEntityPlural() { return WhatsAppWebhookConfig.NAME_PLURAL; } protected String getEntitySingular() { return WhatsAppWebhookConfig.NAME_SINGULAR; } public String getPropertyName() { return WhatsAppWebhookConfig.PLURAL; } From 8bf83b6918530e4f1659002c421fdd72b17345cd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 2 Sep 2026 18:05:33 +0000 Subject: [PATCH 2/2] Release v0.0.49 [skip ci] --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 786e91f..8d05b28 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { } group = 'com.flexcodelabs' -version = '0.0.48' +version = '0.0.49' description = 'Flextuma App' java {