Skip to content

feat(user-management): add invitation accept endpoint#448

Merged
gjtorikian merged 1 commit intoworkos:mainfrom
polleverywhere:accept-invitation-api
Mar 6, 2026
Merged

feat(user-management): add invitation accept endpoint#448
gjtorikian merged 1 commit intoworkos:mainfrom
polleverywhere:accept-invitation-api

Conversation

@andrewhampton
Copy link
Contributor

@andrewhampton andrewhampton commented Mar 6, 2026

Summary

  • add WorkOS::UserManagement.accept_invitation(id:) for POST /user_management/invitations/:id/accept
  • return parsed WorkOS::Invitation, consistent with existing invitation helpers
  • add spec coverage for request path/auth and response parsing

@andrewhampton andrewhampton requested review from a team as code owners March 6, 2026 17:26
@andrewhampton andrewhampton requested review from dandorman and removed request for a team March 6, 2026 17:26
@andrewhampton andrewhampton force-pushed the accept-invitation-api branch from c842f05 to 438502a Compare March 6, 2026 17:26
@greptile-apps
Copy link

greptile-apps bot commented Mar 6, 2026

Greptile Summary

This PR adds an accept_invitation endpoint to WorkOS::UserManagement, allowing callers to accept an existing invitation by ID. The implementation is minimal, correct, and follows the exact same pattern as the existing revoke_invitation and resend_invitation methods.

Implementation (lib/workos/user_management.rb): New accept_invitation(id:) method issues an authenticated POST to /user_management/invitations/{id}/accept and returns a parsed WorkOS::Invitation — fully consistent with surrounding code.

Tests (spec/lib/workos/user_management_spec.rb): A mock-based spec verifies the request path, auth flag, and response parsing for the happy path. However, error-case coverage is absent — unlike revoke_invitation and resend_invitation, which both include test contexts for failure scenarios (invalid invitation IDs, expired invitations, etc.). This represents a gap in test consistency that could be addressed with mock-based error cases.

No security, logic, or syntax concerns with the implementation itself.

Confidence Score: 4/5

  • Safe to merge; the implementation is correct and consistent with established patterns. The main gap is test coverage completeness.
  • The production code change is a clean, single-method addition that mirrors existing patterns exactly. The happy-path test properly verifies request structure and response parsing. The lower-than-perfect score reflects the absence of error-case test coverage (invalid IDs, already-accepted invitations, etc.), which are present in comparable methods. This is a test quality issue rather than a correctness issue.
  • spec/lib/workos/user_management_spec.rb — missing error-case coverage for accept_invitation.

Important Files Changed

Filename Overview
lib/workos/user_management.rb Adds accept_invitation(id:) following the exact same structure as revoke_invitation and resend_invitation — POST to /user_management/invitations/{id}/accept with auth, returns parsed WorkOS::Invitation. Implementation is clean and consistent with existing patterns.
spec/lib/workos/user_management_spec.rb Adds mock-based spec for accept_invitation verifying the happy path: request path, auth flag, and response parsing are correct. Coverage is limited to the happy path only — error-case contexts (e.g., invalid invitation ID) that are present in comparable methods (revoke_invitation, resend_invitation) are absent here, representing a consistency gap in test coverage.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant UserManagement as WorkOS::UserManagement
    participant API as WorkOS API

    Caller->>UserManagement: accept_invitation(id:)
    UserManagement->>UserManagement: post_request(path: /user_management/invitations/{id}/accept, auth: true)
    UserManagement->>API: POST /user_management/invitations/{id}/accept
    API-->>UserManagement: 200 OK (Invitation JSON)
    UserManagement->>UserManagement: WorkOS::Invitation.new(response.body)
    UserManagement-->>Caller: WorkOS::Invitation
Loading

Last reviewed commit: 438502a

Comment on lines +1731 to +1760
describe '.accept_invitation' do
context 'with a valid id' do
it 'accepts invitation' do
expect(described_class).to receive(:post_request) do |options|
expect(options[:path]).to eq('/user_management/invitations/invitation_123/accept')
expect(options[:auth]).to be true

double('request')
end.and_return(double('request'))

response_body = {
id: 'invitation_123',
email: 'test@workos.com',
state: 'accepted',
}.to_json

expect(described_class).to receive(:execute_request).and_return(
double('response', body: response_body),
)

invitation = described_class.accept_invitation(
id: 'invitation_123',
)

expect(invitation.id).to eq('invitation_123')
expect(invitation.email).to eq('test@workos.com')
expect(invitation.state).to eq('accepted')
end
end
end
Copy link

Choose a reason for hiding this comment

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

Unlike the comparable revoke_invitation and resend_invitation specs, there is no test context for failure scenarios (e.g. invitation not found, invitation already accepted). Both of those methods include error-case contexts ('with an invalid payload' for revoke_invitation at line 1776, and 'with an invalid id' / 'when invitation has expired' / etc. for resend_invitation starting at line 1806) that exercise the error path via VCR cassette.

Even if the VCR cassette is blocked for now, a context 'with an invalid id' block using the same mock-based approach would be straightforward to add and improve coverage consistency.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Contributor

@gjtorikian gjtorikian left a comment

Choose a reason for hiding this comment

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

As noted by Greptile, the error-case test coverage is missing for accept_invitation. Here's a suggestion to add tests for invalid IDs and already-accepted invitations, matching the pattern used by revoke_invitation and resend_invitation.

Comment on lines +1759 to +1760
end
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
end
end
end
context 'with an invalid id' do
it 'returns an error' do
expect(described_class).to receive(:post_request).and_return(double('request'))
expect(described_class).to receive(:execute_request).and_raise(
WorkOS::NotFoundError.new(message: 'Invitation not found'),
)
expect do
described_class.accept_invitation(id: 'invalid_id')
end.to raise_error(
WorkOS::NotFoundError,
/Invitation not found/,
)
end
end
context 'when invitation has already been accepted' do
it 'returns an error' do
expect(described_class).to receive(:post_request).and_return(double('request'))
expect(described_class).to receive(:execute_request).and_raise(
WorkOS::InvalidRequestError.new(message: 'Invite has already been accepted'),
)
expect do
described_class.accept_invitation(id: 'invitation_123')
end.to raise_error(
WorkOS::InvalidRequestError,
/Invite has already been accepted/,
)
end
end
end

@andrewhampton andrewhampton force-pushed the accept-invitation-api branch from 438502a to 63c0f76 Compare March 6, 2026 18:07
@andrewhampton andrewhampton force-pushed the accept-invitation-api branch from 63c0f76 to 94be40b Compare March 6, 2026 18:16
@andrewhampton
Copy link
Contributor Author

Thanks for the feedback @gjtorikian. I've added those specs.

@gjtorikian gjtorikian merged commit b5b4da1 into workos:main Mar 6, 2026
5 checks passed
@gjtorikian
Copy link
Contributor

thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants