security: remove is_system_role from public API
Remove is_system_role from accept lists in create_role and update_role actions. This field should only be set via seeds or internal actions to prevent users from creating unkillable roles through the public API.
This commit is contained in:
parent
73763b1f58
commit
5f13901ca5
4 changed files with 11 additions and 122 deletions
|
|
@ -17,6 +17,10 @@ defmodule Mv.Accounts.User do
|
|||
# When a member is deleted, set the user's member_id to NULL
|
||||
# This allows users to continue existing even if their linked member is removed
|
||||
reference :member, on_delete: :nilify
|
||||
|
||||
# When a role is deleted, prevent deletion if users are assigned to it
|
||||
# This protects critical roles from accidental deletion
|
||||
reference :role, on_delete: :restrict
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -61,14 +61,16 @@ defmodule Mv.Authorization.Role do
|
|||
|
||||
create :create_role do
|
||||
primary? true
|
||||
accept [:name, :description, :permission_set_name, :is_system_role]
|
||||
# is_system_role is intentionally excluded - should only be set via seeds/internal actions
|
||||
accept [:name, :description, :permission_set_name]
|
||||
# Note: In Ash 3.0, require_atomic? is not available for create actions
|
||||
# Custom validations will still work
|
||||
end
|
||||
|
||||
update :update_role do
|
||||
primary? true
|
||||
accept [:name, :description, :permission_set_name, :is_system_role]
|
||||
# is_system_role is intentionally excluded - should only be set via seeds/internal actions
|
||||
accept [:name, :description, :permission_set_name]
|
||||
# Required because custom validation functions cannot be executed atomically
|
||||
require_atomic? false
|
||||
end
|
||||
|
|
@ -85,7 +87,8 @@ defmodule Mv.Authorization.Role do
|
|||
Mv.Authorization.PermissionSets.all_permission_sets()
|
||||
|> Enum.map(&Atom.to_string/1)
|
||||
),
|
||||
message: "must be one of: own_data, read_only, normal_user, admin"
|
||||
message:
|
||||
"must be one of: #{Mv.Authorization.PermissionSets.all_permission_sets() |> Enum.map_join(", ", &Atom.to_string/1)}"
|
||||
|
||||
validate fn changeset, _context ->
|
||||
if changeset.data.is_system_role do
|
||||
|
|
|
|||
|
|
@ -1,118 +0,0 @@
|
|||
{
|
||||
"attributes": [
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"gen_random_uuid()\")",
|
||||
"generated?": false,
|
||||
"precision": null,
|
||||
"primary_key?": true,
|
||||
"references": null,
|
||||
"scale": null,
|
||||
"size": null,
|
||||
"source": "id",
|
||||
"type": "uuid"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"precision": null,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"scale": null,
|
||||
"size": null,
|
||||
"source": "name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"precision": null,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"scale": null,
|
||||
"size": null,
|
||||
"source": "description",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"precision": null,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"scale": null,
|
||||
"size": null,
|
||||
"source": "permission_set_name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "false",
|
||||
"generated?": false,
|
||||
"precision": null,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"scale": null,
|
||||
"size": null,
|
||||
"source": "is_system_role",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||
"generated?": false,
|
||||
"precision": null,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"scale": null,
|
||||
"size": null,
|
||||
"source": "inserted_at",
|
||||
"type": "utc_datetime_usec"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||
"generated?": false,
|
||||
"precision": null,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"scale": null,
|
||||
"size": null,
|
||||
"source": "updated_at",
|
||||
"type": "utc_datetime_usec"
|
||||
}
|
||||
],
|
||||
"base_filter": null,
|
||||
"check_constraints": [],
|
||||
"custom_indexes": [],
|
||||
"custom_statements": [],
|
||||
"has_create_action": true,
|
||||
"hash": "FFDA74F44B5F11381D4C1F4DACA54901A1E02C3D181A88484AEED4E1ADA21B87",
|
||||
"identities": [
|
||||
{
|
||||
"all_tenants?": false,
|
||||
"base_filter": null,
|
||||
"index_name": "roles_unique_name_index",
|
||||
"keys": [
|
||||
{
|
||||
"type": "atom",
|
||||
"value": "name"
|
||||
}
|
||||
],
|
||||
"name": "unique_name",
|
||||
"nils_distinct?": true,
|
||||
"where": null
|
||||
}
|
||||
],
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"repo": "Elixir.Mv.Repo",
|
||||
"schema": null,
|
||||
"table": "roles"
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
"strategy": null
|
||||
},
|
||||
"name": "users_role_id_fkey",
|
||||
"on_delete": null,
|
||||
"on_delete": "restrict",
|
||||
"on_update": null,
|
||||
"primary_key?": true,
|
||||
"schema": "public",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue