punk 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.editorconfig +9 -0
- data/.github/workflows/test.yml +26 -1
- data/.rdoc_options +23 -0
- data/.rgignore +1 -0
- data/.rspec +2 -0
- data/Gemfile +5 -6
- data/Gemfile.lock +16 -29
- data/README.md +1 -1
- data/VERSION +1 -1
- data/app/migrations/001_lets_punk.rb +3 -0
- data/app/routes/hello.rb +4 -0
- data/env/.gitignore +3 -0
- data/env/spec/test.sh +3 -0
- data/lib/punk/actions/.keep +0 -0
- data/lib/punk/actions/groups/list.rb +24 -0
- data/lib/punk/actions/sessions/clear.rb +21 -0
- data/lib/punk/actions/sessions/create.rb +64 -0
- data/lib/punk/actions/sessions/list.rb +18 -0
- data/lib/punk/actions/sessions/verify.rb +24 -0
- data/lib/punk/actions/tenants/list.rb +18 -0
- data/lib/punk/actions/users/list_group.rb +18 -0
- data/lib/punk/actions/users/list_tenant.rb +18 -0
- data/lib/punk/actions/users/show.rb +18 -0
- data/lib/punk/commands/list.rb +12 -6
- data/lib/punk/config/defaults.json +3 -0
- data/lib/punk/config/schema.json +3 -0
- data/lib/punk/core/app.rb +4 -6
- data/lib/punk/core/commander.rb +7 -4
- data/lib/punk/core/exec.rb +2 -0
- data/lib/punk/core/load.rb +0 -1
- data/lib/punk/framework/command.rb +5 -1
- data/lib/punk/framework/plugins/validation.rb +0 -14
- data/lib/punk/helpers/loggable.rb +1 -1
- data/lib/punk/migrations/001_punk.rb +103 -0
- data/lib/punk/models/.keep +0 -0
- data/lib/punk/models/group.rb +20 -0
- data/lib/punk/models/group_user_metadata.rb +17 -0
- data/lib/punk/models/identity.rb +29 -0
- data/lib/punk/models/session.rb +89 -0
- data/lib/punk/models/tenant.rb +19 -0
- data/lib/punk/models/tenant_user_metadata.rb +17 -0
- data/lib/punk/models/user.rb +31 -0
- data/lib/punk/routes/groups.rb +31 -0
- data/lib/punk/routes/plivo.rb +4 -0
- data/lib/punk/routes/sessions.rb +108 -0
- data/lib/punk/routes/swagger.rb +9 -0
- data/lib/punk/routes/tenants.rb +29 -0
- data/lib/punk/routes/users.rb +36 -0
- data/lib/punk/services/.keep +0 -0
- data/lib/punk/services/challenge_claim.rb +46 -0
- data/lib/punk/services/create_identities.rb +25 -0
- data/lib/punk/services/generate_swagger.rb +25 -0
- data/lib/punk/services/prove_claim.rb +29 -0
- data/lib/punk/services/secret.rb +9 -0
- data/lib/punk/templates/groups/list.jbuilder +7 -0
- data/lib/punk/templates/plivo.slim +16 -0
- data/lib/punk/templates/sessions/list.jbuilder +6 -0
- data/lib/punk/templates/sessions/pending.jbuilder +4 -0
- data/lib/punk/templates/tenants/list.jbuilder +7 -0
- data/lib/punk/templates/tenants/list.slim +8 -0
- data/lib/punk/templates/users/list.jbuilder +7 -0
- data/lib/punk/templates/users/list.rcsv +4 -0
- data/lib/punk/templates/users/show.jbuilder +5 -0
- data/lib/punk/views/groups/list.rb +22 -0
- data/lib/punk/views/plivo_store.rb +15 -0
- data/lib/punk/views/sessions/list.rb +22 -0
- data/lib/punk/views/sessions/pending.rb +28 -0
- data/lib/punk/views/tenants/list.rb +22 -0
- data/lib/punk/views/users/list.rb +22 -0
- data/lib/punk/views/users/show.rb +22 -0
- data/lib/punk/workers/.keep +0 -0
- data/lib/punk/workers/expire_sessions.rb +9 -0
- data/lib/punk/workers/geocode_session_worker.rb +48 -0
- data/lib/punk/workers/identify_session_worker.rb +45 -0
- data/lib/punk/workers/secret.rb +18 -0
- data/lib/punk/workers/send_email_worker.rb +51 -0
- data/lib/punk/workers/send_sms_worker.rb +40 -0
- data/punk.gemspec +140 -14
- data/schema.psql +345 -0
- data/spec/actions/groups/punk/list_groups_action_spec.rb +36 -0
- data/spec/actions/sessions/punk/clear_session_action_spec.rb +29 -0
- data/spec/actions/sessions/punk/create_session_action_spec.rb +33 -0
- data/spec/actions/sessions/punk/list_sessions_action_spec.rb +26 -0
- data/spec/actions/sessions/punk/verify_session_action_spec.rb +59 -0
- data/spec/actions/tenants/punk/list_tenants_action_spec.rb +25 -0
- data/spec/actions/users/punk/list_group_users_action_spec.rb +26 -0
- data/spec/actions/users/punk/list_tenant_users_action_spec.rb +26 -0
- data/spec/factories/group.rb +12 -0
- data/spec/factories/group_user_metadata.rb +10 -0
- data/spec/factories/identity.rb +19 -0
- data/spec/factories/session.rb +12 -0
- data/spec/factories/tenant.rb +10 -0
- data/spec/factories/tenant_user_metadata.rb +10 -0
- data/spec/factories/user.rb +12 -0
- data/spec/lib/commands/auth_spec.rb +11 -0
- data/spec/lib/commands/generate_spec.rb +7 -0
- data/spec/lib/commands/http_spec.rb +23 -0
- data/spec/lib/commands/list_spec.rb +7 -0
- data/spec/lib/commands/swagger_spec.rb +7 -0
- data/spec/lib/engine/punk_env_spec.rb +13 -0
- data/spec/lib/engine/punk_exec_spec.rb +9 -0
- data/spec/lib/engine/punk_init_spec.rb +9 -0
- data/spec/lib/engine/punk_store_spec.rb +10 -0
- data/spec/lib/punk.env +7 -0
- data/spec/models/punk/group_spec.rb +50 -0
- data/spec/models/punk/group_user_metadata_spec.rb +61 -0
- data/spec/models/punk/identity_spec.rb +61 -0
- data/spec/models/punk/session_spec.rb +156 -0
- data/spec/models/punk/tenant_spec.rb +51 -0
- data/spec/models/punk/tenant_user_metadata_spec.rb +61 -0
- data/spec/models/punk/user_spec.rb +115 -0
- data/spec/routes/groups/get_groups_spec.rb +33 -0
- data/spec/routes/plivo/get_plivo_spec.rb +11 -0
- data/spec/routes/sessions/delete_session_spec.rb +11 -0
- data/spec/routes/sessions/get_sessions_spec.rb +30 -0
- data/spec/routes/sessions/patch_session_spec.rb +11 -0
- data/spec/routes/sessions/post_session_spec.rb +11 -0
- data/spec/routes/swagger/get_swagger_spec.rb +12 -0
- data/spec/routes/tenants/get_tenants_spec.rb +31 -0
- data/spec/routes/users/get_users_spec.rb +60 -0
- data/spec/services/punk/challenge_claim_service_spec.rb +7 -0
- data/spec/services/punk/create_identities_service_spec.rb +14 -0
- data/spec/services/punk/generate_swagger_service_spec.rb +7 -0
- data/spec/services/punk/prove_claim_service_spec.rb +7 -0
- data/spec/services/punk/secret_service_spec.rb +7 -0
- data/spec/spec_helper.rb +122 -0
- data/spec/vcr_cassettes/PUNK_GeocodeSessionWorker/updates_the_session_data.yml +57 -0
- data/spec/vcr_cassettes/PUNK_IdentifySessionWorker/updates_the_session_data.yml +112 -0
- data/spec/views/punk/plivo_store_spec.rb +7 -0
- data/spec/views/sessions/punk/list_sessions_view_spec.rb +7 -0
- data/spec/views/sessions/punk/pending_session_view_spec.rb +7 -0
- data/spec/views/tenants/punk/list_tenants_view_spec.rb +7 -0
- data/spec/views/users/punk/list_groups_view_spec.rb +7 -0
- data/spec/views/users/punk/list_users_view_spec.rb +7 -0
- data/spec/workers/punk/expire_sessions_worker_spec.rb +31 -0
- data/spec/workers/punk/geocode_session_worker_spec.rb +14 -0
- data/spec/workers/punk/identify_session_worker_spec.rb +15 -0
- data/spec/workers/punk/secret_worker_spec.rb +20 -0
- data/spec/workers/punk/send_email_worker_spec.rb +46 -0
- data/spec/workers/punk/send_sms_worker_spec.rb +33 -0
- metadata +148 -11
- data/lib/punk/views/all.rb +0 -4
data/spec/lib/punk.env
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe PUNK::Group do
|
|
4
|
+
it "is valid with valid attributes" do
|
|
5
|
+
expect { create(:group) }.not_to raise_error
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "is assigned a uuid on save" do
|
|
9
|
+
group = build(:group)
|
|
10
|
+
expect(group.id).to be_nil
|
|
11
|
+
group.save
|
|
12
|
+
expect(valid_uuid?(group.id)).to be(true)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "can be saved with a custom uuid" do
|
|
16
|
+
uuid = generate(:uuid)
|
|
17
|
+
group = create(:group, id: uuid)
|
|
18
|
+
expect(group.id).to eq(uuid)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "is invalid without a name" do
|
|
22
|
+
group = build(:group, name: nil)
|
|
23
|
+
expect(group.valid?).to be(false)
|
|
24
|
+
expect(group.errors[:name].first).to eq('is not present')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "is valid without an icon" do
|
|
28
|
+
group = build(:group, icon: nil)
|
|
29
|
+
expect(group.valid?).to be(true)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "is invalid if the icon is not a URL" do
|
|
33
|
+
group = build(:group, icon: Faker::Alphanumeric.alpha)
|
|
34
|
+
expect(group.valid?).to be(false)
|
|
35
|
+
expect(group.errors[:icon].first).to eq('is not a URL')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "must belong to a tenant" do
|
|
39
|
+
group = build(:group, tenant: nil)
|
|
40
|
+
expect(group.valid?).to be(false)
|
|
41
|
+
expect(group.errors[:tenant].first).to eq('is not present')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "can have multiple members" do
|
|
45
|
+
group = create(:group)
|
|
46
|
+
expect(group.users.count).to eq(0)
|
|
47
|
+
3.times { create(:user).add_group(group) }
|
|
48
|
+
expect(group.users.count).to eq(3)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe PUNK::GroupUserMetadata do
|
|
4
|
+
it "is valid with valid attributes" do
|
|
5
|
+
expect { create(:group_user_metadata) }.not_to raise_error
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "is invalid without a group" do
|
|
9
|
+
group_user_metadata = build(:group_user_metadata, group: nil)
|
|
10
|
+
expect(group_user_metadata.valid?).to be(false)
|
|
11
|
+
expect(group_user_metadata.errors[:group].first).to eq('is not present')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "is invalid without a user" do
|
|
15
|
+
group_user_metadata = build(:group_user_metadata, user: nil)
|
|
16
|
+
expect(group_user_metadata.valid?).to be(false)
|
|
17
|
+
expect(group_user_metadata.errors[:user].first).to eq('is not present')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "displays as the two IDs concatenated" do
|
|
21
|
+
group_user_metadata = create(:group_user_metadata)
|
|
22
|
+
expect(group_user_metadata.to_s).to include(group_user_metadata.group.id)
|
|
23
|
+
expect(group_user_metadata.to_s).to include(group_user_metadata.user.id)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context "when a user and a group exist" do
|
|
27
|
+
let(:user) { create(:user) }
|
|
28
|
+
let(:group) { create(:group) }
|
|
29
|
+
|
|
30
|
+
context "when a user is added to a group" do
|
|
31
|
+
let(:group_user_metadata) do
|
|
32
|
+
described_class[group: group, user: user]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
before do
|
|
36
|
+
group.add_user(user)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "is created automatically" do
|
|
40
|
+
expect(group_user_metadata).not_to be_nil
|
|
41
|
+
expect(group.users).to include(user)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "destroying it will remove the user from the group" do
|
|
45
|
+
expect(group.users).to include(user)
|
|
46
|
+
group_user_metadata.destroy
|
|
47
|
+
group.reload
|
|
48
|
+
expect(group.users).not_to include(user)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context "when it is created" do
|
|
53
|
+
it "adds a user to a group" do
|
|
54
|
+
expect(group.users).not_to include(user)
|
|
55
|
+
create(:group_user_metadata, group: group, user: user)
|
|
56
|
+
group.reload
|
|
57
|
+
expect(group.users).to include(user)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe PUNK::Identity do
|
|
4
|
+
it 'is valid with valid attributes' do
|
|
5
|
+
expect { create(:identity) }.not_to raise_error
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it 'must claim an email or a phone' do
|
|
9
|
+
identity = build(:identity, claim_type: 'zork', claim: 'xyzzy')
|
|
10
|
+
expect(identity.valid?).to be(false)
|
|
11
|
+
expect(identity.errors[:claim_type].first).to eq('is not in range or set: [:email, :phone]')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'is assigned a uuid on save' do
|
|
15
|
+
identity = build(:identity)
|
|
16
|
+
expect(identity.id).to be_nil
|
|
17
|
+
identity.save
|
|
18
|
+
expect(valid_uuid?(identity.id)).to be(true)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'can be saved with a custom uuid' do
|
|
22
|
+
uuid = generate(:uuid)
|
|
23
|
+
identity = create(:identity, id: uuid)
|
|
24
|
+
expect(identity.id).to eq(uuid)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'may belong to a user' do
|
|
28
|
+
identity_with_user = create(:identity)
|
|
29
|
+
expect(identity_with_user.user).to exist
|
|
30
|
+
identity_without_user = create(:identity, user: nil)
|
|
31
|
+
expect(identity_without_user.user).to be_nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'has an email? accessor' do
|
|
35
|
+
identity_with_email = build(:identity, claim_type: 'email')
|
|
36
|
+
expect(identity_with_email.email?).to be(true)
|
|
37
|
+
identity_without_email = build(:identity, claim_type: 'phone')
|
|
38
|
+
expect(identity_without_email.email?).to be(false)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'has a phone? accessor' do
|
|
42
|
+
identity_with_phone = create(:identity, claim_type: 'phone')
|
|
43
|
+
expect(identity_with_phone.phone?).to be(true)
|
|
44
|
+
identity_without_phone = create(:identity, claim_type: 'email')
|
|
45
|
+
expect(identity_without_phone.phone?).to be(false)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'has a unique claim' do
|
|
49
|
+
identity = create(:identity)
|
|
50
|
+
duplicate_identity = build(:identity, claim_type: identity.claim_type, claim: identity.claim)
|
|
51
|
+
expect(duplicate_identity.valid?).to be(false)
|
|
52
|
+
expect(duplicate_identity.errors[:claim].first).to eq('is already taken')
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'can have multiple sessions' do
|
|
56
|
+
identity = create(:identity)
|
|
57
|
+
expect(identity.sessions.count).to eq(0)
|
|
58
|
+
create_list(:session, 3, identity: identity)
|
|
59
|
+
expect(identity.sessions.count).to eq(3)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe PUNK::Session do
|
|
4
|
+
it "is valid with valid attributes" do
|
|
5
|
+
expect { create(:session) }.not_to raise_error
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "is assigned a uuid on save" do
|
|
9
|
+
session = build(:session)
|
|
10
|
+
expect(session.id).to be_nil
|
|
11
|
+
session.save
|
|
12
|
+
expect(valid_uuid?(session.id)).to be(true)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "can be saved with a custom uuid" do
|
|
16
|
+
uuid = generate(:uuid)
|
|
17
|
+
session = create(:session, id: uuid)
|
|
18
|
+
expect(session.id).to eq(uuid)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "must belong to an identity" do
|
|
22
|
+
session = build(:session, identity: nil)
|
|
23
|
+
expect(session.valid?).to be(false)
|
|
24
|
+
expect(session.errors[:identity].first).to eq('is not present')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "may have a user" do
|
|
28
|
+
session = build(:session)
|
|
29
|
+
expect(session.user).to exist
|
|
30
|
+
session = build(:session, identity: create(:identity, user: nil))
|
|
31
|
+
expect(session.user).to be_nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "can contain client data" do
|
|
35
|
+
identity = create(:session, data: { foo: 'bar' })
|
|
36
|
+
expect(identity.data[:foo]).to eq('bar')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "permits only three validation attempts" do
|
|
40
|
+
session = create(:session, attempt_count: 3)
|
|
41
|
+
expect(session.valid?).to be(true)
|
|
42
|
+
expect { session.increment_attempts }.to raise_error(Sequel::ValidationFailed, "attempt_count is not in range or set: [0, 1, 2, 3]")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "starts in the created state" do
|
|
46
|
+
session = create(:session)
|
|
47
|
+
expect(session.created?).to be(true)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "can be challenged" do
|
|
51
|
+
session = create(:session)
|
|
52
|
+
expect(session.may_challenge?).to be(true)
|
|
53
|
+
session.challenge!
|
|
54
|
+
expect(session.pending?).to be(true)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "can be verified" do
|
|
58
|
+
session = create(:session)
|
|
59
|
+
session.challenge!
|
|
60
|
+
expect(session.may_verify?).to be(true)
|
|
61
|
+
session.verify!
|
|
62
|
+
expect(session.active?).to be(true)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "will not timeout when first created" do
|
|
66
|
+
session = create(:session)
|
|
67
|
+
session.timeout?
|
|
68
|
+
expect(session.created?).to be(true)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "will timeout after 5 minutes if not active" do
|
|
72
|
+
session = create(:session)
|
|
73
|
+
Timecop.travel(6.minutes.from_now)
|
|
74
|
+
expect(described_class.expiring.count).to eq(1)
|
|
75
|
+
session.timeout?
|
|
76
|
+
expect(session.expired?).to be(true)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "will not time out after 5 minutes if active" do
|
|
80
|
+
session = create(:session, state: :active)
|
|
81
|
+
Timecop.travel(1.week.from_now)
|
|
82
|
+
expect(described_class.expiring.count).to eq(0)
|
|
83
|
+
session.timeout?
|
|
84
|
+
expect(session.active?).to be(true)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "will timeout after 1 month if active but unused" do
|
|
88
|
+
session = create(:session, state: :active)
|
|
89
|
+
Timecop.travel((1.month + 1.day).from_now)
|
|
90
|
+
expect(described_class.expiring.count).to eq(1)
|
|
91
|
+
session.timeout?
|
|
92
|
+
expect(session.expired?).to be(true)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "will not timeout after 1 month if active and used" do
|
|
96
|
+
session = create(:session, state: :active)
|
|
97
|
+
Timecop.travel(6.months.from_now)
|
|
98
|
+
session.touch
|
|
99
|
+
session.timeout?
|
|
100
|
+
expect(session.active?).to be(true)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "will timeout after 1 year if active and used" do
|
|
104
|
+
session = create(:session, state: :active)
|
|
105
|
+
Timecop.travel((1.year + 1.day).from_now)
|
|
106
|
+
session.touch
|
|
107
|
+
session.timeout?
|
|
108
|
+
expect(session.expired?).to be(true)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "can be cleared" do
|
|
112
|
+
session = create(:session, state: :active)
|
|
113
|
+
expect(session.may_clear?).to be(true)
|
|
114
|
+
session.clear!
|
|
115
|
+
expect(session.deleted?).to be(true)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
context "when many sessions exist" do
|
|
119
|
+
before do
|
|
120
|
+
create(:session, state: :created)
|
|
121
|
+
create(:session, state: :pending)
|
|
122
|
+
create(:session, state: :active)
|
|
123
|
+
create(:session, state: :expired)
|
|
124
|
+
create(:session, state: :deleted)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "can be scoped to created sessions" do
|
|
128
|
+
expect(described_class.count).to eq(5)
|
|
129
|
+
expect(described_class.created.count).to eq(1)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "can be scoped to pending sessions" do
|
|
133
|
+
expect(described_class.count).to eq(5)
|
|
134
|
+
expect(described_class.pending.count).to eq(1)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "can be scoped to active sessions" do
|
|
138
|
+
expect(described_class.count).to eq(5)
|
|
139
|
+
expect(described_class.active.count).to eq(1)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "can be scoped to expired sessions" do
|
|
143
|
+
expect(described_class.count).to eq(5)
|
|
144
|
+
expect(described_class.expired.count).to eq(1)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "can be scoped to deleted sessions" do
|
|
148
|
+
expect(described_class.count).to eq(5)
|
|
149
|
+
expect(described_class.deleted.count).to eq(1)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "can be accessed at random" do
|
|
153
|
+
expect { described_class.sample }.not_to raise_error
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe PUNK::Tenant do
|
|
4
|
+
it "is valid with valid attributes" do
|
|
5
|
+
expect { create(:tenant) }.not_to raise_error
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "is assigned a uuid on save" do
|
|
9
|
+
tenant = build(:tenant)
|
|
10
|
+
expect(tenant.id).to be_nil
|
|
11
|
+
tenant.save
|
|
12
|
+
expect(valid_uuid?(tenant.id)).to be(true)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "can be saved with a custom uuid" do
|
|
16
|
+
uuid = generate(:uuid)
|
|
17
|
+
tenant = create(:tenant, id: uuid)
|
|
18
|
+
expect(tenant.id).to eq(uuid)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "is invalid without a name" do
|
|
22
|
+
tenant = build(:tenant, name: nil)
|
|
23
|
+
expect(tenant.valid?).to be(false)
|
|
24
|
+
expect(tenant.errors[:name].first).to eq('is not present')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "is valid without an icon" do
|
|
28
|
+
tenant = build(:tenant, icon: nil)
|
|
29
|
+
expect(tenant.valid?).to be(true)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "is invalid if the icon is not a URL" do
|
|
33
|
+
tenant = build(:tenant, icon: Faker::Alphanumeric.alpha)
|
|
34
|
+
expect(tenant.valid?).to be(false)
|
|
35
|
+
expect(tenant.errors[:icon].first).to eq('is not a URL')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "can have multiple users" do
|
|
39
|
+
tenant = create(:tenant)
|
|
40
|
+
expect(tenant.users.count).to eq(0)
|
|
41
|
+
3.times { create(:user).add_tenant(tenant) }
|
|
42
|
+
expect(tenant.users.count).to eq(3)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "can have multiple groups" do
|
|
46
|
+
tenant = create(:tenant)
|
|
47
|
+
expect(tenant.groups.count).to eq(0)
|
|
48
|
+
create_list(:group, 3, tenant: tenant)
|
|
49
|
+
expect(tenant.groups.count).to eq(3)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe PUNK::TenantUserMetadata do
|
|
4
|
+
it "is valid with valid attributes" do
|
|
5
|
+
expect { create(:tenant_user_metadata) }.not_to raise_error
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "is invalid without a tenant" do
|
|
9
|
+
tenant_user_metadata = build(:tenant_user_metadata, tenant: nil)
|
|
10
|
+
expect(tenant_user_metadata.valid?).to be(false)
|
|
11
|
+
expect(tenant_user_metadata.errors[:tenant].first).to eq('is not present')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "is invalid without a user" do
|
|
15
|
+
tenant_user_metadata = build(:tenant_user_metadata, user: nil)
|
|
16
|
+
expect(tenant_user_metadata.valid?).to be(false)
|
|
17
|
+
expect(tenant_user_metadata.errors[:user].first).to eq('is not present')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "displays as the two IDs concatenated" do
|
|
21
|
+
tenant_user_metadata = create(:tenant_user_metadata)
|
|
22
|
+
expect(tenant_user_metadata.to_s).to include(tenant_user_metadata.tenant.id)
|
|
23
|
+
expect(tenant_user_metadata.to_s).to include(tenant_user_metadata.user.id)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context "when a user and a tenant exist" do
|
|
27
|
+
let(:user) { create(:user) }
|
|
28
|
+
let(:tenant) { create(:tenant) }
|
|
29
|
+
|
|
30
|
+
context "when a user is added to a tenant" do
|
|
31
|
+
let(:tenant_user_metadata) do
|
|
32
|
+
described_class[tenant: tenant, user: user]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
before do
|
|
36
|
+
tenant.add_user(user)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "is created automatically" do
|
|
40
|
+
expect(tenant_user_metadata).not_to be_nil
|
|
41
|
+
expect(tenant.users).to include(user)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "destroying it will remove the user from the tenant" do
|
|
45
|
+
expect(tenant.users).to include(user)
|
|
46
|
+
tenant_user_metadata.destroy
|
|
47
|
+
tenant.reload
|
|
48
|
+
expect(tenant.users).not_to include(user)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context "when it is created" do
|
|
53
|
+
it "adds a user to a tenant" do
|
|
54
|
+
expect(tenant.users).not_to include(user)
|
|
55
|
+
create(:tenant_user_metadata, tenant: tenant, user: user)
|
|
56
|
+
tenant.reload
|
|
57
|
+
expect(tenant.users).to include(user)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|