Skip to content

Commit ff0b716

Browse files
committed
Model for user roles in the context of a space
1 parent 4e8605c commit ff0b716

File tree

7 files changed

+89
-1
lines changed

7 files changed

+89
-1
lines changed

app/models/space.rb

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ class Space < ApplicationRecord
99
has_many :collections, dependent: :nullify
1010
has_many :learning_paths, dependent: :nullify
1111
has_many :learning_path_topics, dependent: :nullify
12+
has_many :space_roles, dependent: :destroy
13+
has_many :space_role_users, through: :space_roles, source: :user, class_name: 'User'
1214

1315
has_image(placeholder: TeSS::Config.placeholder['content_provider'])
1416

@@ -35,4 +37,8 @@ def url
3537
def default?
3638
false
3739
end
40+
41+
def with_space_role?(role)
42+
space_role_users.joins(:space_roles).where(space_roles: { key: role })
43+
end
3844
end

app/models/space_role.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class SpaceRole < ApplicationRecord
2+
ROLES = ['admin'].freeze
3+
belongs_to :user
4+
belongs_to :space
5+
6+
validates :key, inclusion: { in: ROLES }
7+
end

app/models/user.rb

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class User < ApplicationRecord
5252
has_and_belongs_to_many :editables, class_name: "ContentProvider"
5353

5454
has_many :collaborations, dependent: :destroy
55+
has_many :space_roles, dependent: :destroy
5556

5657
before_create :set_default_role, :set_default_profile
5758
before_create :skip_email_confirmation_for_non_production
@@ -374,6 +375,10 @@ def purge
374375
end
375376
end
376377

378+
def has_space_role?(space, role)
379+
space_roles.where(key: role, space: space).any?
380+
end
381+
377382
protected
378383

379384
def reassign_resources(new_owner = User.get_default_user)

config/data/space_roles.yml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
space_admin:
2+
title: Administrator
3+
space_curator:
4+
title: Curator
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class CreateSpaceRoles < ActiveRecord::Migration[7.2]
2+
def change
3+
create_table :space_roles do |t|
4+
t.string :key
5+
t.references :user, foreign_key: true, index: true
6+
t.references :space, foreign_key: true, index: true
7+
t.timestamps
8+
end
9+
end
10+
end

db/schema.rb

+13-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema[7.2].define(version: 2025_02_10_093412) do
13+
ActiveRecord::Schema[7.2].define(version: 2025_03_04_161944) do
1414
# These are extensions that must be enabled in order to support this database
1515
enable_extension "plpgsql"
1616

@@ -483,6 +483,16 @@
483483
t.index ["user_id"], name: "index_sources_on_user_id"
484484
end
485485

486+
create_table "space_roles", force: :cascade do |t|
487+
t.string "key"
488+
t.bigint "user_id"
489+
t.bigint "space_id"
490+
t.datetime "created_at", null: false
491+
t.datetime "updated_at", null: false
492+
t.index ["space_id"], name: "index_space_roles_on_space_id"
493+
t.index ["user_id"], name: "index_space_roles_on_user_id"
494+
end
495+
486496
create_table "spaces", force: :cascade do |t|
487497
t.string "title"
488498
t.text "description"
@@ -654,6 +664,8 @@
654664
add_foreign_key "nodes", "users"
655665
add_foreign_key "sources", "content_providers"
656666
add_foreign_key "sources", "users"
667+
add_foreign_key "space_roles", "spaces"
668+
add_foreign_key "space_roles", "users"
657669
add_foreign_key "spaces", "users"
658670
add_foreign_key "staff_members", "nodes"
659671
add_foreign_key "stars", "users"

test/models/space_role_test.rb

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
require 'test_helper'
2+
3+
class SpaceRoleTest < ActiveSupport::TestCase
4+
setup do
5+
@space = spaces(:plants)
6+
end
7+
8+
test 'validates role key' do
9+
invalid_key = @space.space_roles.build(user: users(:regular_user), key: :yes)
10+
refute invalid_key.valid?
11+
assert invalid_key.errors.added?(:key, :inclusion, value: 'yes')
12+
13+
valid_key = @space.space_roles.build(user: users(:regular_user), key: :admin)
14+
assert valid_key.valid?
15+
end
16+
17+
test 'can retrieve list of users with a given role in a space' do
18+
user = users(:regular_user)
19+
another_user = users(:another_regular_user)
20+
@space.space_roles.create!(user: user, key: :admin)
21+
@space.space_roles.create!(user: another_user, key: :admin)
22+
23+
admins = @space.with_space_role?(:admin)
24+
assert_equal 2, admins.length
25+
assert_includes admins, user
26+
assert_includes admins, another_user
27+
28+
assert_equal 2, @space.with_space_role?('admin').length
29+
30+
assert_empty @space.with_space_role?(:badmin)
31+
end
32+
33+
test 'can check if a user has a given role in a space' do
34+
user = users(:regular_user)
35+
another_user = users(:another_regular_user)
36+
@space.space_roles.create!(user: user, key: :admin)
37+
38+
assert user.has_space_role?(@space, :admin)
39+
assert user.has_space_role?(@space, 'admin')
40+
refute user.has_space_role?(spaces(:astro), :admin)
41+
refute user.has_space_role?(@space, :overlord)
42+
refute another_user.has_space_role?(@space, :admin)
43+
end
44+
end

0 commit comments

Comments
 (0)