-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use token list of accounts for user authorization #240
Changes from 4 commits
b11c0f0
862f874
cde1998
5cb4e8b
a1d1bb6
ad87223
c9ade9b
3dcd64a
dded0e4
af9cafb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,8 @@ class User < BaseModel | |
|
||
after_commit :create_individual_account, on: [:create] | ||
|
||
attr_accessor :approved_accounts | ||
|
||
def individual_account | ||
accounts.where('type = \'IndividualAccount\'').first | ||
end | ||
|
@@ -45,25 +47,15 @@ def name | |
"#{first_name} #{last_name}" | ||
end | ||
|
||
def approved_accounts | ||
Account. | ||
joins('LEFT OUTER JOIN `memberships` ON `memberships`.`account_id` = `accounts`.`id`'). | ||
where(['memberships.user_id = ? and memberships.approved is true', id]) | ||
end | ||
|
||
def approved_active_accounts | ||
approved_accounts.active | ||
approved_accounts.try(:active) | ||
end | ||
|
||
def approved_account_stories | ||
Story. | ||
joins('LEFT OUTER JOIN `memberships` ON `memberships`.`account_id` = `pieces`.`account_id`'). | ||
where(['memberships.user_id = ? and memberships.approved is true', id]) | ||
!approved_accounts.nil? ? Story.where(account_id: approved_accounts.try(:ids)) : [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could certainly be in there! I'm not quite sure where to place the method definitions for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, that is annoying - looks like they do get used for counts in the authorization_representer, but only that one representer at least. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can talk about it when I get in - one way to handle this may be to create an
And then the authorization model is basically a wrapper around the token, accessing the related user(well, user_id, feeder would have to make a remote call to getthe user), and could also return the approved_accounts and such:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would separate the idea of what info comes from the token and it's list of accounts vs. the user and the list of all member accounts, might be better? |
||
end | ||
|
||
def approved_account_series | ||
Series. | ||
joins('LEFT OUTER JOIN `memberships` ON `memberships`.`account_id` = `series`.`account_id`'). | ||
where(['memberships.user_id = ? and memberships.approved is true', id]) | ||
!approved_accounts.nil? ? Series.where(account_id: approved_accounts.try(:ids)) : [] | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,12 +3,17 @@ | |
describe Api::Auth::AccountsController do | ||
|
||
let (:user) { create(:user_with_accounts, group_accounts: 2) } | ||
let (:token) { OpenStruct.new.tap { |t| t.user_id = user.id } } | ||
let (:individual_account) { user.individual_account } | ||
let (:member_account) { user.accounts.member.first } | ||
let (:unapproved_account) { user.accounts.member.last } | ||
let (:random_account) { create(:account) } | ||
before { unapproved_account.memberships.first.update!(approved: false) } | ||
let (:member_account) { create(:account) } | ||
let (:unapproved_account) { create(:account) } | ||
let (:token) { StubToken.new(nil, nil, user.id) } | ||
|
||
before do | ||
token.authorized_resources = { | ||
member_account.id => 'member', | ||
individual_account.id => 'admin' | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. } at 17, 4 is not aligned with StubToken.new(nil, nil, user.id).tap { |t| at 12, 17 or let (:token) { StubToken.new(nil, nil, user.id).tap { |t| at 12, 2. |
||
end | ||
|
||
describe 'with a valid token' do | ||
|
||
|
@@ -31,11 +36,6 @@ | |
assert_response :not_found | ||
end | ||
|
||
it 'does not show non-member accounts' do | ||
get(:show, api_version: 'v1', id: random_account.id) | ||
assert_response :not_found | ||
end | ||
|
||
it 'indexes only member accounts' do | ||
get(:index, api_version: 'v1') | ||
assert_response :success | ||
|
@@ -46,7 +46,6 @@ | |
ids.must_include individual_account.id | ||
ids.must_include member_account.id | ||
ids.wont_include unapproved_account.id | ||
ids.wont_include random_account.id | ||
end | ||
|
||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,12 @@ | |
describe User do | ||
let (:user) { create(:user) } | ||
let (:network) { create(:network, account: user.individual_account) } | ||
let (:story) { create(:story, account: user.individual_account) } | ||
let (:series) { create(:series, account: user.individual_account) } | ||
|
||
before do | ||
user.approved_accounts = Account.where(id: [story.account_id, series.account_id]) | ||
end | ||
|
||
it 'has a table defined' do | ||
User.table_name.must_equal 'users' | ||
|
@@ -39,9 +45,8 @@ | |
user.networks.must_include network | ||
end | ||
|
||
it 'has a list of stories for approved accounts' do | ||
start_count = user.individual_account.stories.count | ||
create(:account, user: user, stories_count: 2) | ||
user.approved_account_stories.count.must_equal start_count + 2 | ||
it 'has a list of stories and series for accounts approved on token' do | ||
user.approved_account_stories.must_include story | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you leaving the User methods like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
user.approved_account_series.must_include series | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we want the user model, which is retrieved from the DB and is in the model layer, also aware of the token and its contents which come from the controller layer. Seems like we are having controller / request logic and information leak into the model which should not be aware of or rely on that layer.
The other part of this is that it is could be misleading, because the user may have a different set of accounts they can access than is allowed by and listed in the token.
For example, you could generate a token with only a subset of the actual accounts the user has access to, or using client credentials, get a different account entirely in
aur
than is reflected in the user's account membership.So the more I think about it, it seems like with the move to get authorized accounts from the token, not the user, they become 2 different things - there is the user that logged in, and the list of accounts authorized in the token, and they are not necessarily related except for having both been identified in the token.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious what @cavis might say about this as well - with the separation of accounts and users, where the token provides the list of accounts not the user, I think it makes sense to move these methods using the list of accounts out of the user model, perhaps into methods on the
ApiAuthenticated
concern, or just in the relevant controller?