API Storage
Introducción
Para poder utilizar las funcionalidades del storage el desarrollador deberá activar en el claimset de la extensión los permisos de 'Aurapps Storage'
Permite almacenar información de las extensiones en nuestros servidores para luego recuperarla cuando sea necesario. (Véase tambíen Módulo Storage del SDK).
La información se almacena en formato Key-Value, es decir, un objeto JSON (Value) bajo un nombre (Key).
Además, cada Key-Value se asocia a un alcance: Usuarios, Lotes o Campos. Este alcance define quién puede acceder a los datos. Por ejemplo, si se crea un Key-Value asociado a un Lote, todos los usuarios que tengan acceso de lectura sobre dicho lote podrán recuperar ese dato, independientemente del usuario que lo almacenó.
Es importante pensar correctamente el alcance que se le va asignar al Key-Value para no exponer datos.
Sobre el alcance de un Usuario, los Key-Values pueden ser:
- creados/recuperados por el usuario en cuestión.
- creados/recuperados por el administrador del espacio al que el usuario pertenece (en caso de pertenecer a un espacio).
- recuperados por el supervisor con permiso de lectura del grupo al que el usuario pertenece (en caso de pertenecer a un grupo de supervisión).
- creados/recuperados por el supervisor con permiso de edición del grupo al que el usuario pertenece (en caso de pertenecer a un grupo de supervisión).
- eliminados por el mismo usuario o su supervisor o administrador (en caso de formar parte de un espacio)
Sobre el alcance de un Lote, los Key-Values pueden ser:
- creados/recuperados por los usuarios dueños o con permiso de edición/agregado/administración sobre el Lote.
- recuperados por los usuarios con permiso de lectura sobre el Lote.
- eliminados por los usuarios con permiso de administración sobre el lote.
Sobre el alcance de un Campo, los Key-Values pueden ser:
- creados/recuperados por los usuarios dueños o con permiso de edición/agregado/administración sobre el Campo.
- recuperados por los usuarios dueños o con algún permiso sobre el Campo.
- eliminados por los usuarios con permiso de administración sobre el campo.
Los nombres de los objetos pueden ser combinaciones de letras a-Z, números o guión bajo (_). Debe verificar el regex "\w+"
Para un mismo alcance, no se puede repetir el nombre del objeto.
API
La API posee solo un método, el método POST.
Content-Type: application/json
POST api/mktplace/storage
A partir de el, podemos acceder a los distintos alcances descritos anteriormente.
Alcance de usuario
Content-Type: application/json
POST api/mktplace/storage/users
Alcance de lote
Content-Type: application/json
POST api/mktplace/storage/fields
Alcance de campo
Content-Type: application/json
POST api/mktplace/storage/farms
A su vez, en el mismo endpoint se encuentran las 4 operaciones del storage, estas son: PUT, PATCH, GET y DELETE
- Parámetro en la URL:
operation
: PUT/PATCH/GET/DELETE
Operación PUT
Permite almacenar un objeto bajo un nombre (Key).
Parámetros:
Recibe un solo parámetro de tipo objeto que cuenta con las siguientes propiedades:
id
: ID del recurso (Usuario, Lote o Campo) según el alcancekey
: Key del objeto a almacenarvalue
: objeto a almacenaroverwrite
: (opcional) bool indicando si se debe sobreescribir el objeto en caso de ya existir. De no especificarse, por defecto toma el valor false.
Ejemplo de uso:
fetch("https://api.auravant.com/api/mktplace/storage/users?operation=PUT", {
method: "POST",
headers: {
authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
id: "UID-dbaefe8503fe6cdb7909611e8953e74f",
key: "test_key",
value: { name: "juan", lastname: "perez" },
overwrite: true,
}),
}).then(async (resp) => {
const response = await resp.json();
console.log(response);
});
Respuesta:
Promesa con el objeto JSON de respuesta bajo la llave "info". Este objeto tiene la propiedad "code" que indica el resultado de la operación:
code | descripción |
---|---|
1 | faltan datos |
2 | la Key es inválida, al no respetar regex '^\w+$' |
3 | el usuario no tiene permisos sobre el recurso según el alcance solicitado |
4 | versión de Extensión inválida |
5 | la Key ya existe para el alcance dado. (Solo posible si overwrite es false) |
6 | Error |
En caso que "code" < 0, revisar los códigos de respuesta generales.
Operación PATCH
Permite modificar un objeto bajo un nombre (Key) ya existente.
Parámetros:
Recibe un solo parámetro de tipo objeto que cuenta con las siguientes propiedades:
id
: ID del recurso (Usuario, Lote o Campo) según el alcancekey
: Key del objeto a modificarvalue
: objeto nuevoappend
:false por defecto
, booleano que, en caso de ser true, indica que el value debe agregarse al valor existente bajo la misma key. En caso de ser false, indica que el value debe reemplazar el valor previo bajo la misma key.create
:false por defecto
, booleano que indica si debe o no crearse la key, en caso de no existir previamente.
Ejemplo de uso:
fetch("https://api.auravant.com/api/mktplace/storage/users?operation=PATCH", {
method: "POST",
headers: {
authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
id: "UID-dbaefe8503fe6cdb7909611e8953e74f",
key: "test_key",
value: { name: "jane", lastname: "doe" },
create: true,
}),
}).then(async (resp) => {
const response = await resp.json();
console.log(response);
});
Respuesta:
Promesa con el objeto JSON de respuesta bajo la llave "info". Este objeto tiene la propiedad "code" que indica el resultado de la operación:
code | descripción |
---|---|
0 | objeto modificado exitosamente |
1 | faltan datos |
2 | la Key es inválida, al no respetar regex '^\w+$' |
3 | el usuario no tiene permisos sobre el recurso según el alcance solicitado |
4 | versión de Extensión inválida |
5 | la Key ya existe para el alcance dado |
6 | Error |
En caso que "code" < 0, revisar los códigos de respuesta generales.
Operación GET
Permite recuperar los objetos bajo uno o varios nombres (Keys). Es posible obtener múltiples Keys para múltiples IDs en una única llamada.
Parámetros:
Recibe un solo parámetro de tipo objeto que cuenta con las siguientes propiedades:
ids
: array de IDs de los recursos (Usuario, Lote o Campo) según el alcance.keys
: array de las Keys a recuperar.
Se recuperará cada Key del array keys para cada ID del array ids, si es que existen. Además, en caso de enviar en ids un array vacío para el alcance Lotes o Campos, se buscarán las keys indicadas para todos los Lotes/Campos sobre los que el usuario tenga permiso de lectura.
Ejemplo de uso:
fetch("https://api.auravant.com/api/mktplace/storage/users?operation=GET", {
method: "POST",
headers: {
authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
ids: ["UID-dbaefe8503fe6cdb7909611e8953e74f"],
keys: ["test_key", "no_key"],
}),
}).then(async (resp) => {
const response = await resp.json();
console.log(response);
});
Respuesta:
Promesa con el objeto JSON de respuesta bajo la llave "info". Este objeto tiene la propiedad "code" que indica el resultado de la operación, y la propiedad "objects" con los datos:
code | descripción |
---|---|
0 | objeto recuperado exitosamente |
1 | faltan datos |
2 | al menos una Key solicitada es inválida, al no respetar regex '\w+' |
3 | el usuario no tiene permisos sobre al menos un recurso según el alcance solicitado |
4 | versión de Extensión inválida |
5 | al menos un ID solicitado es inválido |
En caso que "code" < 0, revisar los códigos de respuesta generales.
Operación DELETE
Permite eliminar uno o múltiples objetos bajo nombres (Keys) ya existentes.
Parámetros:
Recibe un solo parámetro de tipo objeto que cuenta con las siguientes propiedades:
id
: ID del recurso (Usuario, Lote o Campo) según el alcancekeys
: array con las Keys a eliminar.
Ejemplo de uso:
fetch("https://api.auravant.com/api/mktplace/storage/users?operation=DELETE", {
method: "POST",
headers: {
authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
id: "UID-dbaefe8503fe6cdb7909611e8953e74f",
keys: ["test_key"],
}),
}).then(async (resp) => {
const response = await resp.json();
console.log(response);
});
Respuesta:
Promesa con el objeto JSON de respuesta bajo la llave "info". Este objeto tiene la propiedad "code" que indica el resultado de la operación:
code | descripción |
---|---|
0 | objeto modificado exitosamente |
1 | la Key no fue provista |
2 | la Key es inválida, al no respetar regex '^\w+$' |
3 | el usuario no tiene permisos sobre el recurso según el alcance solicitado |
4 | versión de Extensión inválida |
6 | Error |
En caso que "code" < 0, revisar los códigos de respuesta generales.
File Storage
El File Storage permite a una extensión almacenar archivos para un usuario, lote o campo. Los alcances son iguales a los explicados en la sección del storage convencional.
Alcance de usuario
Content-Type: application/json
POST api/mktplace/filestorage/users
Alcance de lote
Content-Type: application/json
POST api/mktplace/filestorage/fields
Alcance de campo
Content-Type: application/json
POST api/mktplace/filestorage/farms
Operación GET
Consulta para obtener información de los archivos guardados en storage. Se agrega en el POST el parámetro con la operación correspondiente:
?operation=GET
Body
keys
: array de keys a consultar - Obligatorioids
: array de ids para filtrar recursos sobre los que buscar las keys:- según el scope, serán ids de usuarios, lotes o campos.
- en el scope de users, si no se incluye, se asume que se está consultando por el usuario que realiza la consulta.
- en los scopes de fields y farms, si no se incluye, se buscan las keys solicitadas en todos los lotes/campos a los que tiene acceso el usuario
get_url
: booleano que indica si se debe retornar o no la url de descarga en la respuesta.
Respuesta:
{
"objects": {
"resource_id_1": {
"key_1": {
"file_name": "d5fa71aa-1f35-11ef-a2b9-ab5cffcaca66.pdf",
"file_size_kb": 150.5,
"created_at": "2024-01-01T00:00:00Z",
"url": "..."
}
},
"resource_id_1": {...}
}
}
file_name
: string que representa el nombre del archivo.file_size_kb
: peso del archivo en kilobytes.created_at
: fecha y hora en la que fue guardado en storage el archivo.url
: string de la url que permite realizar la descarga del archivo.
En caso de solicitar keys para el scope de users y no indicar ids, como la consulta se realiza para el mismo usuario, la respuesta es distinta ya que no se incluye el nivel de recurso.
Respuesta sin nivel de recurso:
{
"objects": {
"key_1": {
"file_name": "d5fa71aa-1f35-11ef-a2b9-ab5cffcaca66.pdf",
"file_size_kb": 150.5,
"created_at": "2024-01-01T00:00:00Z",
"url": "..."
},
"key_2": {...}
}
}
Operación PUT
Este endpoint nos permite crear una key y como respuesta obtendremos una url para subir el archivo al storage. Entonces al momento de realizar esta consulta, la nueva key se generará y figurará en el listado de las consultas GET, pero hasta que el cliente no suba el nuevo archivo con la URL provista, el mismo no estará disponible. En caso de sobreescribir una key, el archivo reemplazado se eliminará al momento de hacer la consulta.
Se agrega en el POST el parámetro con la operación correspondiente:
?operation=PUT
Body
key
: string key sobre la que se quiere guardar el archivo.original_file_name
: string que representa el nombre del archivo que se quiere subirmd5
: string hash MD5 codificado en base64 del archivo a subir. Este es el valor que luego debe enviarse al subir el archivo.file_size_kb
: float tamaño en kb del archivo a subir.overwrite
: boolean que indica si sobreescribir la key en caso de que ya exista. Por default es false por lo que si la key indicada ya existe, el endpoint responderá con error.user
: UID-XXXX id encriptado. Sólo obligatorio en el scope users, indicando el id del usuario sobre el cual se desea guardar.field
: uuid/int sólo obligatorio en el scope fields, indicando el id del lote sobre el cual se desea guardar.farm
: uuid/int sólo obligatorio en el scope farms, indicando el id del campo sobre el cual se desea guardar.
Código Javascript para obtener el md5
requerido en el body de la consulta:
const reader = new FileReader();
reader.readAsBinaryString(blob);
reader.onloadend = () => {
resolve(CryptoJS.enc.Base64.stringify(CryptoJS.MD5(CryptoJS.enc.Latin1.parse(reader.result.toString()))));
};
Respuesta
{
"data": {
"url": "....",
"fields": {
"f1": "...",
"f2": "...",
"f3": "..."
}
}
}
Tras una respuesta correcta, la key ya se encuentra almacenada y el próximo paso es subir el archivo. Para eso se utiliza el objeto devuelto bajo la key data
de la siguiente manera:
Se debe realizar un POST a la url devuelta, con un Content-Type multipart/form-data y un Body que incluya todos los key-value que se encuentran bajo la key fields
del objeto devuelto en la misma respuesta del PUT. Además, se deberá incluir en el form un campo Content-MD5 con el hash MD5 del archivo a subir.
Datos a tener en cuenta
- La url de subida tiene una vigencia de 10 segundos.
- El máximo tamaño de archivo está configurado en 10MB.
- Para la descarga de archivos sólo se proporciona una URL y se descarga mediante un GET.
- La url de descarga tiene una vigencia de 10 segundos.
Posibles errores
code | descripción |
---|---|
2 | formato de key inválido |
3 | no se tiene permiso sobre el recurso (usuario/lote/campo) indicado |
5 | la key indicada ya existe para el recurso indicado, y no se envió el flag de overwrite |
7 | el archivo supera el tamaño máximo permitido |
Operación PATCH
Este endpoint sirve para actualizar el archivo almacenado bajo una key. Primero se realiza la modificación en el endpoint, obteniendose la nueva url para subir el nuevo archivo.
Al momento de realizar esta consulta, el nuevo valor reemplaza al anterior y el archivo reemplazado se elimina inmediatamente. En las consultas GET se listará el nuevo archivo pero hasta que el cliente no lo suba con la URL provista, el mismo no estará disponible.
Se agrega en el POST el parámetro con la operación correspondiente:
?operation=PATCH
Body
key
: string key sobre la que se quiere sobreescribir el archivo.original_file_name
: string nombre del archivo que se quiere subir.md5
: string hash MD5 codificado en base64 del archivo a subir. Este es el valor que luego debe enviarse al subir el archivo.file_size_kb
: float tamaño en kb del archivo a subir.create
: boolean indica si crear la key en caso de no existir. Por default es false por lo que si la key indicada no existe, el endpoint responderá con error.user
: UID-XXXX id encriptado. Sólo obligatorio en el scope users, indicando el id del usuario sobre el cual se desea guardar.field
: uuid/int sólo obligatorio en el scope fields, indicando el id del lote sobre el cual se desea guardar.farm
: uuid/int sólo obligatorio en el scope farms, indicando el id del campo sobre el cual se desea guardar.
Respuesta
La respuesta y el procedimiento a seguir posteriormente para hacer efectiva la subida del archivo son iguales a lo explicado para el PUT.
Posibles errores
code | descripción |
---|---|
2 | formato de key inválido |
3 | no se tiene permiso sobre el recurso (usuario/lote/campo) indicado |
5 | la key indicada no existe para el recurso indicado, y no se envió el flag de create |
7 | el archivo supera el tamaño máximo permitido |
Operación DELETE
Este servicio nos permite borrar keys del storage. Se pueden borrar una key o un grupo de keys para todos los recursos del scope o filtrar por id de recurso.
Se agrega en el POST el parámetro con la operación correspondiente:
?operation=DELETE
Body
keys
: este es un parámetro obligatorio, es el array de keys a eliminar.id
: este parámetro es opcional, puede ser un string o un int id del recurso.
Respuesta
{
"data": {
"keys": ["key_eliminada_1", "key_eliminada_2"]
}
}
Posibles errores
code | descripción |
---|---|
2 | formato de key inválido |
3 | no se tiene permiso sobre el recurso (usuario/lote/campo) indicado |
Compartir datos entre extensiones
Esta funcionalidad permite compartir datos en y entre extensiones de tal forma que la información sea más accesible a distintos niveles y entre diferentes usuarios. A continuación detallaremos cómo es el funcionamiento y cuáles son los usos que se le pueden dar.
URL base:
https://api.aurapps.com/
¿Qué significa compartir datos en y entre extensiones?
En todos los endpoints que usemos para este servicio tenemos la posibilidad de enviar un parámetro llamado 'client_id', el cual es opcional. En caso de que enviemos este parámetro las consultas que realicemos nos retornarán únicamente aquellos datos guardados en el storage de la extensión a la que corresponda dicho client_id bajo la key (enviada por parámetro) que comience con el prefijo 'public_ext_'. Entonces, si en una extensión guardamos información que querramos compartir con otras extensiones, debemos guardar dichos datos bajo una key que comience con el prefijo antes mencionado y lo único que debemos hacer desde las otras extensiones es enviar una consulta pasando por parámetro la misma key (sin el prefijo) y el client_id de la extensión de la que queremos extraer dichos datos.
En caso contrario, si no enviamos el parámetro 'client_id', la consulta nos retornará todos los datos guardados (en la extensión desde la cual se está realizando dicha consulta) bajo la key enviada por parámetro que comience con los prefijos 'public_priv_' y 'public_ext_'. Esto quiere decir que al ejecutar el GET de esta manera obtendremos toda la información que se haya guardado tanto para ser visualizada dentro de la extensión misma como para ser compartida con otras extensiones.
Public Values
Este módulo nos permite compartir entre las extensiones datos guardados en el storage en tres niveles diferentes: user, field y farm.
User
GET publicvalues/user
Parámetros:
key
: string que definimos como key bajo la cual se guardó la información en el storage sin el 'public_'client_id
: identificador público de la extensión. Este parámetro es opcional, solo se aplica si el usuario necesita ver información de una extensión en particular desde otra extensión.users
: listado de uuid de usuarios separados por comas. Este parámetro es opcional, en caso de ser utilizado el endpoint solo devolverá información de los usuarios consultados.dev
: booleano que define si la información será buscada en el storage de dev (en caso de ser verdadero) o el de producción (en caso de ser falso).
Ejemplo de respuesta:
[
{
"user": "UID-5112320dasd0112f2afd2eac1bb53b5190",
"value": {
"key_storage_1": "value_1",
"key_storage_2": "value_2",
"key_storage_3": "value_3"
}
}
]
Dentro del array se nos retorna objetos, los cuales tienen las siguientes propiedades:
user
: uuid del usuario en el que se guardaron los datos.value
: objeto que contiene todos los datos guardados a este nivel bajo la 'key' enviada por parámetro en la consulta.
Field
GET publicvalues/field
Parámetros:
key
: string que definimos como key bajo la cual se guardó la información en el storage.client_id
: identificador público de la extensión. Este parámetro es opcional, solo se aplica si el usuario necesita ver información de una extensión en particular desde otra extensión.fields
: listado de ids de lotes separados por comas. Este parámetro es obligatorio. El usuario debe tener permiso de lectura sobre los lotes consultados (permiso número 320). Si el usuario no tiene permiso de lectura sobre ninguno de los lotes consultados, el endpoint responderá con un 401. De lo contrario, retornará información de los lotes sobre los cuales si tiene dicho permiso.
Ejemplo de respuesta:
[
{
"field": 12345,
"value": {
"key_storage_1": "value_1",
"key_storage_2": "value_2",
"key_storage_3": "value_3"
}
}
]
Dentro del array se nos retorna objetos, los cuales tienen las siguientes propiedades:
field
: id del lote en el que se guardaron los datos.value
: objeto que contiene todos los datos guardados a este nivel bajo la 'key' enviada por parámetro en la consulta.
Farm
GET publicvalues/farm
Parámetros:
key
: string que definimos como key bajo la cual se guardó la información en el storage.client_id
: identificador público de la extensión. Este parámetro es opcional, solo se aplica si el usuario necesita ver información de una extensión en particular desde otra extensión.farms
: listado de ids de campos separados por comas. Este parámetro es obligatorio. El usuario debe tener permiso de lectura sobre los campos consultados (permiso número 320). Si el usuario no tiene permiso de lectura sobre ninguno de los campos consultados, el endpoint responderá con un 401. De lo contrario, retornará información de los campos sobre los cuales si tiene dicho permiso.
Ejemplo de respuesta:
[
{
"farm": 12345,
"value": {
"key_storage_1": "value_1",
"key_storage_2": "value_2",
"key_storage_3": "value_3"
}
}
]
Dentro del array se nos retorna objetos, los cuales tienen las siguientes propiedades:
farm
: id del campo en el que se guardaron los datos.value
: objeto que contiene todos los datos guardados a este nivel bajo la 'key' enviada por parámetro en la consulta.
Public Files
Este módulo nos permite compartir archivos guardados en el filestorage entre las extensiones en dos niveles diferentes: field y farm (a nivel de usuario aún no está implementado).
Farm
GET publicfiles/farm
Parámetros:
Mismos parámetros que para /publicvalues/farm
Ejemplo de respuesta:
{
"12345": {
"storage_key": {
"file_name": "1458480-0e39-47f6-1112-1212121.pdf",
"file_size_kb": 2357.9092,
"created_at": "2025-01-06T13:00:23Z",
"url": "https://avt-aurapps-storage....."
}
}
}
El endpoint nos retorna un conjunto de objetos, para los cuales cada key es el id de los campos consultados; dentro de estos vienen más objetos, cada uno de los cuales representan un file guardado en el storage para ese campo en particular (la key de estos objetos es el indentificador bajo el cual se guardó dicho file en storage). Cada file retorna los siguientes datos:
file_name
: nombre del archivo,file_size_kb
: peso en kilobytes del archivo.created_at
: fecha y hora en la que se guardó el archivo en storage.url
: pre-sign key que da acceso al archivo por una pequeña cantidad de tiempo (100 segundos). Haciendo una consulta al mismo y siempre que esto se haga durante el tiempo que dura dicho acceso, se puede descargar el archivo.
Field
GET publicfiles/field
Parámetros:
Mismos parámetros que para /publicvalues/field
Ejemplo de respuesta:
{
"6789": {
"storage_key": {
"file_name": "107565-as39-47074-av2-04780.pdf",
"file_size_kb": 1257.012,
"created_at": "2025-02-12T13:00:23Z",
"url": "https://avt-aurapps-storage....."
}
}
}
El endpoint nos retorna el mismo esquema de respuesta que para publicfiles/farm, con la diferencia de que en este caso la key de los objetos son los ids de los lotes consultados. Las propiedades que vienen dentro de los objetos que representan los files guardados en storage también son iguales al ejemplo anterior.