Skip to content

Commit

Permalink
Fixes the workflow for revoking a block on a user (un-blocking). (#1890)
Browse files Browse the repository at this point in the history
* Updated blockUser.ts

* Updated sendMembershipRequest.ts

* Updated unblockUser.ts

* Added tests

---------

Co-authored-by: Peter Harrison <16875803+palisadoes@users.noreply.github.com>
  • Loading branch information
Sahi1l-Kumar and palisadoes authored Mar 11, 2024
1 parent 9cb6272 commit d34aa8a
Show file tree
Hide file tree
Showing 9 changed files with 530 additions and 54 deletions.
9 changes: 7 additions & 2 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,13 @@ export const MEMBERSHIP_REQUEST_NOT_FOUND_ERROR = {
MESSAGE: "membershipRequest.notFound",
PARAM: "membershipRequest",
};
export const MEMBERSHIP_REQUEST_ALREADY_EXISTS =
"Membership Request already exists";

export const MEMBERSHIP_REQUEST_ALREADY_EXISTS = {
DESC: "Membership Request already exists",
CODE: "membershipRequest.alreadyExists",
MESSAGE: "membershipRequest.alreadyExists",
PARAM: "membershipRequest",
};

export const ORGANIZATION_MEMBER_NOT_FOUND_ERROR = {
DESC: "Organization's user is not a member",
Expand Down
16 changes: 14 additions & 2 deletions src/resolvers/Mutation/blockUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ export const blockUser: MutationResolvers["blockUser"] = async (
_id: args.organizationId,
}).lean();

await cacheOrganizations([organization!]);
if (organization) {
await cacheOrganizations([organization]);
}
}

// Checks whether organization exists.
Expand Down Expand Up @@ -105,7 +107,10 @@ export const blockUser: MutationResolvers["blockUser"] = async (
);
}

// Adds args.userId to blockedUsers list on organization's document.
/*
Adds args.userId to blockedUsers list on organization's document.
Removes args.userId from the organization's members list
*/
const updatedOrganization = await Organization.findOneAndUpdate(
{
_id: organization._id,
Expand All @@ -114,6 +119,9 @@ export const blockUser: MutationResolvers["blockUser"] = async (
$push: {
blockedUsers: args.userId,
},
$pull: {
members: args.userId,
},
},
{
new: true,
Expand All @@ -127,6 +135,7 @@ export const blockUser: MutationResolvers["blockUser"] = async (
/*
Adds organization._id to organizationsBlockedBy list on user's document
with _id === args.userId and returns the updated user.
Remove organization's id from joinedOrganizations list on args.userId.
*/
return await User.findOneAndUpdate(
{
Expand All @@ -136,6 +145,9 @@ export const blockUser: MutationResolvers["blockUser"] = async (
$push: {
organizationsBlockedBy: organization._id,
},
$pull: {
joinedOrganizations: organization._id,
},
},
{
new: true,
Expand Down
19 changes: 18 additions & 1 deletion src/resolvers/Mutation/joinPublicOrganization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ export const joinPublicOrganization: MutationResolvers["joinPublicOrganization"]
_id: args.organizationId,
}).lean();

await cacheOrganizations([organization!]);
if (organization !== null) {
await cacheOrganizations([organization]);
}
}

// Checks whether organization exists.
Expand Down Expand Up @@ -82,6 +84,21 @@ export const joinPublicOrganization: MutationResolvers["joinPublicOrganization"]
);
}

// Checks if the user is blocked
const user = await User.findById(context.userId).lean();
if (
user !== null &&
organization.blockedUsers.some((blockedUser) =>
Types.ObjectId(blockedUser).equals(user._id),
)
) {
throw new errors.UnauthorizedError(
requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE),
USER_NOT_AUTHORIZED_ERROR.CODE,
USER_NOT_AUTHORIZED_ERROR.PARAM,
);
}

// Adds context.userId to members list of organzation's document.
const updatedOrganization = await Organization.findOneAndUpdate(
{
Expand Down
58 changes: 52 additions & 6 deletions src/resolvers/Mutation/sendMembershipRequest.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import {
MEMBERSHIP_REQUEST_NOT_FOUND_ERROR,
MEMBERSHIP_REQUEST_ALREADY_EXISTS,
ORGANIZATION_NOT_FOUND_ERROR,
USER_NOT_FOUND_ERROR,
USER_NOT_AUTHORIZED_ERROR,
USER_ALREADY_MEMBER_ERROR,
} from "../../constants";
import type { MutationResolvers } from "../../types/generatedGraphQLTypes";
import { errors, requestContext } from "../../libraries";
import { User, MembershipRequest, Organization } from "../../models";
import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache";
import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations";
import { Types } from "mongoose";
/**
* This function enables to send membership request.
* @param _parent - parent of current request
* @param args - payload provided with the request
* @param context - context of entire application
* @remarks The following checks are done:
* 1. If the user exists.
* 2. If the organization exists
* 1. If the organization exists
* 2. If the user exists.
* 3. If the membership request already exists.
* @returns Membership request.
*/
Expand Down Expand Up @@ -46,16 +50,58 @@ export const sendMembershipRequest: MutationResolvers["sendMembershipRequest"] =
);
}

const userExists = await User.exists({
_id: context.userId,
});

// Checks whether user exists.
if (userExists === false) {
throw new errors.NotFoundError(
requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE),
USER_NOT_FOUND_ERROR.CODE,
USER_NOT_FOUND_ERROR.PARAM,
);
}

// Checks if the user is already a member of the organization
const isMember = organization.members.some((member) =>
Types.ObjectId(member).equals(context.userId),
);

if (isMember === true) {
throw new errors.ConflictError(
requestContext.translate(USER_ALREADY_MEMBER_ERROR.MESSAGE),
USER_ALREADY_MEMBER_ERROR.CODE,
USER_ALREADY_MEMBER_ERROR.PARAM,
);
}

// Checks if the user is blocked
const user = await User.findById(context.userId).lean();
if (
user !== null &&
organization.blockedUsers.some((blockedUser) =>
Types.ObjectId(blockedUser).equals(user._id),
)
) {
throw new errors.UnauthorizedError(
requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE),
USER_NOT_AUTHORIZED_ERROR.CODE,
USER_NOT_AUTHORIZED_ERROR.PARAM,
);
}

// Checks if the membership request already exists
const membershipRequestExists = await MembershipRequest.exists({
user: context.userId,
organization: organization._id,
});

if (membershipRequestExists === true) {
throw new errors.ConflictError(
requestContext.translate(MEMBERSHIP_REQUEST_NOT_FOUND_ERROR.MESSAGE),
MEMBERSHIP_REQUEST_NOT_FOUND_ERROR.CODE,
MEMBERSHIP_REQUEST_NOT_FOUND_ERROR.PARAM,
requestContext.translate(MEMBERSHIP_REQUEST_ALREADY_EXISTS.MESSAGE),
MEMBERSHIP_REQUEST_ALREADY_EXISTS.CODE,
MEMBERSHIP_REQUEST_ALREADY_EXISTS.PARAM,
);
}

Expand Down
65 changes: 62 additions & 3 deletions src/resolvers/Mutation/unblockUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
USER_NOT_FOUND_ERROR,
} from "../../constants";
import type { InterfaceOrganization } from "../../models";
import { Organization, User } from "../../models";
import { MembershipRequest, Organization, User } from "../../models";
import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations";
import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache";
import { Types } from "mongoose";
Expand Down Expand Up @@ -37,8 +37,9 @@ export const unblockUser: MutationResolvers["unblockUser"] = async (
organization = await Organization.findOne({
_id: args.organizationId,
}).lean();

await cacheOrganizations([organization!]);
if (organization) {
await cacheOrganizations([organization]);
}
} else {
organization = organizationFoundInCache[0];
}
Expand Down Expand Up @@ -99,6 +100,64 @@ export const unblockUser: MutationResolvers["unblockUser"] = async (
).lean();

if (updatedOrganization !== null) {
if (updatedOrganization.userRegistrationRequired === true) {
// create a membership request for the user
const createdMembershipRequest = await MembershipRequest.create({
user: user._id,
organization: organization._id,
});
// add membership request to organization
await Organization.findOneAndUpdate(
{
_id: organization._id,
},
{
$push: {
membershipRequests: createdMembershipRequest._id,
},
},
{
new: true,
},
).lean();
// add membership request to user
await User.updateOne(
{
_id: user._id,
},
{
$push: {
membershipRequests: createdMembershipRequest._id,
},
},
);
} else {
// add user to the members list inside the organization record
await Organization.findOneAndUpdate(
{
_id: organization._id,
},
{
$push: {
members: user._id,
},
},
{
new: true,
},
).lean();
// add organization to the joinedOrganizations list inside the user record
await User.updateOne(
{
_id: user._id,
},
{
$push: {
joinedOrganizations: organization._id,
},
},
).lean();
}
await cacheOrganizations([updatedOrganization]);
}
// remove the organization from the organizationsBlockedBy array inside the user record
Expand Down
30 changes: 18 additions & 12 deletions tests/resolvers/Mutation/blockUser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ describe("resolvers -> Mutation -> blockUser", () => {
};

await blockUserResolver?.({}, args, context);
} catch (error: any) {
expect(error.message).toEqual(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE);
} catch (error: unknown) {
expect((error as Error).message).toEqual(
ORGANIZATION_NOT_FOUND_ERROR.MESSAGE,
);
}
});

Expand All @@ -107,8 +109,8 @@ describe("resolvers -> Mutation -> blockUser", () => {
};

await blockUserResolver?.({}, args, context);
} catch (error: any) {
expect(error.message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE);
} catch (error: unknown) {
expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE);
}
});

Expand All @@ -132,8 +134,8 @@ describe("resolvers -> Mutation -> blockUser", () => {
);

await blockUserResolverError?.({}, args, context);
} catch (error: any) {
expect(error.message).toEqual(MEMBER_NOT_FOUND_ERROR.MESSAGE);
} catch (error: unknown) {
expect((error as Error).message).toEqual(MEMBER_NOT_FOUND_ERROR.MESSAGE);
}
});

Expand All @@ -157,8 +159,8 @@ describe("resolvers -> Mutation -> blockUser", () => {
);

await blockUserResolverError?.({}, args, context);
} catch (error: any) {
expect(error.message).toEqual(USER_BLOCKING_SELF.MESSAGE);
} catch (error: unknown) {
expect((error as Error).message).toEqual(USER_BLOCKING_SELF.MESSAGE);
}
});

Expand Down Expand Up @@ -193,8 +195,10 @@ describe("resolvers -> Mutation -> blockUser", () => {
};

await blockUserResolver?.({}, args, context);
} catch (error: any) {
expect(error.message).toEqual(USER_NOT_AUTHORIZED_ADMIN.MESSAGE);
} catch (error: unknown) {
expect((error as Error).message).toEqual(
USER_NOT_AUTHORIZED_ADMIN.MESSAGE,
);
}
});

Expand Down Expand Up @@ -241,8 +245,10 @@ describe("resolvers -> Mutation -> blockUser", () => {
};

await blockUserResolver?.({}, args, context);
} catch (error: any) {
expect(error.message).toEqual(USER_NOT_AUTHORIZED_ERROR.MESSAGE);
} catch (error: unknown) {
expect((error as Error).message).toEqual(
USER_NOT_AUTHORIZED_ERROR.MESSAGE,
);
}
});

Expand Down
Loading

0 comments on commit d34aa8a

Please sign in to comment.