Merge pull request #1923 from Freika/feature/unlimited-family

Remove limit on number of family members for self-hosted instances.
This commit is contained in:
Evgenii Burmakin 2025-11-07 11:35:35 +01:00 committed by GitHub
commit a6f2bd3662
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 189 additions and 63 deletions

View file

@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Changed
- Removed useless system tests and cover map functionality with Playwright e2e tests instead.
- Number of family members on self-hosted instances is no longer limited.
# [0.34.2] - 2025-10-31

View file

@ -11,6 +11,8 @@ class Family < ApplicationRecord
MAX_MEMBERS = 5
def can_add_members?
return true if DawarichSettings.self_hosted?
(member_count + pending_invitations_count) < MAX_MEMBERS
end
@ -32,6 +34,8 @@ class Family < ApplicationRecord
end
def full?
return false if DawarichSettings.self_hosted?
(member_count + pending_invitations_count) >= MAX_MEMBERS
end

View file

@ -1,22 +0,0 @@
# frozen_string_literal: true
class FamilyInvitationPolicy < ApplicationPolicy
def show?
# Public endpoint for invitation acceptance - no authentication required
true
end
def create?
user.family == record.family && user.family_owner?
end
def accept?
# Users can accept invitations sent to their email
user.email == record.email
end
def destroy?
# Only family owners can cancel invitations
user.family == record.family && user.family_owner?
end
end

View file

@ -1,23 +0,0 @@
# frozen_string_literal: true
class FamilyMembershipPolicy < ApplicationPolicy
def show?
user.family == record.family
end
def update?
# Users can update their own settings
return true if user == record.user
# Family owners can update any member's settings
user.family == record.family && user.family_owner?
end
def destroy?
# Users can remove themselves (handled by family leave logic)
return true if user == record.user
# Family owners can remove other members
user.family == record.family && user.family_owner?
end
end

View file

@ -26,31 +26,100 @@ RSpec.describe Family, type: :model do
describe '#can_add_members?' do
let(:family) { create(:family, creator: user) }
context 'when family has fewer than max members' do
context 'when not in self-hosted mode' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 3, family: family, role: :member)
allow(DawarichSettings).to receive(:self_hosted?).and_return(false)
end
it 'returns true' do
expect(family.can_add_members?).to be true
context 'when family has fewer than max members' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 3, family: family, role: :member)
end
it 'returns true' do
expect(family.can_add_members?).to be true
end
end
context 'when family has max members' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 4, family: family, role: :member)
end
it 'returns false' do
expect(family.can_add_members?).to be false
end
end
context 'when family has pending invitations that would reach max' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 3, family: family, role: :member)
create(:family_invitation, family: family, invited_by: user, status: :pending)
end
it 'returns false' do
expect(family.can_add_members?).to be false
end
end
context 'when family has no members' do
it 'returns true' do
expect(family.can_add_members?).to be true
end
end
end
context 'when family has max members' do
context 'when in self-hosted mode' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 4, family: family, role: :member)
allow(DawarichSettings).to receive(:self_hosted?).and_return(true)
end
it 'returns false' do
expect(family.can_add_members?).to be false
end
end
context 'when family has fewer than max members' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 3, family: family, role: :member)
end
context 'when family has no members' do
it 'returns true' do
expect(family.can_add_members?).to be true
it 'returns true' do
expect(family.can_add_members?).to be true
end
end
context 'when family has max members' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 4, family: family, role: :member)
end
it 'returns true (no limit in self-hosted mode)' do
expect(family.can_add_members?).to be true
end
end
context 'when family has more than max members' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 10, family: family, role: :member)
end
it 'returns true (no limit in self-hosted mode)' do
expect(family.can_add_members?).to be true
end
end
context 'when family has pending invitations that would exceed max' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 4, family: family, role: :member)
create_list(:family_invitation, 5, family: family, invited_by: user, status: :pending)
end
it 'returns true (no limit in self-hosted mode)' do
expect(family.can_add_members?).to be true
end
end
end
end
@ -122,4 +191,99 @@ RSpec.describe Family, type: :model do
expect(Family::Membership.find_by(id: membership.id)).to be_nil
end
end
describe '#full?' do
let(:family) { create(:family, creator: user) }
context 'when not in self-hosted mode' do
before do
allow(DawarichSettings).to receive(:self_hosted?).and_return(false)
end
context 'when family has fewer than max members' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 3, family: family, role: :member)
end
it 'returns false' do
expect(family.full?).to be false
end
end
context 'when family has exactly max members' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 4, family: family, role: :member)
end
it 'returns true' do
expect(family.full?).to be true
end
end
context 'when family has pending invitations that would reach max' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 3, family: family, role: :member)
create(:family_invitation, family: family, invited_by: user, status: :pending)
end
it 'returns true' do
expect(family.full?).to be true
end
end
end
context 'when in self-hosted mode' do
before do
allow(DawarichSettings).to receive(:self_hosted?).and_return(true)
end
context 'when family has fewer than max members' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 3, family: family, role: :member)
end
it 'returns false' do
expect(family.full?).to be false
end
end
context 'when family has exactly max members' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 4, family: family, role: :member)
end
it 'returns false (no limit in self-hosted mode)' do
expect(family.full?).to be false
end
end
context 'when family has more than max members' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 10, family: family, role: :member)
end
it 'returns false (no limit in self-hosted mode)' do
expect(family.full?).to be false
end
end
context 'when family has pending invitations that would exceed max' do
before do
create(:family_membership, family: family, user: user, role: :owner)
create_list(:family_membership, 4, family: family, role: :member)
create_list(:family_invitation, 5, family: family, invited_by: user, status: :pending)
end
it 'returns false (no limit in self-hosted mode)' do
expect(family.full?).to be false
end
end
end
end
end

View file

@ -51,8 +51,8 @@ RSpec.describe 'Users::Registrations', type: :request do
get new_user_registration_path
expect(response).to have_http_status(:ok)
expect(response.body).to include('Register now!')
expect(response.body).to include('take control over your location data')
expect(response.body).to include('Almost there!')
expect(response.body).to include('control over your location data')
expect(response.body).not_to include('Join')
expect(response.body).to include('Sign up')
end
@ -227,7 +227,7 @@ RSpec.describe 'Users::Registrations', type: :request do
get new_user_registration_path
expect(response).to have_http_status(:ok)
expect(response.body).to include('Register now!')
expect(response.body).to include('Almost there!')
end
it 'allows account creation' do

View file

@ -99,6 +99,7 @@ RSpec.describe Families::AcceptInvitation do
context 'when family is at max capacity' do
before do
allow(DawarichSettings).to receive(:self_hosted?).and_return(false)
# Fill family to max capacity
create_list(:family_membership, Family::MAX_MEMBERS, family: family, role: :member)
end

View file

@ -57,6 +57,7 @@ RSpec.describe Families::Invite do
context 'when family is at max capacity' do
before do
allow(DawarichSettings).to receive(:self_hosted?).and_return(false)
# Create max members (5 total including owner)
create_list(:family_membership, Family::MAX_MEMBERS - 1, family: family, role: :member)
end