Skip to content
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

Add api endpoint to list all authorized clients by user #954

Merged
merged 6 commits into from
Aug 6, 2018

Conversation

kingjan1999
Copy link
Contributor

Resolves #953

As already mentioned in #953, I'm rather beginner in Go, so I'm open to comments and suggestions for improvement and ask for leniency for possible mistakes.

Signed-off-by: Jan Beckmann king-jan1999@hotmail.de

Resolves ory#953

Signed-off-by: Jan Beckmann <king-jan1999@hotmail.de>
return
}

sessions, err := h.M.FindPreviouslyGrantedConsentRequestsByUser(user)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really think we need pagination here, because this can be a lot! Examples can be found here, here and here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I adapted it. However, I was a bit unsure in consent/manager_memory.go as FindPreviouslyGrantedConsentRequests depends now on the newly created FindPreviouslyGrantedConsentRequestsByUser (which requires a limit and offset now) and does not support limit and offset. As you'll see, I've used a little workaround that I'm personally not 100% satisfied with.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, I don't think this solution will work with SQL as they don't support negative offset (I think).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh sorry, I didn't see that you duplicated the other method. Then it will obviously work. I agree that it's not the cleanest solution but it does get the job done for now. So from my side, this is fine.

var rs []HandledConsentRequest
filteredByUser, _ := m.FindPreviouslyGrantedConsentRequestsByUser(subject)
for _, c := range filteredByUser {
if client != c.ConsentRequest.Client.GetID() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can revert this logic to == and add rs = append(rs, c) in the loop, it is easier to read!

consent/types.go Outdated
@@ -96,7 +96,7 @@ type HandledConsentRequest struct {
// authorization will be remembered indefinitely.
RememberFor int `json:"remember_for"`

ConsentRequest *ConsentRequest `json:"-"`
ConsentRequest *ConsentRequest `json:"consent_request"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with exposing this is that acceptance of the consent request could overwrite this value and potentially mess stuff up. I haven't checked if that's actually the case but it could be an issue in some regression. I think it would be ok to copy this struct 1:1 and there set the consent_request value. If the order of the fields is the same, you can easily convert the type:

var foo HandledConsentRequest
var bar = NewTypeWithJSON(HandledConsentRequest)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I called it HandledConsentRequestResponse now but other suggestions are very welcome

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about PreviousConsentSession? :)

aeneasr
aeneasr approved these changes Jul 30, 2018
Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very solid already. It is really important though that we have a test for the SDK as well (sdk_test.go) and check that the values are populated properly (and also check that e.g. client secrets are removed). Once that is done and the things are addressed, I think this is good to go!

@aeneasr
Copy link
Member

aeneasr commented Aug 1, 2018

I'm pinging you @kingjan1999 so this doesn't get lost in your notifications. This looks already very solid, just a few things which I mentioned during review :)

Signed-off-by: Jan <king-jan1999@hotmail.de>
@kingjan1999
Copy link
Contributor Author

Thanks for your help @arekkas ! I hope I have implemented all your proposals.

When Swagger generated the SDK, some files (concerning JSONWebKeys) appeared for unknown reasons, which I have now simply commited.

@aeneasr
Copy link
Member

aeneasr commented Aug 2, 2018

The only thing left is the naming of the one struct and then this is good to get merged from my side! Thank you so much for your contribution :)

Signed-off-by: Jan <king-jan1999@hotmail.de>
@kingjan1999
Copy link
Contributor Author

Thanks for your naming suggestion @arekkas ! I've implemented it accordingly.

@aeneasr
Copy link
Member

aeneasr commented Aug 2, 2018

Perfect!

Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took another pass. Unfortunately, I have to nag you with some minor things (just newlines that were removed/added) and also some naming and error handling things.

Once those are addressed, I truly believe it's good to merge (unless I missed something).

Thank you, you're awesome! :)

@@ -162,6 +163,21 @@ func (m *MemoryManager) VerifyAndInvalidateConsentRequest(verifier string) (*Han
}

func (m *MemoryManager) FindPreviouslyGrantedConsentRequests(client string, subject string) ([]HandledConsentRequest, error) {
var rs []HandledConsentRequest
filteredByUser, _ := m.FindPreviouslyGrantedConsentRequestsByUser(subject, -1, -1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error must be handled here!

}
return nil, sqlcon.HandleError(err)
}
aa, err := m.resolveHandledConsentRequests(a)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can rewrite this to return m.resolveHandledConsentRequests(a)

va, err := v.toHandledConsentRequest(r)
if err != nil {
return nil, err
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-add newline

@@ -390,4 +415,5 @@ WHERE
}

return aa, nil

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove newline

@@ -376,12 +403,10 @@ WHERE
if v.RememberFor > 0 && v.RequestedAt.Add(time.Duration(v.RememberFor)*time.Second).Before(time.Now().UTC()) {
continue
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-add newline

}
aa, err := m.resolveHandledConsentRequests(a)
return aa, err

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove newline

if limit < 0 && offset < 0 {
return rs, nil
}
start, end := pagination.Index(limit, offset, len(rs))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a newline on top of start, end := ..

@@ -202,8 +214,11 @@ func (m *MemoryManager) FindPreviouslyGrantedConsentRequests(client string, subj
if len(rs) == 0 {
return []HandledConsentRequest{}, nil
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-add this newline

@@ -133,6 +135,55 @@ func (h *Handler) DeleteUserClientConsentSession(w http.ResponseWriter, r *http.
w.WriteHeader(http.StatusNoContent)
}

// swagger:route GET /oauth2/auth/sessions/consent/{user} oAuth2 listUserClientConsentSessions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the naming should be listUserConsentSessions. With the current naming, I would expect the method to be like listUserClientConsentSessions(user, client string)

LIMIT ? OFFSET ?
`), subject, limit, offset); err != nil {
if err == sql.ErrNoRows {
return nil, errors.WithStack(errNoPreviousConsentFound)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So one issue with this is that the HTTP handler function will return errNoPreviousConsentFound which is a "dumb" error (meaning it will return a 500 status code with no context in the API). On the same hand, this error is required to be returned for the consent_strategy to work. Since you duplicated the methods and this particular method is not used in the consent_strategy, you can remove the err == sql.ErrNoRows check and just return return nil, sqlcon.HandleError(err).

Please also add a test for this. It should check that sqlcon.ErrNoRows is returned when we expect that no session exist in the store. This will return a proper 404 error in the API which I think is to be expected here.

In the handler, you may want to choose to ignore the error of type sqlcon.ErrNoRows and instead just write an empty array. This will return [] instead of a 404 which might be a better suited response.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your help and your feedback! I have gladly implemented your suggestions.

However, I'm a little unsure at this point and need your help: Does db.Select really return an ErrNoRows error if no rows could be found? According to my understanding of SQLX / Go SQL documentation, this does not happen here. I have not been able to force such behaviour in my experiments.

Or did I misunderstand and the manager should generate and return an sqlcon.ErrNoRows?

Signed-off-by: Jan Beckmann <king-jan1999@hotmail.de>
Signed-off-by: Jan Beckmann <king-jan1999@hotmail.de>
@aeneasr
Copy link
Member

aeneasr commented Aug 6, 2018

Thank you for the updates! The newly generated SDK breaks tests because the methods have been renamed:

consent/sdk_test.go:121:24: sdk.ListUserClientConsentSessions undefined (type *hydra.CodeGenSDK has no field or method ListUserClientConsentSessions)
consent/sdk_test.go:128:23: sdk.ListUserClientConsentSessions undefined (type *hydra.CodeGenSDK has no field or method ListUserClientConsentSessions)

Signed-off-by: Jan Beckmann <king-jan1999@hotmail.de>
@aeneasr
Copy link
Member

aeneasr commented Aug 6, 2018

Thank you so much for your hard work!

@aeneasr aeneasr merged commit 7aace33 into ory:master Aug 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants