Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http,

auth.requestMatchers(HttpMethod.POST, api + "/loyal-users").hasRole(ADMIN);
auth.requestMatchers(HttpMethod.PUT, api + "/loyal-users/**").hasRole(ADMIN);
auth.requestMatchers(HttpMethod.GET, api + "/loyal-users/me/orders").hasRole(LOYAL_USER);
auth.requestMatchers(HttpMethod.GET, api + "/loyal-users/me/orders").authenticated();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verificar la implementación de getMyOrders() para confirmar validación interna

# Buscar la implementación del método getMyOrders en el servicio
ast-grep --pattern $'public $_ getMyOrders() {
  $$$
}'

# Buscar referencias a LOYAL_USER o validaciones de rol en LoyalUserService
rg -n -C5 'getMyOrders|LOYAL_USER|loyal.*user' --type=java -g '**/LoyalUserService*.java'

# Buscar si hay validación del usuario actual como loyal user
rg -n -C3 'getCurrentUser|getAuthenticated|SecurityContext' --type=java -g '**/LoyalUserService*.java'

Repository: Delivera-Project/Delivera

Length of output: 5305


El endpoint relaja la autorización sin validación suficiente en el servicio.

El cambio de hasRole(LOYAL_USER) a authenticated() permite que cualquier usuario autenticado (ADMIN, ANALYST, OPERATOR, etc.) acceda al endpoint /loyal-users/me/orders.

Aunque loyalUserService.getMyOrders() busca internamente el usuario en la tabla loyal_user, no valida explícitamente que el usuario autenticado tenga el rol LOYAL_USER ni lanza una excepción cuando el usuario no es fidelizado. En su lugar, retorna una lista vacía (List.of()).

Esto viola la guía de codificación: "Seguridad: verifica que los endpoints estén correctamente protegidos según el rol". El endpoint debe:

  • Mantener hasRole(LOYAL_USER) en la configuración de seguridad, O
  • Lanzar una excepción en el servicio (ej. LoyalUserNotFoundException) cuando el usuario autenticado no sea un loyal user, O
  • Justificar formalmente por qué usuarios no fidelizados deben tener acceso al path /loyal-users/**
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/main/java/com/delivera/config/SecurityConfig.java` at line 75,
The requestMatchers configuration for the GET endpoint `/loyal-users/me/orders`
uses `authenticated()` instead of `hasRole(LOYAL_USER)`, allowing any
authenticated user regardless of role to attempt access. While the underlying
service may return an empty list for non-loyal users, this violates the security
principle of explicit role-based access control. Either restore the
`hasRole(LOYAL_USER)` requirement in the requestMatchers call to enforce
role-based authorization at the security layer, or modify the
loyalUserService.getMyOrders() method to explicitly throw an exception (such as
LoyalUserNotFoundException or AccessDeniedException) when the authenticated user
is not found in the loyal_user table, ensuring the authorization is properly
validated rather than silently failing with an empty list.

Source: Coding guidelines


auth.requestMatchers(HttpMethod.POST, api + "/workers/invite").hasRole(ADMIN);
auth.requestMatchers(HttpMethod.PATCH, api + "/workers/*/role").hasRole(ADMIN);
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,9 @@ orders:
details: Details
priority:
label: Priority
HIGH: HIGH
NORMAL: NORMAL
LOW: LOW
HIGH: High
NORMAL: Normal
LOW: Low
status:
PENDING: Pending
IN_TRANSIT: In transit
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,9 @@ orders:
details: Detalles
priority:
label: Prioridad
HIGH: ALTA
HIGH: Alta
NORMAL: Normal
LOW: BAJA
LOW: Baja
status:
PENDING: Pendiente
IN_TRANSIT: En tránsito
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/views/auth/OnboardingView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const step = ref(1) // 1 = crear unidad, 2 = invitar trabajador
// Step 1: unidad
const unitName = ref('')
const unitType = ref('WAREHOUSE')
const unitAddress = ref('')
const unitSaving = ref(false)
const unitError = ref('')

Expand All @@ -30,10 +31,11 @@ const roleOptions = WORKER_ROLES.map(r => ({ label: t('workers.roles.' + r), val

async function createUnit() {
if (!unitName.value.trim()) { unitError.value = t('validation.required', { field: t('fields.unitName') }); return }
if (!unitAddress.value.trim()) { unitError.value = t('validation.required', { field: t('fields.address') }); return }
unitSaving.value = true
unitError.value = ''
try {
const res = await api.post('/units', { name: unitName.value.trim(), type: unitType.value })
const res = await api.post('/units', { name: unitName.value.trim(), type: unitType.value, address: unitAddress.value.trim() })
if (res.ok) step.value = 2
else { const d = await res.json(); unitError.value = api.translateError(d, 'error.saveFailed') }
} catch { unitError.value = t('error.connection') }
Expand Down Expand Up @@ -79,6 +81,10 @@ async function inviteWorker() {
<label for="ob-unit-type">{{ t('fields.type') }}</label>
<PSelect input-id="ob-unit-type" v-model="unitType" :options="unitTypeOptions" option-label="label" option-value="value" fluid />
</div>
<div class="form-field">
<label for="ob-unit-address">{{ t('fields.address') }}</label>
<InputText id="ob-unit-address" v-model="unitAddress" :placeholder="t('fields.addressPlaceholder')" fluid />
</div>

<PMessage v-if="unitError" severity="error" :closable="false" class="form-message">{{ unitError }}</PMessage>

Expand Down
Loading