-
Notifications
You must be signed in to change notification settings - Fork 10
feat: add OAuth grants support #197
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
Changes from all commits
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 |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| require_relative "../lib/resend" | ||
|
|
||
| raise if ENV["RESEND_API_KEY"].nil? | ||
|
|
||
| Resend.api_key = ENV["RESEND_API_KEY"] | ||
|
|
||
| def list | ||
| grants = Resend::OAuthGrants.list | ||
| puts grants | ||
| end | ||
|
|
||
| def list_paginated | ||
| paginated_grants = Resend::OAuthGrants.list({ limit: 10, after: "grant_id_here" }) | ||
| puts "Paginated response:" | ||
| puts paginated_grants | ||
| puts "Has more: #{paginated_grants[:has_more]}" if paginated_grants[:has_more] | ||
| end | ||
|
|
||
| def revoke | ||
| grant = Resend::OAuthGrants.revoke("oauth_grant_id_here") | ||
| puts grant | ||
| end | ||
|
|
||
| list | ||
| # list_paginated | ||
| # revoke |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Resend | ||
| # oauth grants api wrapper | ||
| module OAuthGrants | ||
| class << self | ||
| # https://resend.com/docs/api-reference/oauth/list-grants | ||
| def list(params = {}) | ||
| path = Resend::PaginationHelper.build_paginated_path("oauth/grants", params) | ||
| Resend::Request.new(path, {}, "get").perform | ||
| end | ||
|
|
||
| # https://resend.com/docs/api-reference/oauth/revoke-grant | ||
| def revoke(oauth_grant_id = "") | ||
| path = "oauth/grants/#{oauth_grant_id}" | ||
| Resend::Request.new(path, {}, "delete").perform | ||
| end | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| RSpec.describe "OAuth Grants" do | ||
| shared_examples "oauth grants api" do | ||
| describe "list" do | ||
| it "should list oauth grants" do | ||
| resp = { | ||
| "object": "list", | ||
| "has_more": false, | ||
| "data": [ | ||
| { | ||
| "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e", | ||
|
Contributor
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. P2: The test mock responses use symbol keys for nested objects (via The SDK's Because the mock bypasses Consider using string keys ( Prompt for AI agents |
||
| "client_id": "client_123", | ||
| "scopes": ["emails:send"], | ||
| "resource": nil, | ||
| "created_at": "2023-04-21T01:31:02.671414+00:00", | ||
| "revoked_at": nil, | ||
| "revoked_reason": nil, | ||
| "client": { | ||
| "name": "My App", | ||
| "logo_uri": "https://example.com/logo.png" | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| allow_any_instance_of(Resend::Request).to receive(:perform).and_return(resp) | ||
| grants = Resend::OAuthGrants.list | ||
| expect(grants[:data].length).to eql(1) | ||
| expect(grants[:data].first[:id]).to eql("b6d24b8e-af0b-4c3c-be0c-359bbd97381e") | ||
| expect(grants[:has_more]).to be(false) | ||
| end | ||
|
|
||
| it "should build a paginated path" do | ||
|
Contributor
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. P3: Custom agent: No Use a declarative description without "should". "builds a paginated path" is more direct and follows the rule's guidance. Prompt for AI agents |
||
| expect(Resend::PaginationHelper).to receive(:build_paginated_path) | ||
| .with("oauth/grants", { limit: 10 }) | ||
| .and_return("oauth/grants?limit=10") | ||
| allow_any_instance_of(Resend::Request).to receive(:perform).and_return({}) | ||
| Resend::OAuthGrants.list({ limit: 10 }) | ||
| end | ||
| end | ||
|
|
||
| describe "revoke" do | ||
| it "should revoke an oauth grant" do | ||
| resp = { | ||
| "object": "oauth_grant", | ||
| "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e", | ||
| "revoked_at": "2023-04-22T10:00:00.000000+00:00", | ||
| "revoked_reason": "user_requested" | ||
| } | ||
| allow_any_instance_of(Resend::Request).to receive(:perform).and_return(resp) | ||
| grant = Resend::OAuthGrants.revoke("b6d24b8e-af0b-4c3c-be0c-359bbd97381e") | ||
| expect(grant[:id]).to eql("b6d24b8e-af0b-4c3c-be0c-359bbd97381e") | ||
| expect(grant[:revoked_reason]).to eql("user_requested") | ||
| end | ||
| end | ||
| end | ||
|
|
||
| context "static api_key" do | ||
| before do | ||
| Resend.configure do |config| | ||
| config.api_key = "re_123" | ||
| end | ||
| end | ||
|
|
||
| include_examples "oauth grants api" | ||
| end | ||
|
|
||
| context "dynamic api_key" do | ||
| before do | ||
| Resend.configure do |config| | ||
| config.api_key = -> { "re_123" } | ||
| end | ||
| end | ||
|
|
||
| include_examples "oauth grants api" | ||
| 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.
P3: Custom agent: No
shouldin testsUse a declarative description without "should". For example, "lists oauth grants" is clearer and more direct — it describes what the test verifies rather than what the code should hypothetically do.
Prompt for AI agents