#29 refactor: replace admin code with role-based auth using Pinia

This commit is contained in:
mono
2026-03-14 22:55:24 -05:00
parent 2c9ea4b871
commit 786d0551bb
12 changed files with 105 additions and 129 deletions

View File

@@ -1,51 +0,0 @@
<template>
<v-dialog v-model="dialog" persistent>
<v-card>
<v-card-title>
Ingrese el código
</v-card-title>
<v-card-text>
<v-form id="code-form" @submit.prevent="verifyCode">
<v-text-field v-model="code" label="Código" type="password" autocomplete="off" />
</v-form>
</v-card-text>
<v-card-actions>
<v-btn type="submit" form="code-form" color="green">Aceptar</v-btn>
<v-btn :to="{ path: '/' }" color="red">Cancelar</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
import { inject } from 'vue';
export default {
data() {
return {
api: inject('api'),
dialog: true,
code: '',
};
},
methods: {
verifyCode() {
this.api.isValidAdminCode(this.code)
.then(data => {
if (data['validCode']) {
this.$emit('code-verified', true);
this.dialog = false;
} else {
alert('Código incorrecto');
this.$emit('code-verified', false);
}
})
.catch(error => {
alert('Error al validar el código');
this.$emit('code-verified', false);
console.error(error);
});
}
},
}
</script>

View File

@@ -79,9 +79,14 @@
<script>
import trytonIcon from '../assets/icons/tryton-icon.svg';
import AuthService from '@/services/auth';
import { useAuthStore } from '@/stores/auth';
import { inject } from 'vue';
export default {
name: 'NavBar',
setup() {
const authStore = useAuthStore();
return { authStore };
},
data: () => ({
drawer: false,
group: null,
@@ -132,6 +137,7 @@
async fetchUser() {
try {
this.user = await this.api.getCurrentUser();
this.authStore.setUser(this.user);
} catch (error) {
console.error('Error fetching user:', error);
}
@@ -150,6 +156,7 @@
AuthService.logout();
this.isAuthenticated = false;
this.user = null;
this.authStore.clearUser();
this.$router.push('/');
},
}

View File

@@ -1,20 +1,19 @@
<template>
<div>
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
</div>
<AdminPurchase v-if="showComponent"/>
<AdminPurchase v-if="authStore.isAdmin"/>
</template>
<script >
import CodeDialog from '../components/CodeDialog.vue'
import { useAuthStore } from '@/stores/auth';
export default {
data() {
return {
showComponent: false,
setup() {
const authStore = useAuthStore();
return { authStore };
},
mounted() {
if (!this.authStore.isAdmin) {
this.$router.push('/');
}
},
components: { CodeDialog },
methods: {},
}
</script>

View File

@@ -1,20 +1,19 @@
<template>
<div>
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
</div>
<ReconciliationJar v-if="showComponent" />
<ReconciliationJar v-if="authStore.isAdmin" />
</template>
<script >
import CodeDialog from '../components/CodeDialog.vue'
import { useAuthStore } from '@/stores/auth';
export default {
data() {
return {
showComponent: false,
setup() {
const authStore = useAuthStore();
return { authStore };
},
mounted() {
if (!this.authStore.isAdmin) {
this.$router.push('/');
}
},
components: { CodeDialog },
methods: {},
}
</script>

View File

@@ -1,20 +1,19 @@
<template>
<div>
<CodeDialog @code-verified="(verified) => showComponent = verified" />
</div>
<ReconciliationJarIndex v-if="showComponent" />
<ReconciliationJarIndex v-if="authStore.isAdmin" />
</template>
<script>
import CodeDialog from '../components/CodeDialog.vue'
import { useAuthStore } from '@/stores/auth';
export default {
data() {
return {
showComponent: false,
setup() {
const authStore = useAuthStore();
return { authStore };
},
mounted() {
if (!this.authStore.isAdmin) {
this.$router.push('/');
}
},
components: { CodeDialog },
methods: {},
}
</script>

View File

@@ -1,8 +1,5 @@
<template>
<div>
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
</div>
<v-container class="fill-height d-flex align-center justify-center">
<v-container v-if="authStore.isAdmin" class="fill-height d-flex align-center justify-center">
<v-card class="pa-6" max-width="600" elevation="4">
<v-card-title class="text-h5 font-weight-bold text-center">
🔄 Sincronización de Clientes
@@ -44,11 +41,15 @@
</template>
<script>
import CodeDialog from '../components/CodeDialog.vue'
import { useAuthStore } from '@/stores/auth';
import { inject } from 'vue';
export default {
name: 'CustomersFromTryton',
setup() {
const authStore = useAuthStore();
return { authStore };
},
data() {
return {
api: inject('api'),
@@ -59,21 +60,24 @@
updated_customers: [],
}
},
mounted() {
if (!this.authStore.isAdmin) {
this.$router.push('/');
}
},
methods: {
startSync() {
this.api.getCustomersFromTryton()
.then(response => {
// Manejar la respuesta exitosa
this.checked_tryton_parties = response.checked_tryton_parties.map(id => ({ id }));
this.created_customers = response.created_customers.map(id => ({ id }));
this.failed_parties = response.failed_parties.map(id => ({ id }));
this.untouched_customers = response.untouched_customers.map(id => ({ id }));
})
.catch(error => {
// Manejar el error
console.error("Error al sincronizar clientes:", error);
});
}
}
}
</script>
</script>

View File

@@ -1,8 +1,5 @@
<template>
<div>
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
</div>
<v-container class="fill-height d-flex align-center justify-center">
<v-container v-if="authStore.isAdmin" class="fill-height d-flex align-center justify-center">
<v-card class="pa-6" max-width="600" elevation="4">
<v-card-title class="text-h5 font-weight-bold text-center">
🔄 Sincronización de Productos
@@ -39,16 +36,24 @@
</template>
<script>
import CodeDialog from '../components/CodeDialog.vue'
import { useAuthStore } from '@/stores/auth';
import { inject } from 'vue';
export default {
name: 'ProductsFromTryton',
setup() {
const authStore = useAuthStore();
return { authStore };
},
data() {
return {
api: inject('api'),
productos_tryton: [{}],
showComponent: false,
}
},
mounted() {
if (!this.authStore.isAdmin) {
this.$router.push('/');
}
},
methods: {
@@ -57,4 +62,4 @@
}
}
}
</script>
</script>

View File

@@ -1,8 +1,5 @@
<template>
<div>
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
</div>
<v-container class="fill-height d-flex align-center justify-center">
<v-container v-if="authStore.isAdmin" class="fill-height d-flex align-center justify-center">
<v-card class="pa-6" max-width="600" elevation="4">
<v-card-title class="text-h5 font-weight-bold text-center">
🔄 Sincronización de Ventas
@@ -35,16 +32,24 @@
</v-container>
</template>
<script>
import CodeDialog from '../components/CodeDialog.vue';
import { useAuthStore } from '@/stores/auth';
import { inject } from 'vue';
export default {
name: 'SalesToTryton',
setup() {
const authStore = useAuthStore();
return { authStore };
},
data() {
return {
api: inject('api'),
ventas_tryton: [],
showComponent: false,
}
},
mounted() {
if (!this.authStore.isAdmin) {
this.$router.push('/');
}
},
methods: {

View File

@@ -1,19 +1,18 @@
<template>
<div>
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
</div>
<ExportPurchasesForTryton v-if="showComponent" />
<ExportPurchasesForTryton v-if="authStore.isAdmin" />
</template>
<script>
import CodeDialog from '../components/CodeDialog.vue'
import { useAuthStore } from '@/stores/auth';
export default {
data() {
return {
showComponent: false,
setup() {
const authStore = useAuthStore();
return { authStore };
},
mounted() {
if (!this.authStore.isAdmin) {
this.$router.push('/');
}
},
components: { CodeDialog },
methods: {},
}
</script>

View File

@@ -31,10 +31,6 @@ class Api {
return this.apiImplementation.getReconciliation(reconciliationId);
}
isValidAdminCode(code) {
return this.apiImplementation.isValidAdminCode(code);
}
createPurchase(purchase) {
return this.apiImplementation.createPurchase(purchase);
}

View File

@@ -49,11 +49,6 @@ class DjangoApi {
return this.getRequest(url);
}
isValidAdminCode(code) {
const url = this.base + `/don_confiao/api/admin_code/validate/${code}`
return this.getRequest(url)
}
createPurchase(purchase) {
const url = this.base + '/don_confiao/api/sales/';
return this.postRequest(url, purchase);

19
src/stores/auth.js Normal file
View File

@@ -0,0 +1,19 @@
import { defineStore } from 'pinia'
export const useAuthStore = defineStore('auth', {
state: () => ({
user: null
}),
getters: {
isAdmin: (state) => state.user?.role === 'administrator',
isAuthenticated: (state) => !!state.user
},
actions: {
setUser(user) {
this.user = user
},
clearUser() {
this.user = null
}
}
})