Fix several minor security bugs.

This commit is contained in:
Paulo Gustavo Veiga 2012-06-12 22:33:51 -03:00
parent cbdd6dd146
commit c4d2acec7b
3 changed files with 165 additions and 128 deletions

View File

@ -24,7 +24,7 @@ public class RestCollaboration {
public RestCollaboration(@NotNull Collaboration collaboration) { public RestCollaboration(@NotNull Collaboration collaboration) {
this.email = collaboration.getCollaborator().getEmail(); this.email = collaboration.getCollaborator().getEmail();
this.role = collaboration.getRole().name(); this.role = collaboration.getRole().getLabel();
} }
public RestCollaboration() { public RestCollaboration() {

View File

@ -166,12 +166,16 @@ public class MindmapServiceImpl
mindmap.getCollaborations().add(collaboration); mindmap.getCollaborations().add(collaboration);
mindmapManager.saveMindmap(mindmap); mindmapManager.saveMindmap(mindmap);
try {
// Sent collaboration email ... // Sent collaboration email ...
final Map<String, Object> model = new HashMap<String, Object>(); final Map<String, Object> model = new HashMap<String, Object>();
model.put("role", role); model.put("role", role);
model.put("map", mindmap); model.put("map", mindmap);
model.put("message", "message"); model.put("message", "message");
mailer.sendEmail(mailer.getSiteEmail(), email, "Collaboration", model, "newColaborator.vm"); mailer.sendEmail(mailer.getSiteEmail(), email, "Collaboration", model, "newColaborator.vm");
} catch (Exception e) {
e.printStackTrace();
}
} else if (collaboration.getRole() != role) { } else if (collaboration.getRole() != role) {
// If the relationship already exists and the role changed then only update the role // If the relationship already exists and the role changed then only update the role

View File

@ -28,6 +28,11 @@
<div id="sharingContainer"> <div id="sharingContainer">
<table class="table" id="collabsTable"> <table class="table" id="collabsTable">
<colgroup>
<col width="70%"/>
<col width="20%"/>
<col width="10%"/>
</colgroup>
</table> </table>
</div> </div>
@ -51,19 +56,25 @@
<script type="text/javascript"> <script type="text/javascript">
$("#errorMsg").hide(); $("#errorMsg").hide();
var messages = {
owner: 'Is owner',
editor: 'Can edit',
viewer: 'Can view'};
function onClickShare(aElem) { function onClickShare(aElem) {
var role = $(aElem).attr('data-role'); var role = $(aElem).attr('data-role');
var roleDec = role == 'viewer' ? "Can view" : "Can edit"; var roleDec = messages[role];
var btnElem = $(aElem).parent().parent().parent().find(".dropdown-toggle"); var btnElem = $(aElem).parent().parent().parent().find(".dropdown-toggle");
btnElem.text(roleDec).append(' <span class="caret"> </span>'); btnElem.text(roleDec).append(' <span class="caret"> </span>');
return role; return role;
} }
function addCollaboration(email, role) { function addCollaboration(email, role) {
// Add row to the table ... var rowStr;
var tableElem = $("#collabsTable"); var tableElem = $("#collabsTable");
if (role != "owner") {
// Add row to the table ...
var rowTemplate = '\ var rowTemplate = '\
<tr data-collab="{email}" data-role="{role}">\ <tr data-collab="{email}" data-role="{role}">\
<td>{email}</td>\ <td>{email}</td>\
@ -71,21 +82,22 @@
<div class="btn-group">\ <div class="btn-group">\
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#""></a>\ <a class="btn dropdown-toggle" data-toggle="dropdown" href="#""></a>\
<ul class="dropdown-menu">\ <ul class="dropdown-menu">\
<li><a href="#" data-role="editor">Can edit</a></li>\ <li><a href="#" data-role="editor">' + messages['editor'] + '</a></li>\
<li><a href="#" data-role="viewer">Can view</a></li>\ <li><a href="#" data-role="viewer">' + messages['viewer'] + '</a></li>\
</ul>\ </ul>\
</div>\ </div>\
</td>\ </td>\
<td><a href="#">x</a></td>\ <td><a href="#">x</a></td>\
</tr>'; </tr>';
var rowStr = rowTemplate.replace(/{email}/g, email); rowStr = rowTemplate.replace(/{email}/g, email);
rowStr = rowStr.replace(/{role}/g, role); rowStr = rowStr.replace(/{role}/g, role);
var elem = tableElem.append(rowStr); var elem = tableElem.append(rowStr);
// Register change role event ... // Register change role event ...
var rowElem = $("#collabsTable tr:last"); var rowElem = $("#collabsTable tr:last");
$(rowElem.find(".dropdown-menu a").click(function() { $(rowElem.find(".dropdown-menu a").click(function() {
reportError(null);
var role = onClickShare(this); var role = onClickShare(this);
rowElem.attr('data-role', role); rowElem.attr('data-role', role);
event.preventDefault(); event.preventDefault();
@ -94,26 +106,40 @@
// Register remove event ... // Register remove event ...
rowElem.find("td:last a").click(function(event) { rowElem.find("td:last a").click(function(event) {
reportError(null);
var email = rowElem.attr('data-collab'); var email = rowElem.attr('data-collab');
removeCollab(email); removeCollab(email);
event.preventDefault(); event.preventDefault();
}); });
} } else {
rowStr = '<tr data-collab=' + email + ' data-role="' + role + '">\
<td>' + email + ' (You)</td>\
<td><button class="btn btn-secondary">' + messages[role] + '</button></td>\
<td></td>\
</tr>';
tableElem.append(rowStr);
var removeCollab = function(email) { }
}
var removeCollab = function(email) {
// Remove html entry ... // Remove html entry ...
$('#collabsTable tr[data-collab="' + email + '"]').detach(); $('#collabsTable tr[data-collab="' + email + '"]').detach();
}; };
$(function() { $(function() {
jQuery.ajax("service/maps/${mindmap.id}/collabs", { jQuery.ajax("service/maps/${mindmap.id}/collabs", {
async:false, async:false,
dataType: 'json', dataType: 'json',
type: 'GET', type: 'GET',
contentType:"text/plain", contentType:"text/plain",
success : function(data, textStatus, jqXHR) { success : function(data, textStatus, jqXHR) {
// Init table will all values ... // Owner roles is the first in the table ...
var collabs = data.collaborations; var collabs = data.collaborations.sort(function(a, b) {
return a.role > b.role;
});
// Add all the colums in the table ...
for (var i = 0; i < collabs.length; i++) { for (var i = 0; i < collabs.length; i++) {
var collab = collabs[i]; var collab = collabs[i];
addCollaboration(collab.email, collab.role); addCollaboration(collab.email, collab.role);
@ -124,15 +150,14 @@
alert(textStatus); alert(textStatus);
} }
}); });
}); });
$("#addBtn").click(function(event) { $("#addBtn").click(function(event) {
var i,email; var i,email;
var emailsStr = $("#collabEmails").val(); var emailsStr = $("#collabEmails").val();
var role = $("#shareRole").attr('data-role'); var role = $("#shareRole").attr('data-role');
// Clear previous state ... reportError(null);
$("#errorMsg").text("").hide();
// Split emails ... // Split emails ...
var valid = true; var valid = true;
@ -150,10 +175,11 @@
} }
// Is there a collab with the same email ? // Is there a collab with the same email ?
var useExists = jQuery.grep(model, var useExists = jQuery.grep(model.collaborations,
function(val) { function(val) {
return val.email == email; return val.email.trim() == email.trim();
}).length > 0; }).length > 0;
if (useExists) { if (useExists) {
reportError(email + " is already in the shared list"); reportError(email + " is already in the shared list");
valid = false; valid = false;
@ -176,27 +202,31 @@
} else { } else {
} }
}); });
// Register change event ... // Register change event ...
$("#shareRole a").click(function() { $("#shareRole a").click(function() {
var role = onClickShare(this); var role = onClickShare(this);
$(this).parent().attr('data-role', role); $(this).parent().attr('data-role', role);
event.preventDefault(); event.preventDefault();
}); });
function isValidEmailAddress(emailAddress) { function isValidEmailAddress(emailAddress) {
var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i); var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
return pattern.test(emailAddress); return pattern.test(emailAddress);
} }
function reportError(msg) { function reportError(msg) {
if (msg) {
$('#errorMsg').show(); $('#errorMsg').show();
$('#errorMsg').append("<p>" + msg + "</p>"); $('#errorMsg').append("<p>" + msg + "</p>");
} else {
$("#errorMsg").text("").hide();
} }
}
function buildCollabModel() { function buildCollabModel() {
var collabs = $('#collabsTable tr').map(function() { var collabs = $('#collabsTable tr').map(function() {
return { return {
email: $(this).attr('data-collab'), email: $(this).attr('data-collab'),
@ -209,26 +239,29 @@
count:collabs.length, count:collabs.length,
collaborations:collabs collaborations:collabs
}; };
} }
// Hook for interaction with the main parent window ... // Hook for interaction with the main parent window ...
var submitDialogForm = function() { var submitDialogForm = function() {
var collabs = buildCollabModel();
collabs.collaborations = jQuery.grep(collabs.collaborations, function() {
return this.role != 'owner';
});
console.log(buildCollabModel());
jQuery.ajax("service/maps/${mindmap.id}/collabs", { jQuery.ajax("service/maps/${mindmap.id}/collabs", {
async:false, async:false,
dataType: 'json', dataType: 'json',
type: 'PUT', type: 'PUT',
data: JSON.stringify(buildCollabModel()), data: JSON.stringify(collabs),
contentType:"application/json", contentType:"application/json",
success : function(data, textStatus, jqXHR) { success : function(data, textStatus, jqXHR) {
$('#share-dialog-modal').modal('hide');
}, },
error: function(jqXHR, textStatus, errorThrown) { error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus); reportError(textStatus);
} }
}); });
} }
</script> </script>