Add more components + base for history
This commit is contained in:
@@ -41,7 +41,10 @@
|
||||
|
||||
<nav class="navbar navbar-expand-lg bg-primary" data-bs-theme="dark">
|
||||
<div class="container-fluid">
|
||||
<a href="#" @click="lock_me" class="navbar-brand">{% trans "Lock" %}</a>
|
||||
<v-btn color="navbar-brand" text @click="lock_me">
|
||||
<v-icon small class="mr-2">mdi-lock</v-icon>
|
||||
{% trans "Lock" %}
|
||||
</v-btn>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
@@ -49,12 +52,6 @@
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarColor01">
|
||||
<ul class="navbar-nav me-auto">
|
||||
<li class="nav-item">
|
||||
<router-link class="nav-link active" to="{% url 'main:home' %}">
|
||||
{% trans "K356" %}
|
||||
<span class="visually-hidden"></span>
|
||||
</router-link>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<router-link class="nav-link" to="/ItemView">{% trans "Items" %}</router-link>
|
||||
</li>
|
||||
|
||||
@@ -32,36 +32,56 @@
|
||||
<v-card-text>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<template v-for="field in editable_fields">
|
||||
<template v-if="field.field_widget == 'v-select'">
|
||||
<template v-if="field.choices">
|
||||
<v-select
|
||||
v-model="editedItem[field.value]"
|
||||
:items="field.choices"
|
||||
:label="field.text"
|
||||
item-text="text"
|
||||
item-value="value"
|
||||
persistent-hint>
|
||||
</v-select>
|
||||
<v-form ref="form" v-model="valid">
|
||||
|
||||
<template v-for="field in editable_fields">
|
||||
|
||||
<template v-if="field.field_widget == 'v-select'">
|
||||
<template v-if="field.choices">
|
||||
<v-select
|
||||
v-model="editedItem[field.value]"
|
||||
:items="field.choices"
|
||||
:label="field.text"
|
||||
:rules="[rules.required]"
|
||||
item-text="text"
|
||||
item-value="value"
|
||||
persistent-hint>
|
||||
</v-select>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<v-select
|
||||
v-model="editedItem[field.value]"
|
||||
:items="items_relations[field.value]"
|
||||
:label="field.text"
|
||||
:rules="[rules.required]"
|
||||
item-text="name"
|
||||
item-value="id"
|
||||
return-object
|
||||
persistent-hint>
|
||||
<template slot="item" slot-scope="data">
|
||||
<template v-if="data.item.custom_identifier">
|
||||
[[ data.item.custom_identifier ]] - [[ data.item.name ]]
|
||||
</template>
|
||||
<template v-else>
|
||||
[[ data.item.name ]]
|
||||
</template>
|
||||
</template>
|
||||
</v-select>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template v-else-if="field?.dynamic_field_type">
|
||||
<DynField :item="editedItem" :field="field"></DynField>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<v-select
|
||||
v-model="editedItem[field.value]"
|
||||
:items="items_relations[field.value]"
|
||||
:label="field.text"
|
||||
item-text="name"
|
||||
item-value="id"
|
||||
persistent-hint>
|
||||
<template slot="item" slot-scope="data">
|
||||
[[ data.item.name ]] - [[ data.item.custom_identifier ]]
|
||||
</template>
|
||||
</v-select>
|
||||
<component :is="field.field_widget" v-model="editedItem[field.value]" :label="field.text"></component>
|
||||
</template>
|
||||
|
||||
</template>
|
||||
<template v-else>
|
||||
<component :is="field.field_widget" v-model="editedItem[field.value]" :label="field.text"></component>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
</v-form>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
|
||||
@@ -3,24 +3,51 @@
|
||||
template: "#{{ name }}",
|
||||
router_path: "/{{ name }}",
|
||||
delimiters: ["[[", "]]"],
|
||||
props: ["crypto_key", "items", "items_headers", "items_relations", "group_by", "hidden_fields"],
|
||||
props: {
|
||||
items: Array,
|
||||
items_headers: Array,
|
||||
items_relations: {
|
||||
default: function () {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
group_by: String,
|
||||
hidden_fields: {
|
||||
default: function () {
|
||||
return []
|
||||
},
|
||||
},
|
||||
non_editable_fields: {
|
||||
default: function () {
|
||||
return []
|
||||
},
|
||||
},
|
||||
show_item: {
|
||||
default: "id",
|
||||
},
|
||||
show_url: {
|
||||
default: "{{ show_url|default:'' }}",
|
||||
},
|
||||
},
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
valid: false,
|
||||
dialog: false,
|
||||
dialogDelete: false,
|
||||
editedIndex: -1,
|
||||
defaultItem: {},
|
||||
editedItem: {},
|
||||
search: null,
|
||||
show_url: "{{ show_url|default:'' }}",
|
||||
default_hidden_fields: [{% for field in default_hidden_fields %}"{{ field }}",{% endfor %}]
|
||||
default_hidden_fields: [{% for field in default_hidden_fields %}"{{ field }}",{% endfor %}],
|
||||
rules: {
|
||||
required: value => !!value || "{{_('Required') | escapejs}}",
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
editable_fields: function() {
|
||||
return this.items_headers.filter(e => e.editable)
|
||||
return this.items_headers.filter(e => e.editable).filter(e => !this.non_editable_fields.includes(e.value))
|
||||
},
|
||||
|
||||
citems_headers: function() {
|
||||
@@ -44,23 +71,21 @@
|
||||
},
|
||||
|
||||
showItem (item) {
|
||||
this.$router.replace({ name: this.show_url, params: { id: item.id }})
|
||||
this.$router.push({ name: this.show_url, params: { id: item[this.show_item] }})
|
||||
},
|
||||
|
||||
editItem (item) {
|
||||
this.editedIndex = this.items.indexOf(item)
|
||||
this.editedItem = Object.assign({}, item)
|
||||
this.dialog = true
|
||||
},
|
||||
|
||||
deleteItem (item) {
|
||||
this.editedIndex = this.items.indexOf(item)
|
||||
this.editedItem = Object.assign({}, item)
|
||||
this.dialogDelete = true
|
||||
},
|
||||
|
||||
deleteItemConfirm () {
|
||||
this.$emit("deleteItem", this.editedIndex)
|
||||
this.$emit("deleteItem", this.editedItem)
|
||||
this.closeDelete()
|
||||
|
||||
},
|
||||
@@ -68,25 +93,26 @@
|
||||
close () {
|
||||
this.dialog = false
|
||||
this.editedItem = Object.assign({}, this.defaultItem)
|
||||
this.editedIndex = -1
|
||||
},
|
||||
|
||||
closeDelete () {
|
||||
this.dialogDelete = false
|
||||
this.editedItem = Object.assign({}, this.defaultItem)
|
||||
this.editedIndex = -1
|
||||
},
|
||||
|
||||
|
||||
save () {
|
||||
|
||||
if (this.editedIndex > -1) {
|
||||
const isValid = this.$refs.form.validate()
|
||||
if (!isValid) return
|
||||
|
||||
this.$emit("editItem", this.editedIndex, this.editedItem)
|
||||
if (this.editedItem.id == null) {
|
||||
|
||||
this.$emit("createItem", this.editedItem)
|
||||
|
||||
} else {
|
||||
|
||||
this.$emit("createItem", this.editedItem)
|
||||
this.$emit("editItem", this.editedItem)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +1,3 @@
|
||||
async function init() {
|
||||
|
||||
const operations = crypto.subtle
|
||||
|
||||
const KEY_LEN = 256
|
||||
|
||||
const ENCRYPTION_ALGO = "AES-GCM"
|
||||
const ENCRYPTION_USAGES = ["encrypt", "decrypt"]
|
||||
const ENCRYPTION_PARAMS = { name: ENCRYPTION_ALGO, length: KEY_LEN }
|
||||
|
||||
const WRAPPING_ALGO = "AES-KW"
|
||||
const WRAPPING_USAGES = ["wrapKey", "unwrapKey"]
|
||||
|
||||
const DERIVATION_ALGO = "ECDH"
|
||||
|
||||
const { publicKey, privateKey } = await operations.generateKey(
|
||||
{
|
||||
name: DERIVATION_ALGO,
|
||||
namedCurve: "P-384",
|
||||
},
|
||||
false,
|
||||
["derivekey"]
|
||||
)
|
||||
|
||||
const encryptionKey = await operations.deriveKey(
|
||||
{
|
||||
name: DERIVATION_ALGO,
|
||||
public: publicKey,
|
||||
},
|
||||
privateKey,
|
||||
ENCRYPTION_PARAMS,
|
||||
false,
|
||||
["encrypt"]
|
||||
)
|
||||
|
||||
const decryptionKey = await operations.deriveKey(
|
||||
{ name: DERIVATION_ALGO, public: publicKey },
|
||||
privateKey,
|
||||
ENCRYPTION_PARAMS,
|
||||
false,
|
||||
['decrypt']
|
||||
)
|
||||
|
||||
return { encryptionKey, decryptionKey }
|
||||
|
||||
}
|
||||
|
||||
|
||||
function stringToArrayBuffer(str) {
|
||||
var buf = new ArrayBuffer(str.length);
|
||||
var bufView = new Uint8Array(buf);
|
||||
@@ -64,59 +16,3 @@ function arrayBufferToString(str) {
|
||||
}
|
||||
return byteString;
|
||||
}
|
||||
|
||||
|
||||
async function aEncryptWithKey(key, data) {
|
||||
// Encrypt data with key. Return a Promise
|
||||
return new Promise((resolve) => {
|
||||
window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv: stringToArrayBuffer(key.uuid),
|
||||
},
|
||||
key.key,
|
||||
stringToArrayBuffer(data)
|
||||
).then(text => {
|
||||
|
||||
resolve(btoa(arrayBufferToString(text)));
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function encryptWithKey(key, data) {
|
||||
// Encrypt data with key. Return a Promise
|
||||
return new Promise((resolve) => {
|
||||
window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv: stringToArrayBuffer(key.uuid),
|
||||
},
|
||||
key.key,
|
||||
stringToArrayBuffer(data)
|
||||
).then(text => {
|
||||
|
||||
resolve(btoa(arrayBufferToString(text)));
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function decryptWithKey(key, data) {
|
||||
// Decrypt data with key. Return a Promise
|
||||
return new Promise((resolve) => {
|
||||
window.crypto.subtle.decrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv: stringToArrayBuffer(key.uuid),
|
||||
},
|
||||
key.key,
|
||||
stringToArrayBuffer(atob(data))
|
||||
).then(text => {
|
||||
|
||||
resolve(arrayBufferToString(text));
|
||||
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
+91
-49
@@ -1,6 +1,7 @@
|
||||
|
||||
{% include "vue/plugins.js" %}
|
||||
|
||||
Vue.config.devtools = true
|
||||
|
||||
Vue.use(VueRouter)
|
||||
Vue.use(Vuex)
|
||||
Vue.use(EncryptionPlugin)
|
||||
@@ -24,29 +25,13 @@ const routes = [
|
||||
{% endfor %}
|
||||
]
|
||||
|
||||
|
||||
const encryptionStore = new Vuex.Store({
|
||||
state: {
|
||||
aes_key: null,
|
||||
keyPair: null,
|
||||
},
|
||||
|
||||
mutations: {
|
||||
update_aes_key (state, key) {
|
||||
state.aes_key = key
|
||||
},
|
||||
|
||||
update_keyPair (state, keyPair) {
|
||||
state.keyPair = keyPair
|
||||
},
|
||||
}
|
||||
})
|
||||
{% include "vue/stores.js" %}
|
||||
|
||||
const router = new VueRouter({routes})
|
||||
const approuter = new Vue({
|
||||
router,
|
||||
vuetify: new Vuetify(),
|
||||
store: encryptionStore,
|
||||
store: store,
|
||||
el: "#main",
|
||||
data: {
|
||||
uuid: "{{ user_settings.id }}",
|
||||
@@ -54,7 +39,7 @@ const approuter = new Vue({
|
||||
|
||||
computed: {
|
||||
locked: function() {
|
||||
return this.$store.state.aes_key == null || this.$store.state.keyPair?.privateKey == null
|
||||
return this.$store.state.encryption.aes_key == null || this.$store.state.encryption.keyPair?.privateKey == null
|
||||
}
|
||||
},
|
||||
|
||||
@@ -62,56 +47,113 @@ const approuter = new Vue({
|
||||
|
||||
methods: {
|
||||
async load_keys (aes_key) {
|
||||
const response = await this.$http.get(Urls["users:keys"]())
|
||||
try {
|
||||
|
||||
const iv_private = `${this.uuid}--private`
|
||||
const iv_public = `${this.uuid}--public`
|
||||
const response = await this.$http.get(Urls["users:keys"]())
|
||||
|
||||
if (response.data.privateKey != null) {
|
||||
const iv_private = `${this.uuid}--private`
|
||||
const iv_public = `${this.uuid}--public`
|
||||
|
||||
if (response.data.privateKey != null) {
|
||||
|
||||
const keyPair = {
|
||||
privateKey: await this.unwrapKey(aes_key, response.data.privateKey, iv_private, ["decrypt"]),
|
||||
publicKey: await this.unwrapKey(aes_key, response.data.publicKey, iv_public, ["encrypt"]),
|
||||
}
|
||||
|
||||
this.$store.commit('encryption/updateKeyPair', keyPair)
|
||||
|
||||
Swal.fire({title: "Successfully loaded K356!", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000});
|
||||
|
||||
} else {
|
||||
|
||||
const keyPair = await this.generateKeyPair()
|
||||
|
||||
await this.$http.post(
|
||||
Urls["users:keys"](),
|
||||
{
|
||||
privateKey: await this.wrapKey(this.keyPair.privateKey, aes_key, iv_private),
|
||||
publicKey: await this.wrapKey(this.keyPair.publicKey, aes_key, iv_public),
|
||||
}
|
||||
)
|
||||
|
||||
this.$store.commit('encryption/updateKeyPair', keyPair)
|
||||
|
||||
Swal.fire({title: "Successfully created K356!", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000});
|
||||
|
||||
const keyPair = {
|
||||
privateKey: await this.unwrapKey(aes_key, response.data.privateKey, iv_private, ["decrypt"]),
|
||||
publicKey: await this.unwrapKey(aes_key, response.data.publicKey, iv_public, ["encrypt"]),
|
||||
}
|
||||
|
||||
this.$store.commit('update_keyPair', keyPair)
|
||||
this.load_items()
|
||||
this.load_properties()
|
||||
this.load_relations()
|
||||
|
||||
Swal.fire({title: "Successfully loaded K356!", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000});
|
||||
} catch (err) {
|
||||
|
||||
} else {
|
||||
|
||||
const keyPair = await this.generateKeyPair()
|
||||
|
||||
await this.$http.post(
|
||||
Urls["users:keys"](),
|
||||
{
|
||||
privateKey: await this.wrapKey(this.keyPair.privateKey, aes_key, iv_private),
|
||||
publicKey: await this.wrapKey(this.keyPair.publicKey, aes_key, iv_public),
|
||||
}
|
||||
)
|
||||
|
||||
this.$store.commit('update_keyPair', keyPair)
|
||||
|
||||
Swal.fire({title: "Successfully created K356!", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000});
|
||||
Swal.fire({title: "{{_('Error during unwrapping of private key.<br><br>Maybe your password is wrong?') | escapejs}}", icon: "error", showConfirmButton: false})
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
update_key: function(key) {
|
||||
this.$store.commit('update_aes_key', key)
|
||||
this.$store.commit('encryption/updateAesKey', key)
|
||||
|
||||
this.load_keys(key)
|
||||
},
|
||||
|
||||
lock_me: function() {
|
||||
this.$store.commit('update_keyPair', null)
|
||||
this.$store.commit('update_aes_key', null)
|
||||
}
|
||||
this.$store.commit('encryption/updateKeyPair', null)
|
||||
this.$store.commit('encryption/updateAesKey', null)
|
||||
|
||||
// Lock all stores
|
||||
this.$store.commit('encryption/lock')
|
||||
this.$store.commit('items/lock')
|
||||
this.$store.commit('types/lock')
|
||||
this.$store.commit('relations/lock')
|
||||
this.$store.commit('properties/lock')
|
||||
this.$store.commit('linkedProperties/lock')
|
||||
this.$store.commit('relationProperties/lock')
|
||||
},
|
||||
|
||||
async load_items () {
|
||||
|
||||
const response = await this.$http.get(Urls["items:list"]())
|
||||
|
||||
this.$store.state.items.headers = response.data.result.items_headers
|
||||
this.$store.state.types.headers = response.data.result.types_headers
|
||||
|
||||
this.$store.dispatch("items/setItems", { self: this, items: response.data.result.items })
|
||||
this.$store.dispatch("types/setItems", { self: this, items: response.data.result.types })
|
||||
|
||||
},
|
||||
|
||||
async load_properties () {
|
||||
|
||||
const response = await this.$http.get(Urls["items:property.list"]())
|
||||
|
||||
this.$store.state.properties.headers = response.data.result.properties_headers
|
||||
this.$store.state.linkedProperties.headers = response.data.result.linked_properties_headers
|
||||
this.$store.state.relationProperties.headers = response.data.result.relation_properties_headers
|
||||
|
||||
this.$store.dispatch("properties/setItems", { self: this, items: response.data.result.properties })
|
||||
this.$store.dispatch("linkedProperties/setItems", { self: this, items: response.data.result.linked_properties })
|
||||
this.$store.dispatch("relationProperties/setItems", { self: this, items: response.data.result.relation_properties })
|
||||
|
||||
},
|
||||
|
||||
async load_relations () {
|
||||
|
||||
const response = await this.$http.get(Urls["items:relation.list"]())
|
||||
|
||||
this.$store.state.relations.headers = response.data.result.headers
|
||||
|
||||
this.$store.dispatch("relations/setItems", { self: this, items: response.data.result.relations })
|
||||
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
// Prevent from routing if key is not present.
|
||||
// Prevent from routing when locked or loading.
|
||||
next(!approuter.locked)
|
||||
})
|
||||
|
||||
@@ -105,7 +105,7 @@ const EncryptionPlugin = {
|
||||
|
||||
return btoa(arrayBufferToString(await operations.encrypt(
|
||||
{ name: "RSA-OAEP" },
|
||||
this.$store.state.keyPair.publicKey,
|
||||
this.$store.state.encryption.keyPair.publicKey,
|
||||
stringToArrayBuffer(data),
|
||||
)))
|
||||
|
||||
@@ -115,7 +115,7 @@ const EncryptionPlugin = {
|
||||
|
||||
return arrayBufferToString(await operations.decrypt(
|
||||
{ name: "RSA-OAEP" },
|
||||
this.$store.state.keyPair.privateKey,
|
||||
this.$store.state.encryption.keyPair.privateKey,
|
||||
stringToArrayBuffer(atob(armored_data))
|
||||
))
|
||||
|
||||
@@ -153,6 +153,42 @@ const EncryptionPlugin = {
|
||||
}))
|
||||
|
||||
return newobj
|
||||
},
|
||||
|
||||
Vue.prototype.object_edit = async function (url_edit, url_create, type, method, obj) {
|
||||
|
||||
let url = null
|
||||
|
||||
if (obj.id == undefined || obj.id == null) {
|
||||
url = Urls[url_create]()
|
||||
} else {
|
||||
url = Urls[url_edit](obj.id)
|
||||
}
|
||||
|
||||
const efields = this.$store.getters[`${type}/encryptedFields`]
|
||||
|
||||
try {
|
||||
|
||||
const newobj = await this.encryptObject(efields, obj)
|
||||
const response = await this.$http[method](url, newobj)
|
||||
|
||||
if (method != "delete") {
|
||||
return await this.decryptObject(efields, response.data.object)
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
|
||||
let msg = "{{_('Error during edition') | escapejs}}"
|
||||
if (method == "delete") {
|
||||
msg = "{{_('Error during deletion') | escapejs}}"
|
||||
}
|
||||
|
||||
Swal.fire({title: msg, icon: "error", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
|
||||
|
||||
throw err
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
const encryptionStore = {
|
||||
namespaced: true,
|
||||
state: () => (
|
||||
{
|
||||
aes_key: null,
|
||||
keyPair: null,
|
||||
}
|
||||
),
|
||||
|
||||
mutations: {
|
||||
lock (state) {
|
||||
state.aes_key = null
|
||||
state.keyPair = null
|
||||
},
|
||||
|
||||
updateAesKey (state, key) {
|
||||
state.aes_key = key
|
||||
},
|
||||
|
||||
updateKeyPair (state, keyPair) {
|
||||
state.keyPair = keyPair
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const storeMixin = {
|
||||
state: () => (
|
||||
{
|
||||
items: [],
|
||||
headers: [],
|
||||
}
|
||||
),
|
||||
|
||||
mutations: {
|
||||
lock (state) {
|
||||
state.items = []
|
||||
},
|
||||
|
||||
addItem (state, item) {
|
||||
state.items.push(item)
|
||||
},
|
||||
|
||||
removeItem (state, id) {
|
||||
state.items = state.items.filter(i => i.id != id)
|
||||
|
||||
Swal.fire({title: "{{_('Successfully deleted!') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
|
||||
},
|
||||
|
||||
editItem (state, item_edited) {
|
||||
state.items = state.items.map(i => {
|
||||
if (i.id == item_edited.id) {
|
||||
return item_edited
|
||||
}
|
||||
|
||||
return i
|
||||
})
|
||||
|
||||
Swal.fire({title: "{{_('Successfully edited') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
|
||||
},
|
||||
},
|
||||
|
||||
getters: {
|
||||
encryptedFields (state) {
|
||||
return state.headers.filter(e => e.encrypted).map(e => e.value)
|
||||
},
|
||||
|
||||
getById: (state) => (id) => {
|
||||
return state.items.find(e => e.id == id)
|
||||
},
|
||||
},
|
||||
|
||||
actions: {
|
||||
async setItems ({ commit, getters }, payload) {
|
||||
return payload.items.map(async item => {
|
||||
const new_item = await payload.self.decryptObject(getters.encryptedFields, item)
|
||||
|
||||
return await commit('addItem', new_item)
|
||||
})
|
||||
},
|
||||
|
||||
async addItem ({ getters, commit }, payload) {
|
||||
|
||||
const new_item = await payload.self.decryptObject(getters.encryptedFields, payload.item)
|
||||
|
||||
return await commit('addItem', new_item)
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const itemStore = {__proto__: storeMixin, namespaced: true}
|
||||
const typeStore = {__proto__: storeMixin, namespaced: true}
|
||||
const relationStore = {__proto__: storeMixin, namespaced: true}
|
||||
const propertyStore = {__proto__: storeMixin, namespaced: true}
|
||||
const linkedPropertyStore = {__proto__: storeMixin, namespaced: true}
|
||||
const relationPropertyStore = {__proto__: storeMixin, namespaced: true}
|
||||
|
||||
const store = new Vuex.Store({
|
||||
modules: {
|
||||
encryption: encryptionStore,
|
||||
items: itemStore,
|
||||
types: typeStore,
|
||||
relations: relationStore,
|
||||
properties: propertyStore,
|
||||
linkedProperties: linkedPropertyStore,
|
||||
relationProperties: relationPropertyStore,
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user