Skip to content

Commit

Permalink
Membership: Revoke memberships from an organization
Browse files Browse the repository at this point in the history
  • Loading branch information
ansmonjol committed Sep 6, 2022
1 parent 53048e2 commit 30660a3
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 0 deletions.
22 changes: 22 additions & 0 deletions app/graphql/mutations/memberships/revoke.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module Mutations
module Memberships
class Revoke < BaseMutation
include AuthenticableApiUser

graphql_name 'RevokeMembership'
description 'Revoke a membership'

argument :id, ID, required: true

type Types::MembershipType

def resolve(id:)
result = ::Memberships::RevokeService.new(context[:current_user]).revoke(id)

result.success? ? result.membership : result_error(result)
end
end
end
end
2 changes: 2 additions & 0 deletions app/graphql/types/mutation_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,7 @@ class MutationType < Types::BaseObject
field :terminate_customer_wallet, mutation: Mutations::Wallets::Terminate

field :create_customer_wallet_transaction, mutation: Mutations::WalletTransactions::Create

field :revoke_membership, mutation: Mutations::Memberships::Revoke
end
end
24 changes: 24 additions & 0 deletions app/services/memberships/revoke_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Memberships
class RevokeService < BaseService
def revoke(id)
membership = Membership.find_by(id: id)
return result.fail!(code: 'not_found') unless membership

if result.user.id == membership.user.id
return result.fail!(
code: 'unprocessable_entity',
message: 'revoke_own_membership',
)
end

membership.mark_as_revoked!

result.membership = membership
result
rescue ActiveRecord::RecordInvalid => e
result.fail_with_validations!(e.record)
end
end
end
21 changes: 21 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -2937,6 +2937,16 @@ type Mutation {
input: RegisterUserInput!
): RegisterUser

"""
Revoke a membership
"""
revokeMembership(
"""
Parameters for RevokeMembership
"""
input: RevokeMembershipInput!
): Membership

"""
Unassign a coupon from a customer
"""
Expand Down Expand Up @@ -3384,6 +3394,17 @@ input RegisterUserInput {
password: String!
}

"""
Autogenerated input type of RevokeMembership
"""
input RevokeMembershipInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
id: ID!
}

enum StatusTypeEnum {
active
canceled
Expand Down
68 changes: 68 additions & 0 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -9558,6 +9558,35 @@
}
]
},
{
"name": "revokeMembership",
"description": "Revoke a membership",
"type": {
"kind": "OBJECT",
"name": "Membership",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null,
"args": [
{
"name": "input",
"description": "Parameters for RevokeMembership",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "RevokeMembershipInput",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
]
},
{
"name": "terminateAppliedCoupon",
"description": "Unassign a coupon from a customer",
Expand Down Expand Up @@ -11997,6 +12026,45 @@
],
"enumValues": null
},
{
"kind": "INPUT_OBJECT",
"name": "RevokeMembershipInput",
"description": "Autogenerated input type of RevokeMembership",
"interfaces": null,
"possibleTypes": null,
"fields": null,
"inputFields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "id",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"enumValues": null
},
{
"kind": "ENUM",
"name": "StatusTypeEnum",
Expand Down
49 changes: 49 additions & 0 deletions spec/graphql/mutations/memberships/revoke_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Mutations::Memberships::Revoke, type: :graphql do
let(:membership) { create(:membership) }
let(:organization) { membership.organization }

let(:mutation) do
<<-GQL
mutation($input: RevokeMembershipInput!) {
revokeMembership(input: $input) {
id
revokedAt
}
}
GQL
end

it 'Revokes a membership' do
user = create(:user)

result = execute_graphql(
current_user: user,
query: mutation,
variables: {
input: { id: membership.id },
},
)

data = result['data']['revokeMembership']

expect(data['id']).to eq(membership.id)
expect(data['revokedAt']).to be_present
end

it 'Cannot Revoke my own membership' do
result = execute_graphql(
current_user: membership.user,
query: mutation,
variables: {
input: { id: membership.id },
},
)

expect(result['errors'].first['message']).to eq('revoke_own_membership')
expect(result['errors'].first['extensions']['status']).to eq(422)
end
end
40 changes: 40 additions & 0 deletions spec/services/memberships/revoke_service_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Memberships::RevokeService, type: :service do
subject(:revoke_service) { described_class.new(membership.user) }

let(:membership) { create(:membership) }

describe '.revoke' do
context 'when revoking my own membership' do
it 'returns an error' do
result = revoke_service.revoke(membership.id)

expect(result).not_to be_success
expect(result.error).to eq('revoke_own_membership')
end
end

context 'when membership is not found' do
it 'returns an error' do
result = revoke_service.revoke(nil)

expect(result).not_to be_success
expect(result.error).to eq('not_found')
end
end

context 'when revoking another membership' do
let(:another_membership) { create(:membership) }

it 'revokes the memembership' do
result = revoke_service.revoke(another_membership.id)

expect(result).to be_success
expect(result.membership.id).to eq(another_membership.id)
end
end
end
end

0 comments on commit 30660a3

Please sign in to comment.