feat(api)!: Add model permission checks (#485)
* Add model permission checks * test_public * This is the real fix * mistake * public api resource
This commit is contained in:
@@ -8,6 +8,7 @@ from specklepy.core.api.inputs.model_inputs import (
|
||||
)
|
||||
from specklepy.core.api.inputs.project_inputs import ProjectModelsFilter
|
||||
from specklepy.core.api.models import Model, ModelWithVersions, ResourceCollection
|
||||
from specklepy.core.api.models.current import ModelPermissionChecks
|
||||
from specklepy.core.api.resources import ModelResource as CoreResource
|
||||
from specklepy.logging import metrics
|
||||
|
||||
@@ -72,3 +73,7 @@ class ModelResource(CoreResource):
|
||||
def update(self, input: UpdateModelInput) -> Model:
|
||||
metrics.track(metrics.SDK, self.account, {"name": "Model Update"})
|
||||
return super().update(input)
|
||||
|
||||
def get_permissions(self, model_id: str, project_id: str) -> ModelPermissionChecks:
|
||||
metrics.track(metrics.SDK, self.account, {"name": "Model Get Permissions"})
|
||||
return super().get_permissions(model_id, project_id)
|
||||
|
||||
@@ -7,6 +7,7 @@ class ProjectVisibility(str, Enum):
|
||||
PRIVATE = "PRIVATE"
|
||||
PUBLIC = "PUBLIC"
|
||||
UNLISTED = "UNLISTED"
|
||||
"""Deprecated, use PUBLIC instead"""
|
||||
WORKSPACE = "WORKSPACE"
|
||||
|
||||
|
||||
|
||||
@@ -137,6 +137,12 @@ class Version(GraphQLBaseModel):
|
||||
source_application: str | None
|
||||
|
||||
|
||||
class ModelPermissionChecks(GraphQLBaseModel):
|
||||
can_update: "PermissionCheckResult"
|
||||
can_delete: "PermissionCheckResult"
|
||||
can_create_version: "PermissionCheckResult"
|
||||
|
||||
|
||||
class Model(GraphQLBaseModel):
|
||||
author: LimitedUser | None
|
||||
created_at: datetime
|
||||
@@ -156,7 +162,6 @@ class ProjectPermissionChecks(GraphQLBaseModel):
|
||||
can_create_model: "PermissionCheckResult"
|
||||
can_delete: "PermissionCheckResult"
|
||||
can_load: "PermissionCheckResult"
|
||||
can_publish: "PermissionCheckResult"
|
||||
|
||||
|
||||
class Project(GraphQLBaseModel):
|
||||
|
||||
@@ -10,6 +10,7 @@ from specklepy.core.api.inputs.model_inputs import (
|
||||
)
|
||||
from specklepy.core.api.inputs.project_inputs import ProjectModelsFilter
|
||||
from specklepy.core.api.models import Model, ModelWithVersions, ResourceCollection
|
||||
from specklepy.core.api.models.current import ModelPermissionChecks
|
||||
from specklepy.core.api.resource import ResourceBase
|
||||
from specklepy.core.api.responses import DataResponse
|
||||
|
||||
@@ -299,3 +300,40 @@ class ModelResource(ResourceBase):
|
||||
return self.make_request_and_parse_response(
|
||||
DataResponse[DataResponse[Model]], QUERY, variables
|
||||
).data.data
|
||||
|
||||
def get_permissions(self, project_id: str, model_id: str) -> ModelPermissionChecks:
|
||||
QUERY = gql(
|
||||
"""
|
||||
query ModelPermissions($projectId: String!, $modelId: String!) {
|
||||
data:project(id: $projectId) {
|
||||
data:model(id: $modelId) {
|
||||
data:permissions {
|
||||
canUpdate {
|
||||
authorized
|
||||
code
|
||||
message
|
||||
}
|
||||
canDelete {
|
||||
authorized
|
||||
code
|
||||
message
|
||||
}
|
||||
canCreateVersion {
|
||||
authorized
|
||||
code
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
variables = {"projectId": project_id, "modelId": model_id}
|
||||
|
||||
return self.make_request_and_parse_response(
|
||||
DataResponse[DataResponse[DataResponse[ModelPermissionChecks]]],
|
||||
QUERY,
|
||||
variables,
|
||||
).data.data.data
|
||||
|
||||
@@ -50,12 +50,10 @@ class TestActiveUserResourcePermissions:
|
||||
assert hasattr(permissions, "can_create_model")
|
||||
assert hasattr(permissions, "can_delete")
|
||||
assert hasattr(permissions, "can_load")
|
||||
assert hasattr(permissions, "can_publish")
|
||||
|
||||
assert permissions.can_create_model.authorized is True
|
||||
assert permissions.can_delete.authorized is True
|
||||
assert permissions.can_load.authorized is True
|
||||
assert permissions.can_publish.authorized is True
|
||||
|
||||
def test_active_user_get_projects_with_permissions_with_filter(
|
||||
self, client: SpeckleClient, test_project: Project
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from specklepy.api.client import SpeckleClient
|
||||
from specklepy.core.api.enums import ProjectVisibility
|
||||
from specklepy.core.api.inputs.model_inputs import (
|
||||
CreateModelInput,
|
||||
DeleteModelInput,
|
||||
@@ -12,6 +13,7 @@ from specklepy.core.api.inputs.project_inputs import (
|
||||
)
|
||||
from specklepy.core.api.models.current import (
|
||||
Model,
|
||||
ModelPermissionChecks,
|
||||
Project,
|
||||
ProjectWithModels,
|
||||
ResourceCollection,
|
||||
@@ -24,7 +26,9 @@ class TestModelResource:
|
||||
@pytest.fixture()
|
||||
def test_project(self, client: SpeckleClient) -> Project:
|
||||
project = client.project.create(
|
||||
ProjectCreateInput(name="Test project", description="", visibility=None)
|
||||
ProjectCreateInput(
|
||||
name="Test project", description="", visibility=ProjectVisibility.PUBLIC
|
||||
)
|
||||
)
|
||||
return project
|
||||
|
||||
@@ -149,3 +153,24 @@ class TestModelResource:
|
||||
|
||||
with pytest.raises(GraphQLException):
|
||||
client.model.delete(delete_data)
|
||||
|
||||
def test_model_get_permissions(
|
||||
self,
|
||||
client: SpeckleClient,
|
||||
second_client: SpeckleClient,
|
||||
test_project: Project,
|
||||
test_model: Model,
|
||||
):
|
||||
result = client.model.get_permissions(test_project.id, test_model.id)
|
||||
|
||||
assert isinstance(result, ModelPermissionChecks)
|
||||
assert result.can_update.authorized is True
|
||||
assert result.can_create_version.authorized is True
|
||||
assert result.can_delete.authorized is True
|
||||
|
||||
guest = second_client.model.get_permissions(test_project.id, test_model.id)
|
||||
|
||||
assert isinstance(guest, ModelPermissionChecks)
|
||||
assert guest.can_update.authorized is False
|
||||
assert guest.can_create_version.authorized is False
|
||||
assert guest.can_delete.authorized is False
|
||||
|
||||
@@ -24,6 +24,17 @@ class TestProjectResource:
|
||||
)
|
||||
return project
|
||||
|
||||
@pytest.fixture()
|
||||
def test_public_project(self, client: SpeckleClient) -> Project:
|
||||
project = client.project.create(
|
||||
ProjectCreateInput(
|
||||
name="test project123",
|
||||
description="desc",
|
||||
visibility=ProjectVisibility.PUBLIC,
|
||||
)
|
||||
)
|
||||
return project
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"name, description, visibility",
|
||||
[
|
||||
@@ -50,7 +61,7 @@ class TestProjectResource:
|
||||
assert result.id is not None
|
||||
assert result.name == name
|
||||
assert result.description == (description or "")
|
||||
# we've disabled creation of public projects for now, they fall back to unlisted
|
||||
# we've disabled creation of unlisted projects for now, they fall back to public
|
||||
if visibility == ProjectVisibility.UNLISTED:
|
||||
assert result.visibility == ProjectVisibility.PUBLIC
|
||||
else:
|
||||
@@ -67,13 +78,32 @@ class TestProjectResource:
|
||||
assert result.created_at == test_project.created_at
|
||||
|
||||
def test_project_get_permissions(
|
||||
self, client: SpeckleClient, test_project: Project
|
||||
self,
|
||||
client: SpeckleClient,
|
||||
second_client: SpeckleClient,
|
||||
test_project: Project,
|
||||
test_public_project: Project,
|
||||
):
|
||||
result = client.project.get_permissions(test_project.id)
|
||||
result_private = client.project.get_permissions(test_project.id)
|
||||
|
||||
assert isinstance(result_private, ProjectPermissionChecks)
|
||||
assert result_private.can_create_model.authorized is True
|
||||
assert result_private.can_delete.authorized is True
|
||||
assert result_private.can_load.authorized is True
|
||||
|
||||
result = client.project.get_permissions(test_public_project.id)
|
||||
|
||||
assert isinstance(result, ProjectPermissionChecks)
|
||||
assert result.can_create_model.authorized is True
|
||||
assert result.can_delete.authorized is True
|
||||
assert result.can_load.authorized is True
|
||||
|
||||
guest = second_client.project.get_permissions(test_public_project.id)
|
||||
|
||||
assert isinstance(result, ProjectPermissionChecks)
|
||||
assert guest.can_create_model.authorized is False
|
||||
assert guest.can_delete.authorized is False
|
||||
assert guest.can_load.authorized is False
|
||||
|
||||
def test_project_update(self, client: SpeckleClient, test_project: Project):
|
||||
new_name = "MY new name"
|
||||
|
||||
Reference in New Issue
Block a user