Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions shard.lock
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ shards:

office365:
git: https://github.com/placeos/office365.git
version: 1.27.1
version: 1.27.2

openai:
git: https://github.com/spider-gazelle/crystal-openai.git
Expand All @@ -187,7 +187,7 @@ shards:

pg-orm:
git: https://github.com/spider-gazelle/pg-orm.git
version: 2.2.1
version: 2.2.2

pinger:
git: https://github.com/spider-gazelle/pinger.git
Expand Down Expand Up @@ -215,15 +215,15 @@ shards:

placeos-frontend-loader:
git: https://github.com/placeos/frontend-loader.git
version: 2.7.1+git.commit.693b47914d40284458518503be7441dfc7ff98aa
version: 2.7.1+git.commit.4d12eb11b0b381f4d7927b3d7086cbc5b42f21c9

placeos-log-backend:
git: https://github.com/place-labs/log-backend.git
version: 0.13.0

placeos-models:
git: https://github.com/placeos/models.git
version: 9.98.3
version: 9.98.4

placeos-resource:
git: https://github.com/place-labs/resource.git
Expand Down Expand Up @@ -275,7 +275,7 @@ shards:

search-ingest:
git: https://github.com/placeos/search-ingest.git
version: 2.11.3+git.commit.f3e14c701667f3fb185a82b352d4e053c7f082d2
version: 2.11.3+git.commit.57d54cc34bece9abf2c2704f76358b3cd4a3199a

secrets-env: # Overridden
git: https://github.com/spider-gazelle/secrets-env.git
Expand Down
124 changes: 124 additions & 0 deletions spec/controllers/asset_categories_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,129 @@ module PlaceOS::Api
describe "scopes" do
Spec.test_controller_scope(AssetCategories)
end

describe "support-subsystem permissions" do
::Spec.before_each { clear_group_tables }

it "allows POST for a support user with Create on the org zone (both sides)" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Create).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Create).save!

body = Model::Generator.asset_category.to_json
result = client.post(AssetCategories.base_route, body: body, headers: headers)
result.status_code.should eq 201

Model::AssetCategory.from_trusted_json(result.body).destroy
end

it "rejects POST when the support user only has Read on the org zone" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Read).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Read).save!

body = Model::Generator.asset_category.to_json
result = client.post(AssetCategories.base_route, body: body, headers: headers)
result.status_code.should eq 403
end

it "requires Update on both sides to PATCH an asset category" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

asset_category = Model::Generator.asset_category.save!
group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Update).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Update).save!

result = client.patch(
path: "#{AssetCategories.base_route}#{asset_category.id}",
body: {name: "renamed-#{random_name}"}.to_json,
headers: headers,
)
result.success?.should be_true
asset_category.destroy
end

it "rejects PATCH when the support user only has Create on the org zone" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

asset_category = Model::Generator.asset_category.save!
group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Create).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Create).save!

result = client.patch(
path: "#{AssetCategories.base_route}#{asset_category.id}",
body: {name: "renamed-#{random_name}"}.to_json,
headers: headers,
)
result.status_code.should eq 403
asset_category.destroy
end

it "requires Delete on both sides to DELETE an asset category" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

asset_category = Model::Generator.asset_category.save!
group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Delete).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Delete).save!

result = client.delete(path: "#{AssetCategories.base_route}#{asset_category.id}", headers: headers)
result.success?.should be_true
Model::AssetCategory.find?(asset_category.id).should be_nil
end

it "rejects DELETE when the support user only has Update on the org zone" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

asset_category = Model::Generator.asset_category.save!
group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Update).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Update).save!

result = client.delete(path: "#{AssetCategories.base_route}#{asset_category.id}", headers: headers)
result.status_code.should eq 403
asset_category.destroy
end

it "allows a support-JWT user to POST regardless of group grants" do
body = Model::Generator.asset_category.to_json
result = client.post(
AssetCategories.base_route,
body: body,
headers: Spec::Authentication.headers(sys_admin: false, support: true),
)
result.status_code.should eq 201
Model::AssetCategory.from_trusted_json(result.body).destroy
end

it "allows an admin-JWT user to POST regardless of group grants" do
body = Model::Generator.asset_category.to_json
result = client.post(
AssetCategories.base_route,
body: body,
headers: Spec::Authentication.headers(sys_admin: true, support: false),
)
result.status_code.should eq 201
Model::AssetCategory.from_trusted_json(result.body).destroy
end
end
end
end
152 changes: 152 additions & 0 deletions spec/controllers/asset_purchase_orders_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,157 @@ module PlaceOS::Api
describe "scopes" do
Spec.test_controller_scope(AssetPurchaseOrders)
end

describe "support-subsystem permissions" do
::Spec.before_each { clear_group_tables }

it "allows POST for a support user with Create on the org zone (both sides)" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Create).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Create).save!

body = Model::Generator.asset_purchase_order.to_json
result = client.post(AssetPurchaseOrders.base_route, body: body, headers: headers)
result.status_code.should eq 201

Model::AssetPurchaseOrder.from_trusted_json(result.body).destroy
end

it "rejects POST when the support user only has Read on the org zone" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Read).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Read).save!

body = Model::Generator.asset_purchase_order.to_json
result = client.post(AssetPurchaseOrders.base_route, body: body, headers: headers)
result.status_code.should eq 403
end

it "requires Update on both sides to PATCH a purchase order" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

purchase_order = Model::Generator.asset_purchase_order.save!
group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Update).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Update).save!

result = client.patch(
path: "#{AssetPurchaseOrders.base_route}#{purchase_order.id}",
body: {purchase_order_number: "po-#{random_name}"}.to_json,
headers: headers,
)
result.success?.should be_true
purchase_order.destroy
end

it "rejects PATCH when the support user only has Create on the org zone" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

purchase_order = Model::Generator.asset_purchase_order.save!
group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Create).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Create).save!

result = client.patch(
path: "#{AssetPurchaseOrders.base_route}#{purchase_order.id}",
body: {purchase_order_number: "po-#{random_name}"}.to_json,
headers: headers,
)
result.status_code.should eq 403
purchase_order.destroy
end

it "requires Delete on both sides to DELETE a purchase order" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

purchase_order = Model::Generator.asset_purchase_order.save!
group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Delete).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Delete).save!

result = client.delete(path: "#{AssetPurchaseOrders.base_route}#{purchase_order.id}", headers: headers)
result.success?.should be_true
Model::AssetPurchaseOrder.find?(purchase_order.id).should be_nil
end

it "rejects DELETE when the support user only has Update on the org zone" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

purchase_order = Model::Generator.asset_purchase_order.save!
group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Update).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Update).save!

result = client.delete(path: "#{AssetPurchaseOrders.base_route}#{purchase_order.id}", headers: headers)
result.status_code.should eq 403
purchase_order.destroy
end

# index/show map the verb bit to None, so the support path requires
# Manage on the org zone to read.
it "allows GET index for a support user with Manage on the org zone (both sides)" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Manage).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Manage).save!

result = client.get(AssetPurchaseOrders.base_route, headers: headers)
result.status_code.should eq 200
end

it "rejects GET index when the support user only has Read on the org zone" do
authority = Model::Authority.find_by_domain("localhost").not_nil!
user, headers = Spec::Authentication.authentication(sys_admin: false, support: false)
org_zone = Spec::Authentication.org_zone

group = Model::Generator.group(authority: authority, subsystems: ["support"]).save!
Model::Generator.group_user(user: user, group: group, permissions: Model::Permissions::Read).save!
Model::Generator.group_zone(group: group, zone: org_zone, permissions: Model::Permissions::Read).save!

result = client.get(AssetPurchaseOrders.base_route, headers: headers)
result.status_code.should eq 403
end

it "allows a support-JWT user to POST regardless of group grants" do
body = Model::Generator.asset_purchase_order.to_json
result = client.post(
AssetPurchaseOrders.base_route,
body: body,
headers: Spec::Authentication.headers(sys_admin: false, support: true),
)
result.status_code.should eq 201
Model::AssetPurchaseOrder.from_trusted_json(result.body).destroy
end

it "allows an admin-JWT user to POST regardless of group grants" do
body = Model::Generator.asset_purchase_order.to_json
result = client.post(
AssetPurchaseOrders.base_route,
body: body,
headers: Spec::Authentication.headers(sys_admin: true, support: false),
)
result.status_code.should eq 201
Model::AssetPurchaseOrder.from_trusted_json(result.body).destroy
end
end
end
end
Loading
Loading