Skip to content

Commit

Permalink
Facilitation of Collaborative Work (#1863)
Browse files Browse the repository at this point in the history
* Any user (not tester) can create an organization
* isUserOwner unified
* only study owner can "Edit Access Level"
* Allow sharing service with everyone
* default thumbnail if null
  • Loading branch information
odeimaiz authored Oct 7, 2020
1 parent acf3f6d commit 981bc8d
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ qx.Class.define("osparc.component.export.Permissions", {
/**
* @param serializedData {Object} Object containing the Serialized Data
*/
construct: function(serializedData) {
construct: function(serializedData, initCollabs = []) {
this.base(arguments);

this.__serializedData = serializedData;
Expand All @@ -31,7 +31,11 @@ qx.Class.define("osparc.component.export.Permissions", {

this.__buildLayout();

this.__getMyFriends();
this.__collaborators = {};
initCollabs.forEach(initCollab => {
this.__collaborators[initCollab["gid"]] = initCollab;
});
this.__getCollaborators();
},

statics: {
Expand All @@ -58,7 +62,7 @@ qx.Class.define("osparc.component.export.Permissions", {
__serializedData: null,
__organizationsAndMembers: null,
__collaboratorsModel: null,
__myFrieds: null,
__collaborators: null,
__addCollaboratorBtn: null,

__buildLayout: function() {
Expand Down Expand Up @@ -128,12 +132,12 @@ qx.Class.define("osparc.component.export.Permissions", {
bindItem: (ctrl, item, id) => {
ctrl.bindProperty("gid", "model", null, item, id);
ctrl.bindProperty("gid", "key", null, item, id);
ctrl.bindProperty("collabType", "collabType", null, item, id);
ctrl.bindProperty("thumbnail", "thumbnail", null, item, id);
ctrl.bindProperty("name", "title", null, item, id); // user
ctrl.bindProperty("label", "title", null, item, id); // organization
ctrl.bindProperty("login", "subtitle", null, item, id); // user
ctrl.bindProperty("description", "subtitle", null, item, id); // organization
ctrl.bindProperty("isOrg", "isOrganization", null, item, id);
ctrl.bindProperty("accessRights", "accessRights", null, item, id);
ctrl.bindProperty("showOptions", "showOptions", null, item, id);
},
Expand All @@ -159,9 +163,7 @@ qx.Class.define("osparc.component.export.Permissions", {
return vBox;
},

__getMyFriends: function() {
this.__myFrieds = {};

__getCollaborators: function() {
const store = osparc.store.Store.getInstance();
const promises = [];
promises.push(store.getGroupsOrganizations());
Expand All @@ -171,13 +173,13 @@ qx.Class.define("osparc.component.export.Permissions", {
const orgs = values[0];
const orgMembers = values[1];
orgs.forEach(org => {
org["isOrg"] = true;
this.__myFrieds[org["gid"]] = org;
org["collabType"] = 1;
this.__collaborators[org["gid"]] = org;
});
for (const gid of Object.keys(orgMembers)) {
const orgMember = orgMembers[gid];
orgMember["isOrg"] = false;
this.__myFrieds[gid] = orgMember;
orgMember["collabType"] = 2;
this.__collaborators[gid] = orgMember;
}
this.__reloadOrganizationsAndMembers();
this.__reloadCollaboratorsList();
Expand All @@ -188,17 +190,29 @@ qx.Class.define("osparc.component.export.Permissions", {
this.__organizationsAndMembers.reset();

const aceessRights = this.__getAccessRights();
const myFriends = Object.values(this.__myFrieds);
const myFriends = Object.values(this.__collaborators);

// sort them first
myFriends.sort((a, b) => (a["label"] > b["label"]) ? 1 : -1);
myFriends.sort((a, b) => (a["isOrg"] && !b["isOrg"]) ? -1 : 1);
myFriends.sort((a, b) => (a["collabType"] > b["collabType"]) ? 1 : -1);

myFriends.forEach(myFriend => {
const gid = myFriend["gid"];
if (parseInt(gid) !== osparc.auth.Data.getInstance().getGroupId() && !(parseInt(gid) in aceessRights)) {
const btn = this.__organizationsAndMembers.addOption(myFriend);
btn.setIcon(myFriend["isOrg"] ? "@FontAwesome5Solid/users/14" : "@FontAwesome5Solid/user/14");
let iconPath = null;
switch (myFriend["collabType"]) {
case 0:
iconPath = "@FontAwesome5Solid/globe/14";
break;
case 1:
iconPath = "@FontAwesome5Solid/users/14";
break;
case 2:
iconPath = "@FontAwesome5Solid/user/14";
break;
}
btn.setIcon(iconPath);
}
});
},
Expand All @@ -208,8 +222,8 @@ qx.Class.define("osparc.component.export.Permissions", {

const aceessRights = this.__getAccessRights();
Object.keys(aceessRights).forEach(gid => {
if (Object.prototype.hasOwnProperty.call(this.__myFrieds, gid)) {
const collaborator = this.__myFrieds[gid];
if (Object.prototype.hasOwnProperty.call(this.__collaborators, gid)) {
const collaborator = this.__collaborators[gid];
if ("first_name" in collaborator) {
collaborator["thumbnail"] = osparc.utils.Avatar.getUrl(collaborator["login"], 32);
collaborator["name"] = osparc.utils.Utils.firstsUp(collaborator["first_name"], collaborator["last_name"]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ qx.Class.define("osparc.component.export.ServicePermissions", {
construct: function(serviceData) {
this.__serviceData = osparc.utils.Utils.deepCloneObject(serviceData);

this.base(arguments, this.__serviceData);
const initCollabs = this.self().getEveryoneObj();
this.base(arguments, this.__serviceData, [initCollabs]);
},

events: {
Expand All @@ -57,6 +58,17 @@ qx.Class.define("osparc.component.export.ServicePermissions", {

removeCollaborator: function(serializedData, gid) {
return delete serializedData["access_rights"][gid];
},

getEveryoneObj: function() {
return {
"gid": 1,
"label": "Everyone",
"description": "",
"thumbnail": null,
"accessRights": this.getCollaboratorAccessRight(),
"collabType": 0
};
}
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,7 @@ qx.Class.define("osparc.component.export.StudyPermissions", {
__studyData: null,

_isUserOwner: function() {
const myGid = osparc.auth.Data.getInstance().getGroupId();
const aceessRights = this.__studyData["accessRights"];
if (myGid in aceessRights) {
return aceessRights[myGid]["delete"];
}
return false;
return osparc.data.model.Study.isOwner(this.__studyData);
},

_addCollaborator: function() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ qx.Class.define("osparc.component.metadata.StudyDetailsEditor", {
},

__createButtons: function(isTemplate) {
const isCurrentUserOwner = this.__isUserOwner();
const isCurrentUserOwner = osparc.data.model.Study.isOwner(this.__studyData);
const canUpdateTemplate = osparc.data.Permissions.getInstance().canDo("studies.template.update");

const buttonsToolbar = new qx.ui.toolbar.ToolBar();
Expand All @@ -106,7 +106,7 @@ qx.Class.define("osparc.component.metadata.StudyDetailsEditor", {
},

__createEditView: function(isTemplate) {
const isCurrentUserOwner = this.__isUserOwner();
const isCurrentUserOwner = osparc.data.model.Study.isOwner(this.__studyData);
const canUpdateTemplate = osparc.data.Permissions.getInstance().canDo("studies.template.update");
const fieldIsEnabled = isCurrentUserOwner && (!isTemplate || canUpdateTemplate);

Expand Down Expand Up @@ -282,13 +282,6 @@ qx.Class.define("osparc.component.metadata.StudyDetailsEditor", {
this.__stack.setSelection([this.__editView]);
break;
}
},

__isUserOwner: function() {
if (this.__studyData) {
return this.__studyData.prjOwner === osparc.auth.Data.getInstance().getEmail();
}
return false;
}
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ qx.Class.define("osparc.component.node.BaseNodeView", {
},

__buildToolbar: function() {
const study = osparc.store.Store.getInstance().getCurrentStudy();

const toolbar = this.__toolbar = new qx.ui.toolbar.ToolBar();
const titlePart = new qx.ui.toolbar.Part();
const infoPart = new qx.ui.toolbar.Part();
Expand All @@ -222,7 +224,6 @@ qx.Class.define("osparc.component.node.BaseNodeView", {
if (node) {
node.renameNode(evt.getData());
}
const study = osparc.store.Store.getInstance().getCurrentStudy();
qx.event.message.Bus.getInstance().dispatchByName("updateStudy", study.serializeStudy());
}
}, this);
Expand All @@ -232,8 +233,8 @@ qx.Class.define("osparc.component.node.BaseNodeView", {
infoBtn.addListener("execute", () => this.__openServiceDetails(), this);
infoPart.add(infoBtn);

if (osparc.data.Permissions.getInstance().canDo("study.node.update")) {
const editAccessLevel = new qx.ui.toolbar.Button(this.tr("Edit Access Level"));
if (osparc.data.Permissions.getInstance().canDo("study.node.update") && osparc.data.model.Study.isOwner(study)) {
const editAccessLevel = new qx.ui.toolbar.Button(this.tr("Edit Access Level"), "@FontAwesome5Solid/edit/14");
editAccessLevel.addListener("execute", () => this._openEditAccessLevel(), this);
infoPart.add(editAccessLevel);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ qx.Class.define("osparc.dashboard.CollaboratorListItem", {
},

properties: {
isOrganization: {
check: "Boolean",
event: "changeIsOrganization",
collabType: {
check: [0, 1, 2],
event: "changeCollabType",
nullable: true
},

Expand Down Expand Up @@ -76,6 +76,25 @@ qx.Class.define("osparc.dashboard.CollaboratorListItem", {
return control || this.base(arguments, id);
},

// overriden
_applyThumbnail: function(value) {
if (value === null) {
const collabType = this.getCollabType();
switch (collabType) {
case 0:
value = "@FontAwesome5Solid/globe/28";
break;
case 1:
value = "@FontAwesome5Solid/users/28";
break;
case 2:
value = "@FontAwesome5Solid/user/28";
break;
}
}
this.base(arguments, value);
},

_applyAccessRights: function(value) {
if (value === null) {
return;
Expand Down Expand Up @@ -108,7 +127,7 @@ qx.Class.define("osparc.dashboard.CollaboratorListItem", {
});

const accessRights = this.getAccessRights();
if (!osparc.component.export.Permissions.canDelete(accessRights) && !this.getIsOrganization()) {
if (!osparc.component.export.Permissions.canDelete(accessRights) && this.getCollabType() === 2) {
const makeOwnerButton = new qx.ui.menu.Button(this.tr("Make Owner"));
makeOwnerButton.addListener("execute", () => {
this.fireDataEvent("promoteCollaborator", {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,14 +416,14 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
if (this.self().isTemplate(study)) {
item.set({
uuid: study.uuid,
creator: study.prjOwner ? study.prjOwner : "",
owner: study.prjOwner ? study.prjOwner : "",
accessRights: study.accessRights ? study.accessRights : {},
icon: study.thumbnail ? study.thumbnail : "@FontAwesome5Solid/copy/50"
});
} else if (this.self().isService(study)) {
item.set({
uuid: study.key,
creator: study.owner ? study.owner : "",
owner: study.owner ? study.owner : "",
accessRights: study.access_rights ? study.access_rights : {},
icon: study.thumbnail ? study.thumbnail : "@FontAwesome5Solid/paw/50"
});
Expand Down Expand Up @@ -673,10 +673,10 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
},

__isUserOwner: function(studyData) {
const myEmail = osparc.auth.Data.getInstance().getEmail();
if (this.self().isTemplate(studyData)) {
return studyData.prjOwner === myEmail;
return osparc.data.model.Study.isOwner(studyData);
} else if (this.self().isService(studyData)) {
const myEmail = osparc.auth.Data.getInstance().getEmail();
return studyData.owner === myEmail;
}
return false;
Expand Down
14 changes: 2 additions & 12 deletions services/web/client/source/class/osparc/dashboard/StudyBrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
uuid: study.uuid,
studyTitle: study.name,
studyDescription: study.description,
creator: study.prjOwner ? study.prjOwner : null,
owner: study.prjOwner ? study.prjOwner : null,
accessRights: study.accessRights ? study.accessRights : null,
lastChangeDate: study.lastChangeDate ? new Date(study.lastChangeDate) : null,
icon: study.thumbnail || defaultThumbnail,
Expand Down Expand Up @@ -436,7 +436,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
const studyServicesButton = this.__getStudyServicesMenuButton(studyData);
menu.add(studyServicesButton);

const isCurrentUserOwner = this.__isUserOwner(studyData);
const isCurrentUserOwner = osparc.data.model.Study.isOwner(studyData);
const canCreateTemplate = osparc.data.Permissions.getInstance().canDo("studies.template.create");
if (isCurrentUserOwner && canCreateTemplate) {
const saveAsTemplateButton = this.__getSaveAsTemplateMenuButton(studyData);
Expand Down Expand Up @@ -658,16 +658,6 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
__createConfirmWindow: function(isMulti) {
const msg = isMulti ? this.tr("Are you sure you want to delete the studies?") : this.tr("Are you sure you want to delete the study?");
return new osparc.ui.window.Confirmation(msg);
},

__isUserOwner: function(studyData) {
const myEmail = osparc.auth.Data.getInstance().getEmail();
if ("prjOwner" in studyData) {
return studyData.prjOwner === myEmail;
} else if ("getCreator" in studyData) {
return studyData.getCreator() === myEmail;
}
return false;
}
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ qx.Class.define("osparc.dashboard.StudyBrowserButtonItem", {
nullable: true
},

creator: {
owner: {
check: "String",
apply: "_applyCreator",
apply: "_applyOwner",
nullable: true
},

Expand Down Expand Up @@ -266,7 +266,7 @@ qx.Class.define("osparc.dashboard.StudyBrowserButtonItem", {
}
},

_applyCreator: function(value, old) {
_applyOwner: function(value, old) {
if (this.isResourceType("service") || this.isResourceType("template")) {
const label = this.getChildControl("description2");
label.setValue(value);
Expand Down Expand Up @@ -413,7 +413,7 @@ qx.Class.define("osparc.dashboard.StudyBrowserButtonItem", {
if (text) {
const checks = [
this.getStudyTitle(),
this.getCreator()
this.getOwner()
];
if (checks.filter(label => label.toLowerCase().trim().includes(text)).length == 0) {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ qx.Class.define("osparc.data.Permissions", {
"user.token.create",
"user.token.delete",
"user.tag",
"user.organizations.create",
"study.node.create",
"study.node.delete",
"study.node.update",
Expand All @@ -162,7 +163,6 @@ qx.Class.define("osparc.data.Permissions", {
"studies.template.create.all",
"services.all.read",
"user.role.update",
"user.organizations.create",
"study.nodestree.uuid.read",
"study.filestree.uuid.read",
"study.logger.debug.read",
Expand Down
13 changes: 13 additions & 0 deletions services/web/client/source/class/osparc/data/model/Study.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,19 @@ qx.Class.define("osparc.data.model.Study", {
return true;
}
return false;
},

isOwner: function(studyData) {
if (studyData instanceof osparc.data.model.Study) {
const myEmail = osparc.auth.Data.getInstance().getEmail();
return studyData.getPrjOwner() === myEmail;
}
const myGid = osparc.auth.Data.getInstance().getGroupId();
const aceessRights = studyData["accessRights"];
if (myGid in aceessRights) {
return aceessRights[myGid]["delete"];
}
return false;
}
},

Expand Down

0 comments on commit 981bc8d

Please sign in to comment.