diff --git a/routes/application.js b/routes/application.js
index e87e5539c..ddcacf6a2 100755
--- a/routes/application.js
+++ b/routes/application.js
@@ -700,7 +700,7 @@ router.get('/list', block_access.isLoggedIn, function(req, res) {
// Get user project for clone url generation
let gitlabProjects = [];
- if(gitlabConf.doGit)
+ if(gitlabConf.doGit && req.session.gitlab && req.session.gitlab.user)
gitlabProjects = await gitlab.getAllProjects(req.session.gitlab.user.id);
for (var i = 0; i < projects.length; i++) {
diff --git a/routes/routes.js b/routes/routes.js
index fc78da93c..5b9d50a7f 100755
--- a/routes/routes.js
+++ b/routes/routes.js
@@ -352,9 +352,10 @@ router.post('/reset_password_form', block_access.loginAccess, function(req, res)
}
});
+ let gitlabUser = null;
// Update Gitlab password
if(gitlabConf.doGit){
- let gitlabUser = await gitlab.getUser(email_user);
+ gitlabUser = await gitlab.getUser(email_user);
if(!gitlabUser)
console.warn('Cannot update gitlab user password, user not found.');
@@ -373,10 +374,11 @@ router.post('/reset_password_form', block_access.loginAccess, function(req, res)
}
});
- return connectedUser;
+ return {connectedUser, gitlabUser};
- })().then(connectedUser => {
- req.login(connectedUser, err => {
+ })().then(infos => {
+
+ req.login(infos.connectedUser, err => {
if (err) {
console.error(err);
req.session.toastr = [{
@@ -385,6 +387,9 @@ router.post('/reset_password_form', block_access.loginAccess, function(req, res)
}];
res.redirect('/login');
} else {
+ req.session.gitlab = {
+ user: infos.gitlabUser
+ };
req.session.toastr = [{
message: "login.passwordReset",
level: "success"
diff --git a/services/bot.js b/services/bot.js
index 8998683a6..f5fc5a4ba 100644
--- a/services/bot.js
+++ b/services/bot.js
@@ -2814,29 +2814,29 @@ exports.complete = function (instruction) {
let answer = " ";
let valid = true;
- let letiable = false;
+ let variable = false;
while ((m < l) && (k < n) && (valid)) {
// Check if words are the same, goto next word
if (template[k] == "(.*)" || template[k] == instr[m]) {
- letiable = false;
+ variable = false;
k++;
} else {
// Check if beginning of word are the same
let sublen = instr[m].length;
if (template[k].substring(0, sublen) == instr[m]) {
// Do not increment k, we are still on keyword
- letiable = false;
+ variable = false;
} else {
- // If we parse the letiable value
+ // If we parse the variable value
if (template[k] == "(.*)") {
// Check next word
if (template[k + 1]) {
k++;
- letiable = true;
+ variable = true;
}
} else {
- // If we are not parsing a letiable, it means template is not appropriate => Exit
- if (!letiable)
+ // If we are not parsing a variable, it means template is not appropriate => Exit
+ if (!variable)
valid = false;
}
}
@@ -2857,12 +2857,12 @@ exports.complete = function (instruction) {
else {
if (template[k - 1] == "type")
answer = answer + "[type] ";
- // Return [letiable] to explain this is something dynamic
+ // Return [variable] to explain this is something dynamic
else
- answer = answer + "[letiable] ";
+ answer = answer + "[variable] ";
- // If first loop on letiable, we need to display possible end of instruction
- // Else, it means we have keyword at the beginning of suggestion, so we cut on letiable step
+ // If first loop on variable, we need to display possible end of instruction
+ // Else, it means we have keyword at the beginning of suggestion, so we cut on variable step
if (!firstLoop)
found = true;
}
diff --git a/services/designer.js b/services/designer.js
index bddcbd7a3..20b481d0f 100755
--- a/services/designer.js
+++ b/services/designer.js
@@ -1046,7 +1046,7 @@ exports.setFieldKnownAttribute = function (attr, callback) {
}).catch(function (err) {
if (typeof err.parent !== "undefined" && (err.parent.errno == 1062 || err.parent.code == 23505)) {
let err = new Error("structure.field.attributes.duplicateUnique");
- } else if(typeof err.parent !== "undefined" && (err.parent.errno == 1146 || err.parent.code == "42P01")){
+ } else if(typeof err.parent !== "undefined" && (err.parent.errno == 1146 || err.parent.code == "42P01" || err.parent.code == "3F000")){
// Handle case by Newmips, no worry about this one
if(['e_group', 'e_role', 'e_user'].indexOf(attr.name_data_entity) == -1 && attr.options.showValue == 'label'){
// Table do not exist - In case of script it's totally normal, just generate a warning
@@ -3336,6 +3336,7 @@ exports.createWidgetLastRecords = function (attr, callback) {
if (attr.columns[k].toLowerCase() == 'id') {
attr.columns[k] = {codeName: 'id', name: 'id', found:true};
kFound = true;
+ continue;
}
for (var i = 0; i < columns.length; i++) {
if (columns[i].codeName.indexOf('s_') == 0)
diff --git a/structure/pieces/administration/routes/e_user.js b/structure/pieces/administration/routes/e_user.js
index 6b75e80ef..83fc96db0 100644
--- a/structure/pieces/administration/routes/e_user.js
+++ b/structure/pieces/administration/routes/e_user.js
@@ -522,7 +522,8 @@ router.get('/set_status/:id_user/:status/:id_new_status', block_access.actionAcc
status_helper.setStatus('e_user', req.params.id_user, req.params.status, req.params.id_new_status, req.session.passport.user.id, req.query.comment).then(()=> {
res.redirect(req.headers.referer);
}).catch((err)=> {
- entity_helper.error(err, req, res, '/user/show?id=' + req.params.id_user, "e_user");
+ req.session.toastr.push({level: 'error', message: 'component.status.error.action_error'});
+ res.redirect(req.headers.referer);
});
});
diff --git a/structure/pieces/component/document_template/routes/e_document_template.js b/structure/pieces/component/document_template/routes/e_document_template.js
index cf4e663d3..48dcff29a 100644
--- a/structure/pieces/component/document_template/routes/e_document_template.js
+++ b/structure/pieces/component/document_template/routes/e_document_template.js
@@ -227,7 +227,8 @@ router.get('/set_status/:id_document_template/:status/:id_new_status', block_acc
status_helper.setStatus('e_document_template', req.params.id_document_template, req.params.status, req.params.id_new_status, req.session.passport.user.id, req.query.comment).then(() => {
res.redirect('/document_template/show?id=' + req.params.id_document_template);
}).catch((err) => {
- entity_helper.error(err, req, res, '/document_template/show?id=' + req.params.id_document_template);
+ req.session.toastr.push({level: 'error', message: 'component.status.error.action_error'});
+ res.redirect(req.headers.referer);
});
});
diff --git a/structure/pieces/component/status/locales/global_locales_FR.json b/structure/pieces/component/status/locales/global_locales_FR.json
index 7c6523a43..788d537da 100644
--- a/structure/pieces/component/status/locales/global_locales_FR.json
+++ b/structure/pieces/component/status/locales/global_locales_FR.json
@@ -3,7 +3,7 @@
"status": {
"error": {
"illegal_status": "Ce statut n'est pas valide.",
- "action_error": "Une ou plusieurs actions n'ont pas pu être éxecutée. Verifiez que les notifications sont activées et verifiez votre configuration mail."
+ "action_error": "Une ou plusieurs actions n'ont pas pu être executée. Verifiez que les notifications sont activées et verifiez votre configuration mail."
},
"next_status": "Statut suivant",
"available_status": "Statuts disponibles",
diff --git a/structure/pieces/component/status/models/e_media_notification.js b/structure/pieces/component/status/models/e_media_notification.js
index 01967e963..354ae8bbe 100644
--- a/structure/pieces/component/status/models/e_media_notification.js
+++ b/structure/pieces/component/status/models/e_media_notification.js
@@ -147,7 +147,7 @@ module.exports = (sequelize, DataTypes) => {
}
getGroupAndUserID().then(function(targetIds) {
- var entityUrl;
+ var entityUrl, notificationObj;
try {
try {
// Build show url of targeted entity
@@ -161,7 +161,7 @@ module.exports = (sequelize, DataTypes) => {
// Will redirect to current page
entityUrl = '#';
}
- var notificationObj = {
+ notificationObj = {
f_color: self.f_color,
f_icon: insertVariablesValue('f_icon'),
f_title: insertVariablesValue('f_title'),
diff --git a/structure/pieces/component/status/routes/e_action.js b/structure/pieces/component/status/routes/e_action.js
index 70d36817c..2dca4fd9a 100644
--- a/structure/pieces/component/status/routes/e_action.js
+++ b/structure/pieces/component/status/routes/e_action.js
@@ -372,7 +372,8 @@ router.get('/set_status/:id_action/:status/:id_new_status', block_access.actionA
status_helper.setStatus('e_action', req.params.id_action, req.params.status, req.params.id_new_status, req.session.passport.user.id, req.query.comment).then(()=> {
res.redirect('/action/show?id=' + req.params.id_action)
}).catch((err)=> {
- entity_helper.error(err, req, res, '/action/show?id=' + req.params.id_action);
+ req.session.toastr.push({level: 'error', message: 'component.status.error.action_error'});
+ res.redirect(req.headers.referer);
});
});
diff --git a/structure/pieces/component/status/routes/e_media.js b/structure/pieces/component/status/routes/e_media.js
index c97d0ab3a..94426a4db 100644
--- a/structure/pieces/component/status/routes/e_media.js
+++ b/structure/pieces/component/status/routes/e_media.js
@@ -280,7 +280,8 @@ router.get('/set_status/:id_media/:status/:id_new_status', block_access.actionAc
status_helper.setStatus('e_media', req.params.id_media, req.params.status, req.params.id_new_status, req.session.passport.user.id, req.query.comment).then(()=> {
res.redirect('/media/show?id=' + req.params.id_media);
}).catch((err)=> {
- entity_helper.error(err, req, res, '/media/show?id=' + req.params.id_media);
+ req.session.toastr.push({level: 'error', message: 'component.status.error.action_error'});
+ res.redirect(req.headers.referer);
});
});
diff --git a/structure/pieces/routes/data_entity.js b/structure/pieces/routes/data_entity.js
index 1e6c3fdaa..da8da5ff9 100755
--- a/structure/pieces/routes/data_entity.js
+++ b/structure/pieces/routes/data_entity.js
@@ -524,7 +524,8 @@ router.get('/set_status/:id_ENTITY_URL_NAME/:status/:id_new_status', block_acces
status_helper.setStatus('ENTITY_NAME', req.params.id_ENTITY_URL_NAME, req.params.status, req.params.id_new_status, req.session.passport.user.id, req.query.comment).then(()=> {
res.redirect(req.headers.referer);
}).catch(err => {
- entity_helper.error(err, req, res, '/ENTITY_URL_NAME/show?id=' + req.params.id_ENTITY_URL_NAME, "ENTITY_NAME");
+ req.session.toastr.push({level: 'error', message: 'component.status.error.action_error'});
+ res.redirect(req.headers.referer);
});
});
diff --git a/structure/structure_data_field.js b/structure/structure_data_field.js
index 33b0c3d67..1781ca923 100755
--- a/structure/structure_data_field.js
+++ b/structure/structure_data_field.js
@@ -397,10 +397,14 @@ function getFieldHtml(type, nameDataField, nameDataEntity, readOnly, file, value
str += " \n";
} else {
str += "
\n";
}
break;
@@ -413,7 +417,7 @@ function getFieldHtml(type, nameDataField, nameDataEntity, readOnly, file, value
str += " \n";
} else {
str += " \n";
}
break;
@@ -630,6 +634,7 @@ exports.setupDataField = function (attr, callback) {
case "mel" :
typeForModel = "STRING";
typeForDatalist = "email";
+ type_data_field = "email";
break;
case "phone" :
case "tel" :
diff --git a/structure/template/locales/en-EN.json b/structure/template/locales/en-EN.json
index 62269af5c..787aebd32 100755
--- a/structure/template/locales/en-EN.json
+++ b/structure/template/locales/en-EN.json
@@ -173,6 +173,7 @@
"question": "Are you sure you want to delete this entity ?"
},
"empty": "No data to display",
+ "empty_file": "No file",
"unique": "This field must be unique:",
"relatedtomanycheckbox_required": "A field requires you to check at least one checkbox."
},
diff --git a/structure/template/locales/fr-FR.json b/structure/template/locales/fr-FR.json
index 383e542aa..ff205ca9f 100755
--- a/structure/template/locales/fr-FR.json
+++ b/structure/template/locales/fr-FR.json
@@ -173,6 +173,7 @@
"question": "Êtes-vous sûr de vouloir supprimer cette entité ?"
},
"empty": "Aucune donnée à afficher",
+ "empty_file": "Aucun fichier",
"unique": "Ce champ doit être unique:",
"relatedtomanycheckbox_required": "Un champ necessite d'avoir au moins une case cochée."
},
diff --git a/structure/template/public/js/Newmips/dataTableBuilder.js b/structure/template/public/js/Newmips/dataTableBuilder.js
index 30c8672b7..1d6db05ae 100644
--- a/structure/template/public/js/Newmips/dataTableBuilder.js
+++ b/structure/template/public/js/Newmips/dataTableBuilder.js
@@ -416,7 +416,7 @@ function init_datatable(tableID, doPagination, context) {
valueFromArray = getValue(parts, row);
}
} else {
- // Has one sur une sous entité
+ // Has one relation field
let parts = columns[meta.col].data.split('.');
valueFromArray = getValue(parts, row);
}
@@ -440,7 +440,7 @@ function init_datatable(tableID, doPagination, context) {
if (typeof columns[meta.col].type != 'undefined') {
// date / datetime
if (columns[meta.col].type == 'date' || columns[meta.col].type == 'datetime') {
- if (cellValue != "" && cellValue != null && cellValue != "Invalid date" && cellValue != "Invalid Date") {
+ if (cellValue != null && cellValue != "" && cellValue.toLowerCase() != "invalid date") {
var tmpDate = moment(new Date(cellValue));
if (!tmpDate.isValid())
cellValue = '-';
@@ -484,6 +484,9 @@ function init_datatable(tableID, doPagination, context) {
// Get current entity by splitting current table id
var currentEntity = tableID.split("#table_")[1];
var justFilename = cellValue.replace(cellValue.split("_")[0], "").substring(1);
+ // Remove uuid
+ if(justFilename[32] == '_')
+ justFilename = justFilename.substring(33);
cellValue = ''+justFilename+'';
} else
cellValue = '';
@@ -609,7 +612,6 @@ function init_datatable(tableID, doPagination, context) {
}
]
}
- // Global search
table = $(tableID, context).DataTable(tableOptions);
//modal on click on picture cell
@@ -650,7 +652,6 @@ function init_datatable(tableID, doPagination, context) {
var mainTh = $(this);
var title = $(this).text();
- // Custom
var currentField = mainTh.data('field');
var val = getFilter(tableID.substring(1), currentField);
var search = '';
diff --git a/structure/template/public/js/newmips.js b/structure/template/public/js/newmips.js
index 85c37966b..ee207cf2d 100755
--- a/structure/template/public/js/newmips.js
+++ b/structure/template/public/js/newmips.js
@@ -425,7 +425,7 @@ function initForm(context) {
if (!confirm('Êtes-vous sûr de vouloir supprimer ce fichier ?'))
return false;
$.ajax({
- url: '/default/delete-file-ajax',
+ url: '/default/delete_file',
type: 'post',
data: {
dataEntity: that.attr("data-entity"),
diff --git a/structure/template/routes/default.js b/structure/template/routes/default.js
index e12601e37..8ac7a7b14 100755
--- a/structure/template/routes/default.js
+++ b/structure/template/routes/default.js
@@ -294,6 +294,11 @@ router.get('/get_picture', block_access.isLoggedIn, function (req, res) {
let entity = req.query.entity;
let filename = req.query.src;
let cleanFilename = filename.substring(16);
+
+ // Remove uuid
+ if(cleanFilename[32] == '_')
+ cleanFilename = cleanFilename.substring(33);
+
let folderName = filename.split("-")[0];
let filePath = globalConfig.localstorage + entity + '/' + folderName + '/' + filename;
@@ -322,6 +327,11 @@ router.get('/download', block_access.isLoggedIn, function (req, res) {
let entity = req.query.entity;
let filename = req.query.f;
let cleanFilename = filename.substring(16);
+
+ // Remove uuid
+ if(cleanFilename[32] == '_')
+ cleanFilename = cleanFilename.substring(33);
+
let folderName = filename.split("-")[0];
let filePath = globalConfig.localstorage + entity + '/' + folderName + '/' + filename;
@@ -345,37 +355,34 @@ router.get('/download', block_access.isLoggedIn, function (req, res) {
}
});
-router.post('/delete-file-ajax', block_access.isLoggedIn, function (req, res) {
- let entity = req.body.dataEntity;
- let dataStorage = req.body.dataStorage;
- let filename = req.body.filename;
- if (entity && dataStorage && filename) {
- let partOfFilepath = filename.split('-');
- if (partOfFilepath.length) {
- let base = partOfFilepath[0];
- let completeFilePath = globalConfig.localstorage + entity + '/' + base + '/' + filename;
- // thumbnail file to delete
- let completeThumbnailPath = globalConfig.localstorage + globalConfig.thumbnail.folder + entity + '/' + base + '/' + filename;
- fs.unlink(completeFilePath, function (err) {
- if (!err) {
- res.status(200).json({ message: 'message.delete.success'});
- fs.unlink(completeThumbnailPath, function (err) {
- if (err)
- console.error(err);
- });
- } else {
- req.session.toastr.push({level: 'error', message: "Internal error"});
- res.status(500).json({message: ''});
- }
- });
- } else {
- req.session.toastr.push({level: 'error', message: "File syntax not valid"});
- res.status(404).json({message: ''});
- }
+router.post('/delete_file', block_access.isLoggedIn, function (req, res) {
+ try {
+ let entity = req.body.dataEntity;
+ let filename = req.body.filename;
+ let cleanFilename = filename.substring(16);
+
+ // Remove uuid
+ if(cleanFilename[32] == '_')
+ cleanFilename = cleanFilename.substring(33);
+
+ let folderName = filename.split("-")[0];
+ let filePath = globalConfig.localstorage + entity + '/' + folderName + '/' + filename;
+
+ if (!block_access.entityAccess(req.session.passport.user.r_group, entity.substring(2)))
+ throw new Error("403 - Access forbidden");
+
+ if (!fs.existsSync(filePath))
+ throw new Error("404 - File not found: " + filePath);
- } else {
- req.session.toastr.push({level: 'error', message: "File not found"});
- res.status(400).json({message: 'Request parameters must be set'});
+ fs.unlinkSync(filePath);
+ res.status(200).send(true);
+ } catch (err) {
+ console.error(err);
+ req.session.toastr.push({
+ level: 'error',
+ message: "error.500.file"
+ });
+ res.status(500).send(err);
}
});
diff --git a/structure/template/server.js b/structure/template/server.js
index 70944db66..5c631a43a 100755
--- a/structure/template/server.js
+++ b/structure/template/server.js
@@ -350,24 +350,21 @@ models.sequelize.sync({logging: false, hooks: false}).then(() => {
if (!users || users.length == 0 || !hasAdmin) {
models.E_group.create({
- id: 1,
version: 0,
f_label: 'admin'
- }).then(function() {
+ }).then(group => {
models.E_role.create({
- id: 1,
version: 0,
f_label: 'admin'
- }).then(function() {
+ }).then(role => {
models.E_user.create({
- id: 1,
f_login: 'admin',
f_password: null,
f_enabled: 0,
version: 0
- }).then(function(user) {
- user.setR_role(1);
- user.setR_group(1);
+ }).then(user => {
+ user.setR_role(role.id);
+ user.setR_group(group.id);
});
});
});
diff --git a/structure/template/utils/dust_fn.js b/structure/template/utils/dust_fn.js
index 037c81884..eeab289a0 100644
--- a/structure/template/utils/dust_fn.js
+++ b/structure/template/utils/dust_fn.js
@@ -144,8 +144,13 @@ module.exports = {
dust.filters.filename = function(value) {
// Remove datetime part from filename display
- if (moment(value.substring(0,16), 'YYYYMMDD-HHmmss_').isValid() && value != "" && value.length > 16)
- return value.substring(16);
+ if (moment(value.substring(0, 16), 'YYYYMMDD-HHmmss_').isValid() && value != "" && value.length > 16)
+ value = value.substring(16);
+
+ // Remove uuid
+ if(value[32] == '_')
+ value = value.substring(33);
+
return value;
};
diff --git a/structure/template/utils/status_helper.js b/structure/template/utils/status_helper.js
index e984b640a..762220dac 100644
--- a/structure/template/utils/status_helper.js
+++ b/structure/template/utils/status_helper.js
@@ -56,7 +56,7 @@ module.exports = {
fullEntityFieldTree: function (entity, alias = entity) {
let genealogy = [];
// Create inner function to use genealogy globaly
- function loadTree(entity, alias) {
+ function loadTree(entity, alias, depth = 0) {
let fieldTree = {
entity: entity,
alias: alias,
@@ -66,9 +66,10 @@ module.exports = {
file_fields: [],
children: []
}
+ let entityFields, entityAssociations;
try {
- let entityFields = JSON.parse(fs.readFileSync(__dirname+'/../models/attributes/'+entity+'.json'));
- let entityAssociations = JSON.parse(fs.readFileSync(__dirname+'/../models/options/'+entity+'.json'));
+ entityFields = JSON.parse(fs.readFileSync(__dirname+'/../models/attributes/'+entity+'.json'));
+ entityAssociations = JSON.parse(fs.readFileSync(__dirname+'/../models/options/'+entity+'.json'));
} catch (e) {
console.error(e);
return fieldTree;
@@ -86,39 +87,124 @@ module.exports = {
}
// Check if current entity has already been built in this branch of the tree to avoid infinite loop
- let foundGenealogy = genealogy.filter(x => x.entity == entity);
- // Entity already proceeded in an other relation
- if(foundGenealogy.length != 0){
- // Check for the better depth, if deeper then remove it to keep the closer one
- if(foundGenealogy[0].depth > depth)
- genealogy = genealogy.filter(x => x.entity != entity); // Remove old one
- else
- return fieldTree;
- }
+ for (const [idx, genealogyBranch] of genealogy.entries())
+ if (genealogyBranch.entity == entity) {
+ // Keep smallest depth
+ if (genealogyBranch.depth > depth)
+ genealogy.splice(idx, 1);
+ else
+ return fieldTree;
+ }
genealogy.push({
entity: entity,
depth: depth
});
- let initalDepth = depth;
-
// Building children array
- for (let i = 0; i < entityAssociations.length; i++){
+ for (let i = 0; i < entityAssociations.length; i++) {
// Do not include history & status table in field list
- if(entityAssociations[i].target.indexOf("e_history_e_") == -1
- && entityAssociations[i].target.indexOf("e_status") == -1){
- depth++;
- fieldTree.children.push(loadTree(entityAssociations[i].target, entityAssociations[i].as));
- }
+ if(entityAssociations[i].target.indexOf("e_history_e_") == -1 && entityAssociations[i].target.indexOf("e_status") == -1 && entityAssociations[i].structureType !== 'auto_generate')
+ fieldTree.children.push(loadTree(entityAssociations[i].target, entityAssociations[i].as, depth+1));
}
- depth = initalDepth;
-
return fieldTree;
}
return loadTree(entity, alias);
},
+ // Build array of fields for media sms/notification/email insertion