diff --git a/consent/handler.go b/consent/handler.go index 78a5897d5da..e42fecccd55 100644 --- a/consent/handler.go +++ b/consent/handler.go @@ -157,9 +157,18 @@ func (h *Handler) GetConsentSessions(w http.ResponseWriter, r *http.Request, ps h.r.Writer().WriteError(w, r, errorsx.WithStack(fosite.ErrInvalidRequest.WithHint(`Query parameter 'subject' is not defined but should have been.`))) return } + loginSessionId := r.URL.Query().Get("login_session_id") limit, offset := pagination.Parse(r, 100, 0, 500) - s, err := h.r.ConsentManager().FindSubjectsGrantedConsentRequests(r.Context(), subject, limit, offset) + + var s []HandledConsentRequest + var err error + if len(loginSessionId) == 0 { + s, err = h.r.ConsentManager().FindSubjectsGrantedConsentRequests(r.Context(), subject, limit, offset) + } else { + s, err = h.r.ConsentManager().FindSubjectsSessionGrantedConsentRequests(r.Context(), subject, loginSessionId, limit, offset) + } + if errors.Is(err, ErrNoPreviousConsentFound) { h.r.Writer().Write(w, r, []PreviousConsentSession{}) return diff --git a/consent/manager.go b/consent/manager.go index f0fa286050b..22af11cd891 100644 --- a/consent/manager.go +++ b/consent/manager.go @@ -47,6 +47,7 @@ type Manager interface { VerifyAndInvalidateConsentRequest(ctx context.Context, verifier string) (*HandledConsentRequest, error) FindGrantedAndRememberedConsentRequests(ctx context.Context, client, user string) ([]HandledConsentRequest, error) FindSubjectsGrantedConsentRequests(ctx context.Context, user string, limit, offset int) ([]HandledConsentRequest, error) + FindSubjectsSessionGrantedConsentRequests(ctx context.Context, user, sid string, limit, offset int) ([]HandledConsentRequest, error) CountSubjectsGrantedConsentRequests(ctx context.Context, user string) (int, error) // Cookie management diff --git a/consent/manager_test_helpers.go b/consent/manager_test_helpers.go index 960fd50d865..0b243a028eb 100644 --- a/consent/manager_test_helpers.go +++ b/consent/manager_test_helpers.go @@ -616,6 +616,59 @@ func ManagerTests(m Manager, clientManager client.Manager, fositeManager x.Fosit _, err = m.HandleConsentRequest(context.Background(), "challengerv2", hcr2) require.NoError(t, err) + for i, tc := range []struct { + subject string + sid string + challenges []string + clients []string + }{ + { + subject: "subjectrv1", + sid: "fk-login-session-rv1", + challenges: []string{"challengerv1"}, + clients: []string{"fk-client-rv1"}, + }, + { + subject: "subjectrv2", + sid: "fk-login-session-rv2", + challenges: []string{"challengerv2"}, + clients: []string{"fk-client-rv2"}, + }, + { + subject: "subjectrv3", + sid: "fk-login-session-rv3", + challenges: []string{}, + clients: []string{}, + }, + } { + t.Run(fmt.Sprintf("case=%d/subject=%s/session=%s", i, tc.subject, tc.sid), func(t *testing.T) { + consents1, err := m.FindSubjectsGrantedConsentRequests(context.Background(), tc.subject, 100, 0) + consents2, _ := m.FindSubjectsSessionGrantedConsentRequests(context.Background(), tc.subject, tc.sid, 100, 0) + + if len(consents1) != 0 && len(consents2) == 0 { + fmt.Println("") + } + + consents, _ := m.FindSubjectsSessionGrantedConsentRequests(context.Background(), tc.subject, tc.sid, 100, 0) + assert.Equal(t, len(tc.challenges), len(consents)) + + if len(tc.challenges) == 0 { + assert.EqualError(t, err, ErrNoPreviousConsentFound.Error()) + } else { + require.NoError(t, err) + for _, consent := range consents { + assert.Contains(t, tc.challenges, consent.ID) + assert.Contains(t, tc.clients, consent.ConsentRequest.Client.OutfacingID) + } + } + + n, err := m.CountSubjectsGrantedConsentRequests(context.Background(), tc.subject) + require.NoError(t, err) + assert.Equal(t, n, len(tc.challenges)) + + }) + } + for i, tc := range []struct { subject string challenges []string diff --git a/persistence/sql/persister_consent.go b/persistence/sql/persister_consent.go index 923e951fa4a..e7bc3b14908 100644 --- a/persistence/sql/persister_consent.go +++ b/persistence/sql/persister_consent.go @@ -325,6 +325,25 @@ func (p *Persister) FindSubjectsGrantedConsentRequests(ctx context.Context, subj return p.resolveHandledConsentRequests(ctx, rs) } +func (p *Persister) FindSubjectsSessionGrantedConsentRequests(ctx context.Context, subject, sid string, limit, offset int) ([]consent.HandledConsentRequest, error) { + var rs []consent.HandledConsentRequest + c := p.Connection(ctx) + tn := consent.HandledConsentRequest{}.TableName() + + if err := c. + RawQuery("SELECT DISTINCT rh.* FROM hydra_oauth2_consent_request_handled rh JOIN hydra_oauth2_consent_request r ON r.challenge = rh.challenge JOIN hydra_oauth2_consent_request r_active ON r_active.client_id = r.client_id AND r_active.subject = r.subject WHERE r.subject = ? AND r.skip = FALSE AND rh.error = '{}' AND r_active.login_session_id = ?", subject, sid). + Order(fmt.Sprintf("%s.requested_at DESC", tn)). + Paginate(offset/limit+1, limit). + All(&rs); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, errorsx.WithStack(consent.ErrNoPreviousConsentFound) + } + return nil, sqlcon.HandleError(err) + } + + return p.resolveHandledConsentRequests(ctx, rs) +} + func (p *Persister) CountSubjectsGrantedConsentRequests(ctx context.Context, subject string) (int, error) { tn := consent.HandledConsentRequest{}.TableName()