Skip to content

Commit

Permalink
feat(#303): Update restful services graphql queries and mutations for…
Browse files Browse the repository at this point in the history
… contact and user services. And also enabling email trigger service
  • Loading branch information
tholulomo committed Jun 13, 2023
1 parent e9c2fd4 commit e2751ae
Show file tree
Hide file tree
Showing 12 changed files with 270 additions and 95 deletions.
3 changes: 2 additions & 1 deletion resfulservice/config/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ module.exports = {
'SYNTHESIS AND PROCESSING': 'PROCESSING',
'CHARACTERIZATION METHODS': 'CHARACTERIZATION',
MICROSTRUCTURE: 'MICROSTRUCTURE'
}
},
ContactPagePurposeOpt: ['QUESTION', 'TICKET', 'SUGGESTION', 'COMMENT']
};
4 changes: 3 additions & 1 deletion resfulservice/src/controllers/authController.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ const _redirect = ({ _id, email, displayName, givenName, surName, roles }, req,
userId: _id,
token,
displayName,
isAdmin
isAdmin,
givenName,
surName
})}`);
};

Expand Down
59 changes: 51 additions & 8 deletions resfulservice/src/graphql/resolver/contact/input.graphql
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
"Input schema for fetching a single contact"
"""
Input schema for fetching a single contact
"""
input userContactQueryInput {
"""
email of user whose contact to fetch.
Expand All @@ -7,6 +9,9 @@ input userContactQueryInput {
email: String!
}

"""
Date and time input filter options
"""
input CreatedBetween {
from: String!
to: String!
Expand All @@ -24,7 +29,9 @@ input contactsQueryInput {
"""
pageNumber: Int

"filter "
"""
Date and time input filter options
"""
datetime: CreatedBetween

"""
Expand All @@ -33,28 +40,64 @@ input contactsQueryInput {
Defaults to 1 if none is specified.
"""
pageSize: Int

"""
Boolean value to specify if to return resolved contact enquiries
"""
resolved: Boolean

"""
Name of the admin user who resolved the enquiry
"""
resolvedBy: String
}

"Input Schema type for creating contact"
"""
Input payload for submitting new contact inquiry
"""
input createContactInput {
"full name of the user requesting contact"
"""
Full name of the user requesting contact
"""
fullName: String!

"email address of the user requesting contact"
"""
Email address of the user requesting contact
"""
email: String!

"""
purpose for requesting contact.
Purpose for requesting contact.
You can specify only one from the list of enumerable values defined
"""
purpose: Purpose!

"details of the reason or purpose for requesting contact"
"""
Details of the reason or purpose for requesting contact
"""
message: String!
}

input updateContactInput {
"""
Id of the contact to update
"""
contactId: ID!

"""
Boolean value to either resolve or unresolve a contact enquiry
"""
resolved: Boolean

"""
Response text sent back to the user who made an enquiry
"""
response: String
}

"list of enumerable value selectable as purpose for requesting contact"
"""
List of enumerable value selectable as purpose for requesting contact
"""
enum Purpose {
"I want to ask a question"
QUESTION
Expand Down
23 changes: 23 additions & 0 deletions resfulservice/src/graphql/resolver/contact/mutation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const Contact = require('../../../models/contact');
const errorFormater = require('../../../utils/errorFormater');
const { userRoles } = require('../../../../config/constant');
const sendMail = require('../../../utils/emailService');

const contactMutation = {
submitContact: async (_, { input }, { req }) => {
Expand All @@ -13,6 +15,27 @@ const contactMutation = {
} catch (error) {
return errorFormater(error.message, 500);
}
},

updateContact: async (_, { input }, { user, req, isAuthenticated }) => {
req.logger.info('[updateContact] Function Entry:');
if (user?.roles !== userRoles.isAdmin || !isAuthenticated) {
req.logger?.error('[updateContact]: User unauthorized');
return errorFormater('Unauthorized', 401);
};
try {
const contactExists = await Contact.findOne({ _id: input.contactId });
if (!contactExists) return errorFormater('Contact not found', 404);
if (contactExists.resolved) return errorFormater('Forbidden', 409);
if (input?.resolved) input.resolvedBy = user.displayName;
const contact = await Contact.findOneAndUpdate({ _id: input.contactId }, { $set: input }, { new: true, lean: true });
if (contact?.response) {
sendMail(req, contact);
}
return contact;
} catch (error) {
return errorFormater(error.message, 500);
}
}
};

Expand Down
18 changes: 8 additions & 10 deletions resfulservice/src/graphql/resolver/contact/query.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Contact = require('../../../models/contact');
const errorFormater = require('../../../utils/errorFormater');
const paginator = require('../../../utils/paginator');
const { userRoles } = require('../../../../config/constant');

const contactQuery = {
getUserContacts: async (_, { input }, { user, req, isAuthenticated }) => {
Expand All @@ -20,23 +21,20 @@ const contactQuery = {

contacts: async (_, { input }, { user, req, isAuthenticated }) => {
req.logger?.info('[contacts]: Function Entry:');
if (!isAuthenticated) {
const { datetime, resolvedBy, resolved } = input;
if (user?.roles !== userRoles.isAdmin || !isAuthenticated) {
req.logger?.error('[contacts]: User not authenticated to view contact listing');
return errorFormater('not authenticated', 401);
}
const filter = input?.datetime?.from && input?.datetime?.to
? {
createdAt: {
$gt: new Date(input.datetime.from),
$lt: new Date(input.datetime.to)
}
}
: {};
const filter = resolved ? { resolved } : { $or: [{ resolved }, { resolved: null }] };
if (datetime?.from && datetime?.to) filter.createdAt = { $gt: new Date(input.datetime.from), $lt: new Date(input.datetime.to) };
if (resolvedBy) filter.resolvedBy = resolvedBy;
try {
const pagination = input ? paginator(await Contact.countDocuments({}), input.pageNumber, input.pageSize) : paginator(await Contact.countDocuments({}));
const pagination = input ? paginator(await Contact.countDocuments(filter), input.pageNumber, input.pageSize) : paginator(await Contact.countDocuments(filter));
const data = await Contact.find(filter).skip(pagination.skip).limit(pagination.limit).lean();
return Object.assign(pagination, { data });
} catch (error) {
req.logger.error(error);
return errorFormater(error.message, 500);
}
}
Expand Down
54 changes: 44 additions & 10 deletions resfulservice/src/graphql/resolver/contact/type.graphql
Original file line number Diff line number Diff line change
@@ -1,32 +1,66 @@
"Schema type returned from the getSingleContact query resolver"
"""
Schema type returned from the getSingleContact query resolver
"""
type Contact {
"ID of the contact"
"""
ID of the contact
"""
_id: ID
"full name of the user requesting contact"

"""
Full name of the user requesting contact
"""
fullName: String!

"email address of the user requesting contact"
"""
Email address of the user requesting contact
"""
email: String!

"""
purpose for requesting contact.
Purpose for requesting contact.
You can specify only one from the list of enumerable values defined
"""
purpose: Purpose!

"details of the reason or purpose for requesting contact"
"""
Details of the reason or purpose for requesting contact
"""
message: String!

"time the contact was created"
"""
Boolean value which shows the status of a contact enquiry
"""
resolved: Boolean

"""
Response text sent back to the user who made an enquiry
"""
response: String

"""
Admin user who resolved the enquiry
"""
resolvedBy: String

"""
Time the contact was created
"""
createdAt: String

"last time contact was updated"
"""
Last time contact was updated
"""
updatedAt: String
}

"This schema type returns the lists of contacts"
"""
This schema type returns the lists of contacts
"""
type Contacts {
"Total number of contacts that exists"
"""
Total number of contacts that exists
"""
totalItems: Int!

"""
Expand Down
102 changes: 73 additions & 29 deletions resfulservice/src/graphql/resolver/user/input.graphql
Original file line number Diff line number Diff line change
@@ -1,48 +1,92 @@
"User ID info for user query resolver"
"""
Verify user input payload
"""
input userIdInput {
"The user's unique ID"
"""
Unique ID of the user
"""
_id: ID!
}

"Page and page size info for users query resolver"
"""
Delete user input payload
"""
input deleteUsersInput {
"""
List of user's unique ID
"""
ids: [ID!]!
}

"""
Get user list input payload
"""
input usersQueryInput {
"Page number of users to find"
"""
Page number of users to find
"""
pageNumber: Int

"Total number of users per page"
"""
Total number of users per page
"""
pageSize: Int
}

"Input schema for createUser Mutation resolver"
input createUserInput {
"User alias from auth service"
alias: String!

"User first name info"
givenName: String!

"User last name info"
surName: String!

"Name displayed on user profile, e.g. username"
displayName: String!
"User email address"
email: String!
"""
Optional field to find users base on userName
"""
displayName: String
}
"Update user mutation resolver schema"

"""
User modification input payload
"""
input updateUserInput {
"Unique ID of user to update"
"""
Unique ID of user to update
"""
_id: ID!
"User alias e.g. username"

"""
User alias e.g. username
"""
alias: String
"User ID from auth service"

"""
User ID from auth service
"""
userid: String
"User first name info"

"""
User first name info
"""
givenName: String
"User last name info"

"""
User last name info
"""
surName: String
"name displayed on user profile similar to username"

"""
Name displayed on user profile similar to username
"""
displayName: String
"User email"

"""
User email email address
"""
email: String

"""
User priviledge options
"""
roles: Roles
}

"""
Available user priviledge options
"""
enum Roles {
isAdmin
member
}
Loading

0 comments on commit e2751ae

Please sign in to comment.