Default-deny access control with group flags and access enumeration
Some checks failed
Some checks failed
Replaces the implicit "empty allowed_groups means public" rule with explicit default-deny across both OIDC and ForwardAuth. Adds two boolean flags on Group — auto_assign (Keycloak-style auto-join on user create) and admin (members can reach the admin panel) — and drops the users.admin column entirely. Adds "Users with access" and "Accessible applications" panels with via-group badges on the application/user show pages. BEHAVIOR CHANGE: a ForwardAuth app with no allowed_groups previously bypassed authentication entirely; it now returns 403 like any other unauthorized request. The data migration seeds an "everyone" group and attaches it to all previously group-less apps to preserve behavior on existing installs. An "admins" group is seeded and backfilled from any user with the old admin column. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
class SeedDefaultGroupsAndMigrateAdmins < ActiveRecord::Migration[8.1]
|
||||
# Data migration: seed "everyone" (auto_assign) and "admins" (admin) groups,
|
||||
# backfill memberships from existing data, attach "everyone" to previously
|
||||
# group-less applications. Idempotent.
|
||||
#
|
||||
# Must run before RemoveAdminFromUsers, because it reads the legacy
|
||||
# users.admin column.
|
||||
|
||||
def up
|
||||
unless Group.exists?(auto_assign: true)
|
||||
everyone = Group.create!(
|
||||
name: "everyone",
|
||||
description: "Auto-assigned to new users. Safe to rename or remove.",
|
||||
auto_assign: true
|
||||
)
|
||||
|
||||
User.where(status: 0).find_each do |u|
|
||||
UserGroup.find_or_create_by!(user_id: u.id, group_id: everyone.id)
|
||||
end
|
||||
|
||||
Application.left_joins(:application_groups)
|
||||
.where(application_groups: {id: nil})
|
||||
.find_each do |app|
|
||||
ApplicationGroup.find_or_create_by!(application_id: app.id, group_id: everyone.id)
|
||||
end
|
||||
end
|
||||
|
||||
unless Group.exists?(admin: true)
|
||||
admins = Group.create!(
|
||||
name: "admins",
|
||||
description: "Members can access the admin panel.",
|
||||
admin: true
|
||||
)
|
||||
|
||||
User.where(admin: true).find_each do |u|
|
||||
UserGroup.find_or_create_by!(user_id: u.id, group_id: admins.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
Group.where(name: ["everyone", "admins"]).destroy_all
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user