4794-mdb_block #1170
|
@ -0,0 +1,11 @@
|
||||||
|
CREATE TABLE `vn`.`mdbApp` (
|
||||||
|
`app` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||||
|
`baselineBranchFk` varchar(255) COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||||
|
`userFk` int(10) unsigned DEFAULT NULL,
|
||||||
|
`locked` datetime DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`app`),
|
||||||
|
KEY `mdbApp_FK` (`userFk`),
|
||||||
|
KEY `mdbApp_FK_1` (`baselineBranchFk`),
|
||||||
|
CONSTRAINT `mdbApp_FK` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `mdbApp_FK_1` FOREIGN KEY (`baselineBranchFk`) REFERENCES `mdbBranch` (`name`) ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci
|
|
@ -0,0 +1,4 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('MdbApp', 'lock', 'WRITE', 'ALLOW', 'ROLE', 'developer'),
|
||||||
|
('MdbApp', 'unlock', 'WRITE', 'ALLOW', 'ROLE', 'developer');
|
|
@ -2745,6 +2745,10 @@ INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`
|
||||||
VALUES
|
VALUES
|
||||||
(0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', 'open', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all');
|
(0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', 'open', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all');
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`mdbApp` (`app`, `baselineBranchFk`, `userFk`, `locked`)
|
||||||
|
VALUES
|
||||||
|
('foo', 'master', NULL, NULL),
|
||||||
|
('bar', 'test', 9, util.VN_NOW());
|
||||||
INSERT INTO `vn`.`ticketLog` (`id`, `originFk`, `userFk`, `action`, `changedModel`, `oldInstance`, `newInstance`, `changedModelId`)
|
INSERT INTO `vn`.`ticketLog` (`id`, `originFk`, `userFk`, `action`, `changedModel`, `oldInstance`, `newInstance`, `changedModelId`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1, 9, 'insert', 'Ticket', '{}', '{"clientFk":1, "nickname": "Bat cave"}', 1);
|
(1, 1, 9, 'insert', 'Ticket', '{}', '{"clientFk":1, "nickname": "Bat cave"}', 1);
|
||||||
|
|
|
@ -143,6 +143,7 @@
|
||||||
"Email verify": "Email verify",
|
"Email verify": "Email verify",
|
||||||
"Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) merged with [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})",
|
"Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) merged with [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})",
|
||||||
"Sale(s) blocked, please contact production": "Sale(s) blocked, please contact production",
|
"Sale(s) blocked, please contact production": "Sale(s) blocked, please contact production",
|
||||||
|
"App locked": "App locked by user {{userId}}",
|
||||||
"The sales of the receiver ticket can't be modified": "The sales of the receiver ticket can't be modified",
|
"The sales of the receiver ticket can't be modified": "The sales of the receiver ticket can't be modified",
|
||||||
"Receipt's bank was not found": "Receipt's bank was not found",
|
"Receipt's bank was not found": "Receipt's bank was not found",
|
||||||
"This receipt was not compensated": "This receipt was not compensated",
|
"This receipt was not compensated": "This receipt was not compensated",
|
||||||
|
|
|
@ -246,9 +246,11 @@
|
||||||
"Already has this status": "Ya tiene este estado",
|
"Already has this status": "Ya tiene este estado",
|
||||||
"There aren't records for this week": "No existen registros para esta semana",
|
"There aren't records for this week": "No existen registros para esta semana",
|
||||||
"Empty data source": "Origen de datos vacio",
|
"Empty data source": "Origen de datos vacio",
|
||||||
vicent marked this conversation as resolved
Outdated
|
|||||||
|
"App locked": "Aplicación bloqueada por el usuario {{userId}}",
|
||||||
"Email verify": "Correo de verificación",
|
"Email verify": "Correo de verificación",
|
||||||
"Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment",
|
"Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment",
|
||||||
"Receipt's bank was not found": "No se encontró el banco del recibo",
|
"Receipt's bank was not found": "No se encontró el banco del recibo",
|
||||||
"This receipt was not compensated": "Este recibo no ha sido compensado",
|
"This receipt was not compensated": "Este recibo no ha sido compensado",
|
||||||
"Client's email was not found": "No se encontró el email del cliente"
|
"Client's email was not found": "No se encontró el email del cliente",
|
||||||
}
|
"Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9"
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('lock', {
|
||||||
|
description: 'Lock an app for the user',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'appName',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'The app name',
|
||||||
|
http: {source: 'path'}
|
||||||
|
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:appName/lock`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.lock = async(ctx, appName, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const myOptions = {};
|
||||||
|
const $t = ctx.req.__; // $translate
|
||||||
|
|
||||||
|
let tx;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
vicent marked this conversation as resolved
jgallego
commented
hay que comprobar que no este bloqueado previamente hay que comprobar que no este bloqueado previamente
|
|||||||
|
try {
|
||||||
|
const mdbApp = await models.MdbApp.findById(appName, {fields: ['app', 'locked', 'userFk']}, myOptions);
|
||||||
vicent marked this conversation as resolved
Outdated
jgallego
commented
traer solo los campos necesarios ejemplo: traer solo los campos necesarios ejemplo:
`{fields: ['locked','userFk']}`
|
|||||||
|
|
||||||
|
if (mdbApp.locked) {
|
||||||
|
throw new UserError($t('App locked', {
|
||||||
|
userId: mdbApp.userFk
|
||||||
|
}));
|
||||||
vicent marked this conversation as resolved
Outdated
jgallego
commented
si se usa dentro del if crearla dentro del if. si se usa dentro del if crearla dentro del if.
En este caso se puede poner todo el codigo dentro de los parentesis, sin crear la variable
|
|||||||
|
}
|
||||||
|
|
||||||
|
const updatedMdbApp = await mdbApp.updateAttributes({
|
||||||
|
userFk: userId,
|
||||||
|
locked: new Date()
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
return updatedMdbApp;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,51 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
|
describe('MdbApp lock()', () => {
|
||||||
|
it('should throw an error if the app is already locked', async() => {
|
||||||
|
const tx = await models.MdbApp.beginTransaction({});
|
||||||
|
let error;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
vicent marked this conversation as resolved
Outdated
jgallego
commented
foo foo
|
|||||||
|
const appName = 'bar';
|
||||||
|
const developerId = 9;
|
||||||
|
const ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {userId: developerId},
|
||||||
|
__: () => {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await models.MdbApp.lock(ctx, appName, options);
|
||||||
|
|
||||||
|
expect(result.locked).not.toBeNull();
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should lock a mdb `, async() => {
|
||||||
|
const tx = await models.MdbApp.beginTransaction({});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const appName = 'foo';
|
||||||
|
const developerId = 9;
|
||||||
|
const ctx = {req: {accessToken: {userId: developerId}}};
|
||||||
|
|
||||||
|
const result = await models.MdbApp.lock(ctx, appName, options);
|
||||||
|
|
||||||
|
expect(result.locked).not.toBeNull();
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,22 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
|
describe('MdbApp unlock()', () => {
|
||||||
|
it(`should unlock a mdb `, async() => {
|
||||||
|
const tx = await models.MdbApp.beginTransaction({});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const appName = 'bar';
|
||||||
|
const developerId = 9;
|
||||||
|
const ctx = {req: {accessToken: {userId: developerId}}};
|
||||||
|
|
||||||
|
const result = await models.MdbApp.unlock(ctx, appName, options);
|
||||||
|
|
||||||
|
expect(result.locked).toBeNull();
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,40 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('unlock', {
|
||||||
|
description: 'Unlock an app for the user',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'appName',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'The app name',
|
||||||
|
http: {source: 'path'}
|
||||||
|
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:appName/unlock`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.unlock = async(ctx, appName, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
vicent marked this conversation as resolved
joan
commented
Llevar tot lo referent a tx i try-catch Llevar tot lo referent a tx i try-catch
|
|||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const mdbApp = await models.MdbApp.findById(appName, null, myOptions);
|
||||||
|
const updatedMdbApp = await mdbApp.updateAttributes({
|
||||||
|
userFk: null,
|
||||||
vicent marked this conversation as resolved
Outdated
joan
commented
En este caso no es necesario transaccionar si no se te pasa una transacción En este caso no es necesario transaccionar si no se te pasa una transacción
|
|||||||
|
locked: null
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
return updatedMdbApp;
|
||||||
|
};
|
||||||
|
};
|
|
@ -23,6 +23,12 @@ module.exports = Self => {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: true,
|
required: true,
|
||||||
description: `The branch name`
|
description: `The branch name`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'unlock',
|
||||||
|
type: 'boolean',
|
||||||
|
required: false,
|
||||||
|
description: `It allows unlock the app`
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
|
@ -35,9 +41,11 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.upload = async(ctx, appName, newVersion, branch, options) => {
|
Self.upload = async(ctx, appName, newVersion, branch, unlock, options) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
|
const $t = ctx.req.__; // $translate
|
||||||
|
|
||||||
const TempContainer = models.TempContainer;
|
const TempContainer = models.TempContainer;
|
||||||
const AccessContainer = models.AccessContainer;
|
const AccessContainer = models.AccessContainer;
|
||||||
|
@ -55,6 +63,14 @@ module.exports = Self => {
|
||||||
|
|
||||||
let srcFile;
|
let srcFile;
|
||||||
try {
|
try {
|
||||||
|
const mdbApp = await models.MdbApp.findById(appName, null, myOptions);
|
||||||
|
|
||||||
|
if (mdbApp.locked && mdbApp.userFk != userId) {
|
||||||
|
throw new UserError($t('App locked', {
|
||||||
|
userId: mdbApp.userFk
|
||||||
vicent marked this conversation as resolved
Outdated
jgallego
commented
mensaje dentro del if como arriba. mensaje dentro del if como arriba.
|
|||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
const tempContainer = await TempContainer.container('access');
|
const tempContainer = await TempContainer.container('access');
|
||||||
const uploaded = await TempContainer.upload(tempContainer.name, ctx.req, ctx.result, fileOptions);
|
const uploaded = await TempContainer.upload(tempContainer.name, ctx.req, ctx.result, fileOptions);
|
||||||
const files = Object.values(uploaded.files).map(file => {
|
const files = Object.values(uploaded.files).map(file => {
|
||||||
|
@ -79,7 +95,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
const existBranch = await models.MdbBranch.findOne({
|
const existBranch = await models.MdbBranch.findOne({
|
||||||
where: {name: branch}
|
where: {name: branch}
|
||||||
});
|
}, myOptions);
|
||||||
|
|
||||||
if (!existBranch)
|
if (!existBranch)
|
||||||
throw new UserError('Not exist this branch');
|
throw new UserError('Not exist this branch');
|
||||||
|
@ -108,7 +124,9 @@ module.exports = Self => {
|
||||||
app: appName,
|
app: appName,
|
||||||
branchFk: branch,
|
branchFk: branch,
|
||||||
version: newVersion
|
version: newVersion
|
||||||
});
|
}, myOptions);
|
||||||
|
|
||||||
|
if (unlock) await models.MdbApp.unlock(ctx, appName, myOptions);
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
if (tx) await tx.commit();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
{
|
{
|
||||||
|
"MdbApp": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"MdbBranch": {
|
"MdbBranch": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/mdbApp/lock')(Self);
|
||||||
|
require('../methods/mdbApp/unlock')(Self);
|
||||||
|
};
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "MdbApp",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "mdbApp"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"app": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The app name",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"type": "date"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"branch": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "MdbBranch",
|
||||||
|
"foreignKey": "baselineBranchFk"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "MdbBranch",
|
||||||
|
"foreignKey": "userFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
bloqueada