-
-
Notifications
You must be signed in to change notification settings - Fork 976
/
Copy pathcreateOrganization.ts
184 lines (162 loc) · 5.78 KB
/
createOrganization.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
import "dotenv/config";
import type {
MutationResolvers,
Address,
} from "../../types/generatedGraphQLTypes";
import { User, Organization, ActionItemCategory } from "../../models";
import { errors, requestContext } from "../../libraries";
import { LENGTH_VALIDATION_ERROR } from "../../constants";
import { superAdminCheck } from "../../utilities";
import { isValidString } from "../../libraries/validators/validateString";
import { uploadEncodedImage } from "../../utilities/encodedImageStorage/uploadEncodedImage";
import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations";
/**
* This function enables to create an organization.
* @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
* @returns Created organization
*/
export const createOrganization: MutationResolvers["createOrganization"] =
async (_parent, args, context) => {
const currentUser = await User.findById({
_id: context.userId,
});
if (currentUser) {
superAdminCheck(currentUser);
}
//Upload file
let uploadImageFileName = null;
if (args.file) {
uploadImageFileName = await uploadEncodedImage(args.file, null);
}
// Checks if the recieved arguments are valid according to standard input norms
let validationResultName = {
isLessThanMaxLength: false,
};
let validationResultDescription = {
isLessThanMaxLength: false,
};
let validationResultAddress = {
isAddressValid: false,
};
if (args.data?.name && args.data?.description) {
validationResultName = isValidString(args.data?.name, 256);
validationResultDescription = isValidString(args.data?.description, 500);
}
if (args.data?.address) {
validationResultAddress = validateAddress(args.data?.address);
}
if (!validationResultName.isLessThanMaxLength) {
throw new errors.InputValidationError(
requestContext.translate(
`${LENGTH_VALIDATION_ERROR.MESSAGE} 256 characters in name`
),
LENGTH_VALIDATION_ERROR.CODE
);
}
if (!validationResultDescription.isLessThanMaxLength) {
throw new errors.InputValidationError(
requestContext.translate(
`${LENGTH_VALIDATION_ERROR.MESSAGE} 500 characters in description`
),
LENGTH_VALIDATION_ERROR.CODE
);
}
if (!validationResultAddress.isAddressValid) {
throw new errors.InputValidationError("Not a Valid Address");
}
// Creates new organization.
const createdOrganization = await Organization.create({
...args.data,
address: args.data?.address,
image: uploadImageFileName ? uploadImageFileName : null,
creatorId: context.userId,
admins: [context.userId],
members: [context.userId],
});
// Creating a default actionItemCategory
await ActionItemCategory.create({
name: "Default",
organizationId: createdOrganization._id,
creatorId: context.userId,
});
await cacheOrganizations([createdOrganization.toObject()]);
/*
Adds createdOrganization._id to joinedOrganizations, createdOrganizations
and adminFor lists on currentUser's document with _id === context.userId
*/
await User.updateOne(
{
_id: context.userId,
},
{
$push: {
joinedOrganizations: createdOrganization._id,
createdOrganizations: createdOrganization._id,
adminFor: createdOrganization._id,
},
}
);
// Returns createdOrganization.
return createdOrganization.toObject();
};
/**
* Validates an address object to ensure its fields meet specified criteria.
* @param address - The address object to validate
* @returns An object containing the validation result: isAddressValid (true if the address is valid, false otherwise)
*/
function validateAddress(address: Address | undefined): {
isAddressValid: boolean;
} {
if (!address) {
return { isAddressValid: false };
}
const {
city,
countryCode,
dependentLocality,
line1,
line2,
postalCode,
sortingCode,
state,
} = address;
// Mandatory: It should be a valid country code.
const isCountryCodeValid = !!countryCode && countryCode.length >= 2;
// Mandatory: It should exist and have a length greater than 0
const isCityValid = !!city && city.length > 0;
// Optional: It should exist and have a length greater than 0
const isDependentLocalityValid =
dependentLocality === undefined ||
(typeof dependentLocality === "string" && dependentLocality.length >= 0);
// Optional: Line 1 should exist and have a length greater than 0
const isLine1Valid =
line1 === undefined || (typeof line1 === "string" && line1.length >= 0);
// Optional: Line 2 should exist and have a length greater than 0, if provided
const isLine2Valid =
line2 === undefined || (typeof line2 === "string" && line2.length >= 0);
// Optional: It should exist and have a valid format.
const isPostalCodeValid =
postalCode === undefined ||
(typeof postalCode === "string" && /^\d*$/.test(postalCode));
// Optional: It should exist and have a length greater than 0, if provided
const isSortingCodeValid =
sortingCode === undefined ||
(typeof sortingCode === "string" && sortingCode.length >= 0);
// Optional: It should exist and have a length greater than 0, if provided
const isStateValid =
state === undefined || (typeof state === "string" && state.length >= 0);
const isAddressValid =
isCityValid &&
isCountryCodeValid &&
isDependentLocalityValid &&
isLine1Valid &&
isLine2Valid &&
isPostalCodeValid &&
isSortingCodeValid &&
isStateValid;
return { isAddressValid: isAddressValid };
}