Skip to content

Commit fd5255e

Browse files
authored
Merge branch 'master' into pr-osparc-login-director-v2
2 parents 1e767df + d443f36 commit fd5255e

File tree

22 files changed

+526
-89
lines changed

22 files changed

+526
-89
lines changed

packages/service-library/src/servicelib/rabbitmq/rpc_interfaces/webserver/functions/functions_rpc_interface.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
from typing import Literal
23

34
from models_library.api_schemas_webserver import WEBSERVER_RPC_NAMESPACE
45
from models_library.api_schemas_webserver.functions import (
@@ -18,6 +19,7 @@
1819
)
1920
from models_library.functions import (
2021
FunctionClass,
22+
FunctionGroupAccessRights,
2123
FunctionJobStatus,
2224
FunctionOutputs,
2325
FunctionUserAccessRights,
@@ -418,6 +420,7 @@ async def update_function_job_status(
418420
product_name: ProductName,
419421
function_job_id: FunctionJobID,
420422
job_status: FunctionJobStatus,
423+
check_write_permissions: bool = True,
421424
) -> FunctionJobStatus:
422425
result = await rabbitmq_rpc_client.request(
423426
WEBSERVER_RPC_NAMESPACE,
@@ -426,6 +429,7 @@ async def update_function_job_status(
426429
job_status=job_status,
427430
user_id=user_id,
428431
product_name=product_name,
432+
check_write_permissions=check_write_permissions,
429433
)
430434
return TypeAdapter(FunctionJobStatus).validate_python(result)
431435

@@ -438,6 +442,7 @@ async def update_function_job_outputs(
438442
product_name: ProductName,
439443
function_job_id: FunctionJobID,
440444
outputs: FunctionOutputs,
445+
check_write_permissions: bool = True,
441446
) -> FunctionOutputs:
442447
result = await rabbitmq_rpc_client.request(
443448
WEBSERVER_RPC_NAMESPACE,
@@ -446,6 +451,7 @@ async def update_function_job_outputs(
446451
outputs=outputs,
447452
user_id=user_id,
448453
product_name=product_name,
454+
check_write_permissions=check_write_permissions,
449455
)
450456
return TypeAdapter(FunctionOutputs).validate_python(result)
451457

@@ -578,3 +584,37 @@ async def get_functions_user_api_access_rights(
578584
product_name=product_name,
579585
)
580586
return TypeAdapter(FunctionUserApiAccessRights).validate_python(result)
587+
588+
589+
@log_decorator(_logger, level=logging.DEBUG)
590+
async def set_group_permissions(
591+
rabbitmq_rpc_client: RabbitMQRPCClient,
592+
*,
593+
user_id: UserID,
594+
product_name: ProductName,
595+
object_type: Literal["function", "function_job", "function_job_collection"],
596+
object_ids: list[FunctionID | FunctionJobID | FunctionJobCollectionID],
597+
permission_group_id: int,
598+
read: bool | None = None,
599+
write: bool | None = None,
600+
execute: bool | None = None,
601+
) -> list[
602+
tuple[
603+
FunctionID | FunctionJobID | FunctionJobCollectionID, FunctionGroupAccessRights
604+
]
605+
]:
606+
result = await rabbitmq_rpc_client.request(
607+
WEBSERVER_RPC_NAMESPACE,
608+
TypeAdapter(RPCMethodName).validate_python("set_group_permissions"),
609+
user_id=user_id,
610+
product_name=product_name,
611+
object_type=object_type,
612+
object_ids=object_ids,
613+
permission_group_id=permission_group_id,
614+
read=read,
615+
write=write,
616+
execute=execute,
617+
)
618+
return TypeAdapter(
619+
list[tuple[FunctionID | FunctionJobID, FunctionGroupAccessRights]]
620+
).validate_python(result)

services/api-server/src/simcore_service_api_server/_service_function_jobs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ async def inspect_function_job(
203203
user_id=self.user_id,
204204
product_name=self.product_name,
205205
job_status=new_job_status,
206+
check_write_permissions=False,
206207
)
207208

208209
async def create_function_job_inputs( # pylint: disable=no-self-use
@@ -529,4 +530,5 @@ async def function_job_outputs(
529530
user_id=user_id,
530531
product_name=product_name,
531532
outputs=new_outputs,
533+
check_write_permissions=False,
532534
)

services/api-server/src/simcore_service_api_server/api/routes/functions_routes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ async def _run_single_function(function_inputs: FunctionInputs) -> FunctionJobID
474474
for function_inputs in function_inputs_list
475475
],
476476
reraise=False,
477-
limit=10,
477+
limit=1,
478478
)
479479

480480
# Check if any tasks raised exceptions and raise the first one found

services/api-server/src/simcore_service_api_server/services_rpc/wb_api_server.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,13 +587,15 @@ async def update_function_job_status(
587587
user_id: UserID,
588588
product_name: ProductName,
589589
job_status: FunctionJobStatus,
590+
check_write_permissions: bool = True,
590591
) -> FunctionJobStatus:
591592
return await functions_rpc_interface.update_function_job_status(
592593
self._client,
593594
function_job_id=function_job_id,
594595
user_id=user_id,
595596
product_name=product_name,
596597
job_status=job_status,
598+
check_write_permissions=check_write_permissions,
597599
)
598600

599601
async def update_function_job_outputs(
@@ -603,13 +605,15 @@ async def update_function_job_outputs(
603605
user_id: UserID,
604606
product_name: ProductName,
605607
outputs: FunctionOutputs,
608+
check_write_permissions: bool = True,
606609
) -> FunctionOutputs:
607610
return await functions_rpc_interface.update_function_job_outputs(
608611
self._client,
609612
function_job_id=function_job_id,
610613
user_id=user_id,
611614
product_name=product_name,
612615
outputs=outputs,
616+
check_write_permissions=check_write_permissions,
613617
)
614618

615619
async def find_cached_function_jobs(

services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,20 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
121121

122122
const walletsEnabled = osparc.desktop.credits.Utils.areWalletsEnabled();
123123
if (walletsEnabled) {
124-
osparc.store.Study.getInstance().getWallet(studyId)
125-
.then(wallet => {
124+
Promise.all([
125+
osparc.store.Study.getInstance().getWallet(studyId),
126+
osparc.store.Study.getInstance().getOne(studyId),
127+
]).then(([wallet, latestStudyData]) => {
128+
const currentUserGroupIds = osparc.study.Utils.state.getCurrentGroupIds(latestStudyData["state"]);
126129
if (
127130
isStudyCreation ||
128131
wallet === null ||
129-
osparc.desktop.credits.Utils.getWallet(wallet["walletId"]) === null
132+
(osparc.desktop.credits.Utils.getWallet(wallet["walletId"]) === null && currentUserGroupIds.length === 0)
130133
) {
131-
// pop up study options if the study was just created or if it has no wallet assigned or user has no access to it
134+
// pop up StudyOptions if:
135+
// - the study was just created
136+
// - it has no wallet assigned
137+
// - I do not have access to it and the project is not being used
132138
const resourceSelector = new osparc.study.StudyOptions(studyId);
133139
if (isStudyCreation) {
134140
resourceSelector.getChildControl("open-button").setLabel(qx.locale.Manager.tr("New"));
@@ -157,7 +163,28 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
157163
}
158164
});
159165
} else {
160-
openStudy();
166+
const found = osparc.store.Store.getInstance().getWallets().find(w => w.getWalletId() === wallet["walletId"]);
167+
if (found) {
168+
// I have access to the wallet
169+
if (osparc.store.Store.getInstance().getContextWallet() !== found) {
170+
// switch to that wallet and inform the user that the context wallet has changed
171+
const text = qx.locale.Manager.tr("Switched to Credit Account") + " '" + found.getName() + "'";
172+
osparc.FlashMessenger.logAs(text);
173+
}
174+
osparc.store.Store.getInstance().setActiveWallet(found);
175+
openStudy();
176+
} else {
177+
// I do not have access to the wallet or it's being used
178+
// cancel and explain the user why
179+
const isRTCEnabled = osparc.utils.DisabledPlugins.isRTCEnabled();
180+
const msg = isRTCEnabled ?
181+
qx.locale.Manager.tr("You can't join the project because you don't have access to the Credit Account associated with it. Please contact the project owner.") :
182+
qx.locale.Manager.tr("You can't join the project because it's already open by another user.");
183+
osparc.FlashMessenger.logAs(msg, "ERROR");
184+
if (cancelCB) {
185+
cancelCB();
186+
}
187+
}
161188
}
162189
});
163190
} else {
@@ -196,7 +223,22 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
196223
osparc.utils.Utils.addBorderRightRadius(rButton);
197224
}
198225
return rButton;
199-
}
226+
},
227+
228+
getOpenText: function(resourceData) {
229+
const studyAlias = osparc.product.Utils.getStudyAlias({firstUpperCase: true});
230+
let openText = qx.locale.Manager.tr("New") + " " + studyAlias;
231+
if (resourceData["resourceType"] === "study") {
232+
// if it's in use call it join
233+
const isRTCEnabled = osparc.utils.DisabledPlugins.isRTCEnabled();
234+
if (osparc.study.Utils.state.getCurrentGroupIds(resourceData["state"]).length && isRTCEnabled) {
235+
openText = qx.locale.Manager.tr("Join");
236+
} else {
237+
openText = qx.locale.Manager.tr("Open");
238+
}
239+
}
240+
return openText;
241+
},
200242
},
201243

202244
members: {
@@ -899,8 +941,7 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
899941
},
900942

901943
_getOpenMenuButton: function(resourceData) {
902-
const studyAlias = osparc.product.Utils.getStudyAlias({firstUpperCase: true});
903-
const openText = (resourceData["resourceType"] === "study") ? this.tr("Open") : this.tr("New") + " " + studyAlias;
944+
const openText = osparc.dashboard.ResourceBrowserBase.getOpenText(resourceData);
904945
const openButton = new qx.ui.menu.Button(openText);
905946
openButton["openResourceButton"] = true;
906947
openButton.addListener("execute", () => {

services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,14 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
157157
maxHeight: 40
158158
});
159159
return toolbar;
160-
}
160+
},
161+
162+
disableIfInUse: function(resourceData, widget) {
163+
if (resourceData["resourceType"] === "study") {
164+
// disable if it's being used
165+
widget.setEnabled(!osparc.study.Utils.state.getCurrentGroupIds(resourceData["state"]).length);
166+
}
167+
},
161168
},
162169

163170
properties: {
@@ -225,8 +232,7 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
225232
toolbar.add(serviceVersionSelector);
226233
}
227234

228-
const studyAlias = osparc.product.Utils.getStudyAlias({firstUpperCase: true});
229-
const openText = (this.__resourceData["resourceType"] === "study") ? this.tr("Open") : this.tr("New") + " " + studyAlias;
235+
const openText = osparc.dashboard.ResourceBrowserBase.getOpenText(this.__resourceData);
230236
const openButton = new osparc.ui.form.FetchButton(openText).set({
231237
enabled: true
232238
});
@@ -536,6 +542,7 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
536542

537543
const lazyLoadContent = () => {
538544
const billingSettings = new osparc.study.BillingSettings(resourceData);
545+
this.self().disableIfInUse(resourceData, billingSettings);
539546
billingSettings.addListener("debtPayed", () => {
540547
page.payDebtButton.set({
541548
visibility: osparc.study.Utils.isInDebt(resourceData) ? "visible" : "excluded"
@@ -785,6 +792,7 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
785792

786793
const lazyLoadContent = () => {
787794
const servicesUpdate = new osparc.metadata.ServicesInStudyUpdate(resourceData);
795+
this.self().disableIfInUse(resourceData, servicesUpdate);
788796
servicesUpdate.addListener("updateService", e => {
789797
const updatedData = e.getData();
790798
this.__fireUpdateEvent(resourceData, updatedData);
@@ -818,6 +826,7 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
818826

819827
const lazyLoadContent = () => {
820828
const servicesBootOpts = new osparc.metadata.ServicesInStudyBootOpts(resourceData);
829+
this.self().disableIfInUse(resourceData, servicesBootOpts);
821830
servicesBootOpts.addListener("updateService", e => {
822831
const updatedData = e.getData();
823832
this.__fireUpdateEvent(resourceData, updatedData);

services/static-webserver/client/source/class/osparc/desktop/WorkbenchView.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ qx.Class.define("osparc.desktop.WorkbenchView", {
657657
}, this);
658658

659659
workbench.addListener("fileRequested", () => {
660-
if (this.getStudy().getUi().getMode() === "workbench") {
660+
if (["workbench", "pipeline"].includes(this.getStudy().getUi().getMode())) {
661661
const tabViewLeftPanel = this.getChildControl("side-panel-left-tabs");
662662
tabViewLeftPanel.setSelection([this.__storagePage]);
663663
}

services/static-webserver/client/source/class/osparc/desktop/wallets/WalletListItem.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ qx.Class.define("osparc.desktop.wallets.WalletListItem", {
153153
rowSpan: 2
154154
});
155155
break;
156-
case "favourite-button":
156+
case "preferred-button":
157157
control = new qx.ui.form.Button().set({
158158
iconPosition: "right",
159159
width: 110, // make Primary and Secondary buttons same width
@@ -326,8 +326,11 @@ qx.Class.define("osparc.desktop.wallets.WalletListItem", {
326326
},
327327

328328
__applyPreferredWallet: function(isPreferredWallet) {
329-
const favouriteButton = this.getChildControl("favourite-button");
330-
favouriteButton.setBackgroundColor("transparent");
329+
const favouriteButton = this.getChildControl("preferred-button");
330+
favouriteButton.set({
331+
backgroundColor: "transparent",
332+
width: 60,
333+
});
331334
const favouriteButtonIcon = favouriteButton.getChildControl("icon");
332335
if (isPreferredWallet) {
333336
favouriteButton.set({

services/static-webserver/client/source/class/osparc/desktop/wallets/WalletsList.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ qx.Class.define("osparc.desktop.wallets.WalletsList", {
229229
flex: 1
230230
});
231231
if (showCurrently) {
232-
const selectColumn = new qx.ui.basic.Label(this.tr("Currently in use")).set({
233-
marginRight: 18
232+
const selectColumn = new qx.ui.basic.Label(this.tr("Preferred")).set({
233+
marginRight: 8 // align it with the "preferred-button"
234234
});
235235
header.add(selectColumn)
236236
}

services/static-webserver/client/source/class/osparc/file/FilePicker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ qx.Class.define("osparc.file.FilePicker", {
283283
this.__buildInfoLayout();
284284
} else {
285285
this.__addProgressBar();
286-
if (viewContext === "workbench") {
286+
if (["workbench", "pipeline"].includes(viewContext)) {
287287
this.__buildWorkbenchLayout();
288288
} else {
289289
this.setMargin(10);

0 commit comments

Comments
 (0)