-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #815 from aviav/extend-query-interface
Extend query interface
- Loading branch information
Showing
7 changed files
with
235 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
module Pageflow | ||
# Query accounts for members, e.g. based on role | ||
class AccountMemberQuery < ApplicationQuery | ||
class Scope < ApplicationQuery::Scope | ||
# Account whose members we scope | ||
# @return [Pageflow::Account] | ||
attr_reader :account | ||
|
||
# Base scope which is further scoped according to account role | ||
# @return [ActiveRecord::Relation<User>] | ||
attr_reader :scope | ||
|
||
# Create scope that can limit base scope to account members at | ||
# or above a given role | ||
# | ||
# @param [Pageflow::Account] account | ||
# Required. Membership account to check. | ||
# @param [ActiveRecord::Relation<User>] scope | ||
# Optional. Membership entity to check. | ||
def initialize(account, scope = User.all) | ||
@account = account | ||
@scope = scope | ||
end | ||
|
||
# Scope to those members from scope on account who have at least | ||
# role | ||
# | ||
# @param [String] role | ||
# Required. Minimum role that we compare against. | ||
# @return [ActiveRecord::Relation<User>] | ||
def with_role_at_least(role) | ||
scope.joins(memberships_for_account_with_at_least_role(role)) | ||
.where(membership_is_present) | ||
end | ||
|
||
private | ||
|
||
def memberships_for_account_with_at_least_role(role) | ||
options = {roles: Roles.at_least(role), account_id: account.id} | ||
|
||
sanitize_sql(<<-SQL, options) | ||
LEFT OUTER JOIN pageflow_memberships as | ||
pageflow_account_memberships ON | ||
pageflow_account_memberships.user_id = users.id AND | ||
pageflow_account_memberships.role IN (:roles) AND | ||
pageflow_account_memberships.entity_id = :account_id AND | ||
pageflow_account_memberships.entity_type = 'Pageflow::Account' | ||
SQL | ||
end | ||
|
||
def membership_is_present | ||
'pageflow_account_memberships.entity_id IS NOT NULL' | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
module Pageflow | ||
# Query users for their role on accounts based on role | ||
class AccountRoleQuery | ||
# Create query that can be used for role comparisons | ||
# | ||
# @param [User] user | ||
# Required. Membership user to check. | ||
# @param [Pageflow::Account] account | ||
# Required. Membership entity to check. | ||
def initialize(user, account) | ||
@user = user | ||
@account = account | ||
end | ||
|
||
# Return true if there is a membership with at least role for | ||
# user/account | ||
# | ||
# @param [String] role | ||
# Required. Minimum role that we compare against. | ||
# @return [Boolean] | ||
def has_at_least_role?(role) | ||
@user | ||
.memberships | ||
.where(role: Roles.at_least(role)) | ||
.where('(entity_id = :account_id AND '\ | ||
"entity_type = 'Pageflow::Account')", | ||
account_id: @account.id) | ||
.any? | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module Pageflow | ||
# Abstraction layer for Pageflow's query interface | ||
class ApplicationQuery | ||
class Scope | ||
protected | ||
|
||
# @api private | ||
def sanitize_sql(sql, interpolations) | ||
ActiveRecord::Base.send(:sanitize_sql_array, [sql, interpolations]) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
require 'spec_helper' | ||
|
||
module Pageflow | ||
describe AccountMemberQuery do | ||
describe AccountMemberQuery::Scope do | ||
describe '.with_role_at_least' do | ||
it 'includes members with account membership with required role' do | ||
user = create(:user) | ||
account = create(:account, with_previewer: user) | ||
|
||
result = AccountMemberQuery::Scope.new(account) | ||
.with_role_at_least(:previewer) | ||
|
||
expect(result).to include(user) | ||
end | ||
|
||
it 'includes members with account membership with stronger role' do | ||
user = create(:user) | ||
account = create(:account, with_editor: user) | ||
|
||
result = AccountMemberQuery::Scope.new(account) | ||
.with_role_at_least(:previewer) | ||
|
||
expect(result).to include(user) | ||
end | ||
|
||
it 'does not include members with account membership with '\ | ||
'insufficient role' do | ||
user = create(:user) | ||
account = create(:account, with_member: user) | ||
|
||
result = AccountMemberQuery::Scope.new(account) | ||
.with_role_at_least(:previewer) | ||
|
||
expect(result).not_to include(user) | ||
end | ||
|
||
it 'does not include members with required role on other account' do | ||
user = create(:user) | ||
account = create(:account, with_member: user) | ||
create(:account, with_previewer: user) | ||
|
||
result = AccountMemberQuery::Scope.new(account) | ||
.with_role_at_least(:previewer) | ||
|
||
expect(result).not_to include(user) | ||
end | ||
|
||
it 'does not include members with required role on entry of account' do | ||
user = create(:user) | ||
account = create(:account, with_member: user) | ||
create(:entry, with_previewer: user) | ||
|
||
result = AccountMemberQuery::Scope.new(account) | ||
.with_role_at_least(:previewer) | ||
|
||
expect(result).not_to include(user) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
require 'spec_helper' | ||
|
||
module Pageflow | ||
describe AccountRoleQuery do | ||
describe '.has_at_least_role?' do | ||
it 'returns true if user has account membership with given role' do | ||
user = create(:user) | ||
account = create(:account, with_publisher: user) | ||
|
||
result = AccountRoleQuery.new(user, account) | ||
.has_at_least_role?(:publisher) | ||
|
||
expect(result).to be true | ||
end | ||
|
||
it 'returns true if user has account membership with stronger role' do | ||
user = create(:user) | ||
account = create(:account, with_manager: user) | ||
|
||
result = AccountRoleQuery.new(user, account) | ||
.has_at_least_role?(:publisher) | ||
|
||
expect(result).to be true | ||
end | ||
|
||
it 'returns false if user has account membership with weaker role' do | ||
user = create(:user) | ||
account = create(:account, with_editor: user) | ||
|
||
result = AccountRoleQuery.new(user, account) | ||
.has_at_least_role?(:publisher) | ||
|
||
expect(result).to be false | ||
end | ||
|
||
it 'returns false if user has entry membership with given role on '\ | ||
'account' do | ||
user = create(:user) | ||
account = create(:account, with_editor: user) | ||
create(:entry, with_publisher: user) | ||
|
||
result = AccountRoleQuery.new(user, account) | ||
.has_at_least_role?(:publisher) | ||
|
||
expect(result).to be false | ||
end | ||
|
||
it 'returns false if user has account membership with given role on '\ | ||
'other account' do | ||
user = create(:user) | ||
account = create(:account, with_editor: user) | ||
create(:account, with_publisher: user) | ||
|
||
result = AccountRoleQuery.new(user, account) | ||
.has_at_least_role?(:publisher) | ||
|
||
expect(result).to be false | ||
end | ||
end | ||
end | ||
end |