Skip to content

Commit

Permalink
Merge pull request #3423 from magda-io/issue/3421
Browse files Browse the repository at this point in the history
#3421, #3426 & #3424 and more...
  • Loading branch information
t83714 authored Nov 9, 2022
2 parents 6d691fa + 27a9db1 commit 588ba63
Show file tree
Hide file tree
Showing 15 changed files with 319 additions and 87 deletions.
8 changes: 7 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
- Upgraded indexer weekly reindexer trigger container to node14
- Distribution page UI minor improvements: display file size (when available) & adjust margins between information blocks
- Improve the error message for `false` unconditional decision.
- #3420 add merge option support to PUT record API
- #3420 add `merge` option support to PUT record API
- #3421 Improve dataset updating UI logic using `merge` option of the PUT record API
- Avoid sending unnecessary `aspects` field as the part of the context data created by RegistryExternalInterface
- #3426 People with orgUnit constraint permission should only be able to perform read operation on datasets not assigned to an orgUnit
- #3424 Set the default order by field for APIs
- #3427 Dataset Editor: offer more details via error message box when encounter insufficient permission error
- #3425 offer a button on dataset page to take the user back to data management tab

## v2.1.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ export default function createResourceApiRouter(options: ApiRouterOptions) {
: (req?.query?.offset as string),
limit: returnCount
? undefined
: (req?.query?.limit as string)
: (req?.query?.limit as string),
orderBy: returnCount
? undefined
: sqls`resources.uri ASC`
}
);
if (returnCount) {
Expand Down Expand Up @@ -434,7 +437,10 @@ export default function createResourceApiRouter(options: ApiRouterOptions) {
: (req?.query?.offset as string),
limit: returnCount
? undefined
: (req?.query?.limit as string)
: (req?.query?.limit as string),
orderBy: returnCount
? undefined
: sqls`operations.uri ASC`
}
);
if (returnCount) {
Expand Down
10 changes: 8 additions & 2 deletions magda-authorization-api/src/apiRouters/createRoleApiRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,10 @@ export default function createRoleApiRouter(options: ApiRouterOptions) {
: (req?.query?.offset as string),
limit: returnCount
? undefined
: (req?.query?.limit as string)
: (req?.query?.limit as string),
orderBy: returnCount
? undefined
: sqls`permissions.create_time DESC`
}
);
if (returnCount) {
Expand Down Expand Up @@ -851,7 +854,10 @@ export default function createRoleApiRouter(options: ApiRouterOptions) {
: (req?.query?.offset as string),
limit: returnCount
? undefined
: (req?.query?.limit as string)
: (req?.query?.limit as string),
orderBy: returnCount
? undefined
: sqls`roles.name, roles.create_time ASC`
}
);
if (returnCount) {
Expand Down
6 changes: 5 additions & 1 deletion magda-opa/policies/common/verifyRecordPermission.rego
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,18 @@ verifyRecordPermission(inputOperationUri, inputObjectRefName) {
input.user.managingOrgUnitIds[_] = input.object[inputObjectRefName]["access-control"].orgUnitId
}

# or when a user has org unit ownership constraint permission, he also can access all records with NO org unit assigned
# or when a user has org unit ownership constraint permission, he also can access (read permission only) all records with NO org unit assigned
verifyRecordPermission(inputOperationUri, inputObjectRefName) {
[resourceType, operationType, resourceUriPrefix] := breakdownOperationUri(inputOperationUri)
operationType == "read"
hasOrgUnitConstaintPermission(inputOperationUri)
# unfortunately, we can't use isEmpty to handle undefined value
not input.object[inputObjectRefName]["access-control"].orgUnitId
}

verifyRecordPermission(inputOperationUri, inputObjectRefName) {
[resourceType, operationType, resourceUriPrefix] := breakdownOperationUri(inputOperationUri)
operationType == "read"
hasOrgUnitConstaintPermission(inputOperationUri)
isEmpty(input.object[inputObjectRefName]["access-control"].orgUnitId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,12 @@ verifyRecordWithPublishingStatusPermission(inputOperationUri, inputObjectRefName
}

# if find a permission with org unit ownership constraint, plus dataset have NOT been assigned org unit
# e.g. anonymous users can access all datasets that not belongs to an org unit
# e.g. anonymous users can access (`read` permission only) all datasets that not belongs to an org unit
verifyRecordWithPublishingStatusPermission(inputOperationUri, inputObjectRefName) {
[resourceType, operationType, resourceUriPrefix] := breakdownOperationUri(inputOperationUri)

# we only want to allow this special permission grant for "read" operation (issue: #3426)
operationType == "read"
resourceType == "*"

input.user.permissions[i].userOwnershipConstraint = false
Expand All @@ -107,6 +109,8 @@ verifyRecordWithPublishingStatusPermission(inputOperationUri, inputObjectRefName
verifyRecordWithPublishingStatusPermission(inputOperationUri, inputObjectRefName) {
[resourceType, operationType, resourceUriPrefix] := breakdownOperationUri(inputOperationUri)

# we only want to allow this special permission grant for "read" operation (issue: #3426)
operationType == "read"
resourceType == "*"

input.user.permissions[i].userOwnershipConstraint = false
Expand Down
162 changes: 162 additions & 0 deletions magda-opa/policies/object/dataset/allow_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,47 @@ test_allow_empty_string_orgUnitId {
}
}

test_not_allow_empty_string_orgUnitId_non_read_operation {
not allow with input as {
"operationUri": "object/dataset/published/update",
"object": {
"dataset": {
"access-control": {
"ownerId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
"orgUnitId": ""
},
"publishing": {
"state": "published"
}
}
},
"user": {
"displayName": "Jacky Jiang",
"email": "[email protected]",
"id": "80a9dce4-91af-44e2-a2f4-9ddccb3f4c5e",
"managingOrgUnitIds": ["90a9dce4-91af-44e2-a2f4-9ddccb3f4c5f"],
"permissions": [
{
"id": "e5ce2fc4-9f38-4f52-8190-b770ed2074e6",
"name": "View Published Dataset",
"operations": [
{
"id": "f1e2af3e-5d98-4081-a4ff-7016f43002fa",
"name": "Read Publish Dataset",
"uri": "object/dataset/published/read"
}
],
"orgUnitOwnershipConstraint": true,
"preAuthorisedConstraint": false,
"resourceId": "ef3b767f-d06b-46f4-9302-031ae5004275",
"resourceUri": "object/dataset/published",
"userOwnershipConstraint": false
}
]
}
}
}

test_allow_undefined_orgUnitId {
allow with input as {
"operationUri": "object/dataset/published/read",
Expand Down Expand Up @@ -791,6 +832,46 @@ test_allow_undefined_orgUnitId {
}
}

test_not_allow_undefined_orgUnitId_non_read {
not allow with input as {
"operationUri": "object/dataset/published/update",
"object": {
"dataset": {
"access-control": {
"ownerId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
},
"publishing": {
"state": "published"
}
}
},
"user": {
"displayName": "Jacky Jiang",
"email": "[email protected]",
"id": "80a9dce4-91af-44e2-a2f4-9ddccb3f4c5e",
"managingOrgUnitIds": ["90a9dce4-91af-44e2-a2f4-9ddccb3f4c5f"],
"permissions": [
{
"id": "e5ce2fc4-9f38-4f52-8190-b770ed2074e6",
"name": "View Published Dataset",
"operations": [
{
"id": "f1e2af3e-5d98-4081-a4ff-7016f43002fa",
"name": "Read Publish Dataset",
"uri": "object/dataset/published/read"
}
],
"orgUnitOwnershipConstraint": true,
"preAuthorisedConstraint": false,
"resourceId": "ef3b767f-d06b-46f4-9302-031ae5004275",
"resourceUri": "object/dataset/published",
"userOwnershipConstraint": false
}
]
}
}
}

test_allow_empty_string_orgUnitId_any_publishing_status {
allow with input as {
"operationUri": "object/dataset/*/read",
Expand Down Expand Up @@ -832,6 +913,47 @@ test_allow_empty_string_orgUnitId_any_publishing_status {
}
}

test_not_allow_empty_string_orgUnitId_any_publishing_status_non_read {
not allow with input as {
"operationUri": "object/dataset/*/update",
"object": {
"dataset": {
"access-control": {
"ownerId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
"orgUnitId": ""
},
"publishing": {
"state": "published"
}
}
},
"user": {
"displayName": "Jacky Jiang",
"email": "[email protected]",
"id": "80a9dce4-91af-44e2-a2f4-9ddccb3f4c5e",
"managingOrgUnitIds": ["90a9dce4-91af-44e2-a2f4-9ddccb3f4c5f"],
"permissions": [
{
"id": "e5ce2fc4-9f38-4f52-8190-b770ed2074e6",
"name": "View Published Dataset",
"operations": [
{
"id": "f1e2af3e-5d98-4081-a4ff-7016f43002fa",
"name": "Read Publish Dataset",
"uri": "object/dataset/published/read"
}
],
"orgUnitOwnershipConstraint": true,
"preAuthorisedConstraint": false,
"resourceId": "ef3b767f-d06b-46f4-9302-031ae5004275",
"resourceUri": "object/dataset/published",
"userOwnershipConstraint": false
}
]
}
}
}

test_allow_undefined_orgUnitId_any_publishing_status {
allow with input as {
"operationUri": "object/dataset/*/read",
Expand Down Expand Up @@ -870,4 +992,44 @@ test_allow_undefined_orgUnitId_any_publishing_status {
]
}
}
}

test_not_allow_undefined_orgUnitId_any_publishing_status_non_read {
not allow with input as {
"operationUri": "object/dataset/*/delete",
"object": {
"dataset": {
"access-control": {
"ownerId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
},
"publishing": {
"state": "published"
}
}
},
"user": {
"displayName": "Jacky Jiang",
"email": "[email protected]",
"id": "80a9dce4-91af-44e2-a2f4-9ddccb3f4c5e",
"managingOrgUnitIds": ["90a9dce4-91af-44e2-a2f4-9ddccb3f4c5f"],
"permissions": [
{
"id": "e5ce2fc4-9f38-4f52-8190-b770ed2074e6",
"name": "View Published Dataset",
"operations": [
{
"id": "f1e2af3e-5d98-4081-a4ff-7016f43002fa",
"name": "Read Publish Dataset",
"uri": "object/dataset/published/read"
}
],
"orgUnitOwnershipConstraint": true,
"preAuthorisedConstraint": false,
"resourceId": "ef3b767f-d06b-46f4-9302-031ae5004275",
"resourceUri": "object/dataset/published",
"userOwnershipConstraint": false
}
]
}
}
}
11 changes: 7 additions & 4 deletions magda-opa/policies/storage/bucket/allow.rego
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package storage.bucket
import data.common.hasNoConstraintPermission
import data.common.hasOrgUnitConstaintPermission
import data.common.hasOwnerConstraintPermission
import data.common.breakdownOperationUri
import data.common.isEmpty

default allow = false
Expand All @@ -29,16 +30,18 @@ allow {
input.user.managingOrgUnitIds[_] = input.storage.bucket.orgUnitId
}

# or when a user has org unit ownership constraint permission, he also can access (read only) all buckets with NO org unit assigned
allow {
[resourceType, operationType, resourceUriPrefix] := breakdownOperationUri(input.operationUri)
operationType == "read"
hasOrgUnitConstaintPermission(input.operationUri)

# or when a user has org unit ownership constraint permission, he also can access all buckets with NO org unit assigned
not input.storage.bucket.orgUnitId
}

# or when a user has org unit ownership constraint permission, he also can access (read only) all buckets with NO org unit assigned
allow {
[resourceType, operationType, resourceUriPrefix] := breakdownOperationUri(input.operationUri)
operationType == "read"
hasOrgUnitConstaintPermission(input.operationUri)

# or when a user has org unit ownership constraint permission, he also can access all buckets with NO org unit assigned
isEmpty(input.storage.bucket.orgUnitId)
}
8 changes: 6 additions & 2 deletions magda-opa/policies/storage/object/allow.rego
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,19 @@ allow {
input.user.managingOrgUnitIds[_] = input.storage.object.orgUnitId
}

# or when a user has org unit ownership constraint permission, he also can access (read only) all objects with NO org unit assigned
allow {
[resourceType, operationType, resourceUriPrefix] := breakdownOperationUri(input.operationUri)
operationType == "read"
hasOrgUnitConstaintPermission(input.operationUri)
# or when a user has org unit ownership constraint permission, he also can access all objects with NO org unit assigned
not input.storage.object.orgUnitId
}

# or when a user has org unit ownership constraint permission, he also can access (read only) all objects with NO org unit assigned
allow {
[resourceType, operationType, resourceUriPrefix] := breakdownOperationUri(input.operationUri)
operationType == "read"
hasOrgUnitConstaintPermission(input.operationUri)
# or when a user has org unit ownership constraint permission, he also can access all objects with NO org unit assigned
isEmpty(input.storage.object.orgUnitId)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ class RegistryExternalInterface(
case JsObject(v) => v.toSeq
case _ => Seq()
}
JsObject((rawJsData.fields - "aspect") ++ aspects)
JsObject((rawJsData.fields - "aspects") ++ aspects)
}
case _ =>
Unmarshal(response.entity).to[String].flatMap(onError(response))
Expand Down
6 changes: 6 additions & 0 deletions magda-web-client/src/Components/Common/ErrorMessageBox.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@
margin-top: 10px;
margin-bottom: 10px;
}
.tooltip-container {
.tooltip {
padding-left: 0px !important;
left: 0px;
}
}
}
Loading

0 comments on commit 588ba63

Please sign in to comment.