From 7afe579b8342ff3f67c17cfa04104cfe7551cec3 Mon Sep 17 00:00:00 2001 From: Jareth Whitney Date: Thu, 9 Jan 2025 16:04:36 -0800 Subject: [PATCH 1/2] feature/deseng751: Added external link model, service, and swagger definitions. Updated search service. --- CHANGELOG.md | 3 + api/controllers/externalLink.js | 330 +++++++++++++++++ api/controllers/search.js | 17 +- api/helpers/models/externalLink.js | 25 ++ api/swagger/swagger.yaml | 544 +++++++++++++++++++++++++++++ app.js | 1 + package.json | 2 +- 7 files changed, 911 insertions(+), 11 deletions(-) create mode 100644 api/controllers/externalLink.js create mode 100644 api/helpers/models/externalLink.js diff --git a/CHANGELOG.md b/CHANGELOG.md index a2e4340..036640d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### 1.11.0 Jan 9, 2025 +* Added external link model, service, and swagger definitions. Modified search service. [DESENG-751](https://apps.itsm.gov.bc.ca/jira/browse/DESENG-751) + ### 1.10.0 Nov 26, 2024 * Modified project definition to accomodate shape file colours. [DESENG-743](https://apps.itsm.gov.bc.ca/jira/browse/DESENG-743) * Modified project definition to accomodate project type multiselect. [DESENG-745](https://apps.itsm.gov.bc.ca/jira/browse/DESENG-745) diff --git a/api/controllers/externalLink.js b/api/controllers/externalLink.js new file mode 100644 index 0000000..7841095 --- /dev/null +++ b/api/controllers/externalLink.js @@ -0,0 +1,330 @@ +const { remove, indexOf, assignIn } = require('lodash'); +const defaultLog = require('winston').loggers.get('defaultLog'); +const mongoose = require('mongoose'); +const Actions = require('../helpers/actions'); +const Utils = require('../helpers/utils'); + +const getSanitizedFields = (fields) => { + return remove(fields, (f) => { + return (indexOf([ + '_addedBy', + 'project', + 'displayName', + 'externalLink', + 'section', + 'dateAdded', + 'dateUpdated', + 'description', + 'projectPhase', + 'checkbox', + 'read', + ], f) !== -1); + }); +}; + +exports.protectedOptions = (args, res) => { + defaultLog.info('EXTERNAL LINK PROTECTED OPTIONS'); + res.status(200).send(); +}; + +exports.publicGet = async (args, res) => { + defaultLog.info('EXTERNAL LINK PUBLIC GET'); + // Build match query if on exLinkId route + let query = {}; + + if (args.swagger.params.exLinkId?.value) { + query = Utils.buildQuery("_id", args.swagger.params.exLinkId.value, query); + } else if (args.swagger.params.exLinkIds?.value?.length > 0) { + query = Utils.buildQuery("_id", args.swagger.params.exLinkIds.value, query); + } + + if (args.swagger.params.project?.value) { + query = Utils.buildQuery("project", args.swagger.params.project.value, query); + } + + // Set query type + assignIn(query, { "_schemaName": "ExternalLink" }); + + try { + const data = await Utils.runDataQuery( + 'ExternalLink', + ['public'], + null, + query, + getSanitizedFields(args.swagger.params.fields.value), // Fields + null, // sort warmup + null, // sort + null, // skip + null, // limit + false); // count + defaultLog.info('Got external link file(s):', data); + Utils.recordAction('Get', 'ExternalLink', 'public', args.swagger.params.exLinkId?.value || null); + return Actions.sendResponse(res, 200, data); + } catch (e) { + defaultLog.error(e); + return Actions.sendResponse(res, 400, e); + } +}; + +exports.unProtectedPost = async (args, res) => { + defaultLog.info('EXTERNAL LINK PUBLIC POST'); + const _comment = args.swagger.params._comment.value; + const project = args.swagger.params.project.value; + try { + Promise.resolve() + .then(async function () { + defaultLog.info('Now saving external link in DB.'); + const ExternalLink = mongoose.model('ExternalLink'); + const extLink = new ExternalLink(); + // Define security tag defaults + extLink.project = mongoose.Types.ObjectId(project); + extLink._comment = _comment; + extLink._addedBy = 'public'; + extLink._createdDate = new Date(); + extLink.read = ['sysadmin', 'staff']; + extLink.write = ['sysadmin', 'staff']; + extLink.delete = ['sysadmin', 'staff']; + extLink.displayName = args.body.displayName; + extLink.dateAdded = new Date(); + extLink.dateUpdated = new Date(); + extLink.externalLink = args.body.externalLink; + extLink.projectPhase = args.body.projectPhase; + extLink.checkbox = 'true' === args.body.checkbox ? true : false; + extLink.save() + .then(async function (link) { + defaultLog.info("Saved new external link object:", link._id); + const Comment = mongoose.model('Comment'); + const c = await Comment.update({ _id: _comment }, { $addToSet: { documents: link._id } }); + defaultLog.info('External link updated:', c); + Utils.recordAction('Post', 'ExternalLink', 'public', link._id); + return Actions.sendResponse(res, 200, link); + }) + .catch(async function (error) { + defaultLog.error(error); + return Actions.sendResponse(res, 400, error); + }); + }); + } catch (e) { + defaultLog.error(e); + // Delete the path details before we return to the caller. + delete e['path']; + return Actions.sendResponse(res, 400, e); + } +}; + +exports.protectedHead = (args, res) => { + defaultLog.info('EXTERNAL LINK PROTECTED HEAD'); + // Build match query if on exLinkId route + let query = {}; + if (args.swagger.params.exLinkId?.value) { + query = Utils.buildQuery("_id", args.swagger.params.exLinkId.value, query); + } + if (args.swagger.params._application?.value) { + query = Utils.buildQuery('_application', args.swagger.params._application.value, query); + } + if (args.swagger.params._comment?.value) { + query = Utils.buildQuery('_comment', args.swagger.params._comment.value, query); + } + // Set query type + assignIn(query, { "_schemaName": "ExternalLink" }); + + Utils.runDataQuery('ExternalLink', + args.swagger.params.auth_payload.client_roles, + args.swagger.params.auth_payload.idir_user_guid, + query, + ['_id', + 'read'], // Fields + null, // sort warmup + null, // sort + null, // skip + null, // limit + true) // count + .then((data) => { + Utils.recordAction('Head', 'ExternalLink', args.swagger.params.auth_payload.preferred_username, args.swagger.params.exLinkId?.value || null); + // /api/commentperiod/ route, return 200 OK with 0 items if necessary + if (!(args.swagger.params.exLinkId && args.swagger.params.exLinkId.value) || (data && data.length > 0)) { + res.setHeader('x-total-count', data?.length > 0 ? data[0].total_items : 0); + return Actions.sendResponse(res, 200, data); + } else { + return Actions.sendResponse(res, 404, data); + } + }); +} + +exports.protectedGet = async (args, res) => { + defaultLog.info('EXTERNAL LINK PROTECTED GET'); + let query = {}, sort = {}, skip = null, limit = null, count = false; + + // Build match query if on exLinkId route + if (args.swagger.params.exLinkId?.value) { + assignIn(query, { _id: mongoose.Types.ObjectId(args.swagger.params.exLinkId.value) }); + } else if (args.swagger.params.exLinkIds?.value?.length > 0) { + query = Utils.buildQuery("_id", args.swagger.params.exLinkIds.value); + } + if (args.swagger.params.project?.value) { + query = Utils.buildQuery("project", args.swagger.params.project.value, query); + } + // Set query type + assignIn(query, { "_schemaName": "ExternalLink" }); + + try { + const data = await Utils.runDataQuery('ExternalLink', + args.swagger.params.auth_payload.client_roles, + args.swagger.params.auth_payload.idir_user_guid, + query, + getSanitizedFields(args.swagger.params.fields.value), // Fields + null, // sort warmup + sort, // sort + skip, // skip + limit, // limit + count); // count + Utils.recordAction('Get', 'ExternalLink', args.swagger.params.auth_payload.preferred_username, args.swagger.params.exLinkId?.value || null); + defaultLog.info('Got external file(s):', data); + return Actions.sendResponse(res, 200, data); + } catch (e) { + defaultLog.error(e); + return Actions.sendResponse(res, 400, e); + } +}; + +exports.protectedPost = async (args, res, next) => { + defaultLog.info('EXTERNAL LINK PROTECTED POST'); + try { + const project = args.swagger.params.project?.value; + // const _comment = args.swagger.params._comment.value; + defaultLog.info('Section value:', args.swagger.params.section?.value); + Promise.resolve() + .then(async () => { + const ExternalLink = mongoose.model('ExternalLink'); + const extLink = new ExternalLink(); + // Define security tag defaults + extLink.read = ['sysadmin', 'staff']; + extLink.write = ['sysadmin', 'staff']; + extLink.delete = ['sysadmin', 'staff']; + + // Map the form values + extLink.project = mongoose.Types.ObjectId(project); + extLink._addedBy = args.swagger.params.auth_payload.preferred_username; + extLink._createdDate = new Date(); + extLink.displayName = args.swagger.params.displayName.value; + extLink.externalLink = args.swagger.params.externalLink.value; + extLink.section = args.swagger.params.section?.value; + extLink.dateAdded = args.swagger.params.dateAdded.value; + extLink.dateUpdated = args.swagger.params.dateUpdated.value; + extLink.description = args.swagger.params.description.value; + extLink.projectPhase = args.swagger.params.projectPhase.value; + extLink.checkbox = 'true' === args.body.checkbox ? true : false; + // extLink._comment = _comment; + // extLink.alt = args.swagger.params.alt?.value || null; + // extLink.documentAuthor = args.swagger.params.documentAuthor?.value || null; + extLink.save() + .then((exl) => { + Utils.recordAction('Post', 'ExternalLink', args.swagger.params.auth_payload.preferred_username, exl._id); + return Actions.sendResponse(res, 200, exl); + }) + .catch((error) => { + defaultLog.error(error); + return Actions.sendResponse(res, 400, error); + }); + }) + .catch(error => defaultLog.error(error)); + } catch (e) { + defaultLog.error(e); + // Delete the path details before we return to the caller. + delete e['path']; + return Actions.sendResponse(res, 500, e); + } +}; + +exports.protectedPublish = async (args, res) => { + defaultLog.info('EXTERNAL LINK PROTECTED PUBLISH'); + const objId = args.swagger.params.exLinkId.value; + defaultLog.info("Publish External Link:", objId); + + const ExternalLink = require('mongoose').model('ExternalLink'); + try { + const exLink = await ExternalLink.findOne({ _id: objId }); + if (exLink) { + defaultLog.info("External Link:", exLink); + const published = await Actions.publish(await exLink.save()); + Utils.recordAction('Publish', 'ExternalLink', args.swagger.params.auth_payload.preferred_username, objId); + return Actions.sendResponse(res, 200, published); + } else { + defaultLog.info("Couldn't find that external link!"); + return Actions.sendResponse(res, 404, e); + } + } catch (e) { + return Actions.sendResponse(res, 400, e); + } +}; + +exports.protectedUnPublish = async (args, res) => { + defaultLog.info('EXTERNAL LINK PROTECTED UNPUBLISH'); + const objId = args.swagger.params.exLinkId.value; + defaultLog.info("Unpublish External Link:", objId); + const ExternalLink = require('mongoose').model('ExternalLink'); + try { + const exLink = await ExternalLink.findOne({ _id: objId }); + if (exLink) { + const unPublished = await Actions.unPublish(await exLink.save()); + Utils.recordAction('Unpublish', 'ExternalLink', args.swagger.params.auth_payload.preferred_username, objId); + defaultLog.info("Published external link:", objId); + return Actions.sendResponse(res, 200, unPublished); + } else { + defaultLog.info("Couldn't find that external link!"); + return Actions.sendResponse(res, 404, e); + } + } catch (e) { + defaultLog.error(e); + return Actions.sendResponse(res, 400, e); + } +}; + +exports.protectedPut = async (args, res) => { + defaultLog.info('EXTERNAL LINK PROTECTED PUT'); + const objId = args.swagger.params.exLinkId.value; + let obj = {}; + defaultLog.info('Put external link:', objId); + + obj._updatedBy = args.swagger.params.auth_payload.preferred_username; + obj.displayName = args.swagger.params.displayName.value; + obj.externalLink = args.swagger.params.externalLink.value; + obj.section = args.swagger.params.section.value; + obj.projectPhase = args.swagger.params.projectPhase.value; + obj.dateAdded = args.swagger.params.dateAdded.value; + obj.dateUpdated = args.swagger.params.dateUpdated.value; + obj.description = args.swagger.params.description.value; + obj.section = "null" === args.swagger.params.section.value ? null : args.swagger.params.section.value; + const ExternalLink = mongoose.model('ExternalLink'); + + try { + const exLink = await ExternalLink.findOneAndUpdate({ _id: objId }, obj, { upsert: false, new: true }); + if (exLink) { + Utils.recordAction('put', 'ExternalLink', args.swagger.params.auth_payload.preferred_username, objId); + defaultLog.info('External link updated:', objId); + return Actions.sendResponse(res, 200, exLink); + } else { + defaultLog.info("Couldn't find that external link!"); + return Actions.sendResponse(res, 404, {}); + } + } catch (e) { + defaultLog.error(e); + return Actions.sendResponse(res, 400, e); + } +} + +exports.protectedDelete = async (args, res) => { + defaultLog.info('EXTERNAL LINK PROTECTED DELETE'); + const objId = args.swagger.params.exLinkId.value; + defaultLog.info("Delete External Link:", objId); + const ExternalLink = require('mongoose').model('ExternalLink'); + + try { + await ExternalLink.findOneAndRemove({ _id: objId }); + Utils.recordAction('Delete', 'ExternalLink', args.swagger.params.auth_payload.preferred_username, objId); + return Actions.sendResponse(res, 200, {}); + } catch (e) { + defaultLog.error("Error:", e); + return Actions.sendResponse(res, 400, e); + } +}; diff --git a/api/controllers/search.js b/api/controllers/search.js index 29bad79..a8c2117 100644 --- a/api/controllers/search.js +++ b/api/controllers/search.js @@ -411,17 +411,14 @@ var executeQuery = async function (args, res, next) { }); if (dataset !== 'Item') { - var data = await searchCollection(roles, userProjectPermissions, keywords, dataset, pageNum, pageSize, project, sortField, sortDirection, caseSensitive, populate, and, or) - if (dataset === 'Comment') { - // Filter - each(data[0].searchResults, function (item) { - if (item.isAnonymous === true) { - delete item.author; - } - }); - } + var data = await searchCollection(roles, userProjectPermissions, keywords, dataset, pageNum, pageSize, project, sortField, sortDirection, caseSensitive, populate, and, or); + // Filter + each(data[0].searchResults, function (item) { + if (item.isAnonymous === true) { + delete item.author; + } + }); return Actions.sendResponse(res, 200, data); - } else if (dataset === 'Item') { var collectionObj = mongoose.model(args.swagger.params._schemaName.value); diff --git a/api/helpers/models/externalLink.js b/api/helpers/models/externalLink.js new file mode 100644 index 0000000..6e548c3 --- /dev/null +++ b/api/helpers/models/externalLink.js @@ -0,0 +1,25 @@ +module.exports = require('../models')('ExternalLink', { + + _createdDate: { type: Date, default: Date.now() }, + _updatedDate: { type: Date, default: Date.now() }, + _addedBy: { type: String, default: 'system' }, + _updatedBy: { type: String, default: 'system' }, + _deletedBy: { type: String, default: 'system' }, + + read: [{ type: String, trim: true, default: 'sysadmin' }], + write: [{ type: String, trim: true, default: 'sysadmin' }], + delete: [{ type: String, trim: true, default: 'sysadmin' }], + + project: { type: 'ObjectId', ref: 'Project', default: null }, + section: { type: 'ObjectId', ref: 'DocumentSection', default: null } | null, + displayName: { type: String, default:'' }, + externalLink: { type: String, default: '' }, + dateAdded: { type: Date, default: Date.now() }, + dateUpdated: { type: Date, default: Date.now() }, + description: { type: String, default: '' }, + projectPhase: { type: String, default: '' }, + checkbox: { type: Boolean, default: false }, + + // alt: { type: String, default: '' }, + // documentAuthor: { type: String, default: '' }, +}, 'lup'); diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 9366fa8..75d13bd 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -216,6 +216,32 @@ definitions: - internalMime - internalSize +### External Link Definitions + ExLinkId: + type: object + properties: + displayName: + type: string + example: "A cool external link" + ExLinkObject: + type: object + properties: + displayName: + type: string + example: "A cool external link" + ExternalLinkFields: + type: string + description: "Optional fields to return." + example: name|type + enum: &externalLinkFields + - displayName + - externalLink + - dateAdded + - dateUpdated + - description + - section + - projectPhase + ### Document Section Definitions DocumentSectionId: type: object @@ -3433,6 +3459,524 @@ paths: schema: $ref: "#/definitions/Error" +## External Links + /link: + x-swagger-router-controller: externalLink + options: + tags: + - link + summary: "Pre-flight request" + operationId: protectedOptions + description: "Options on External Link Route" + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + post: + tags: + - link + summary: "Create a new external link" + operationId: protectedPost + description: "Create a new external link object." + summary: "Create a new external link object." + security: + - Bearer: [] + x-security-scopes: + - staff + - sysadmin + consumes: + - multipart/form-data + parameters: + - name: project + in: formData + description: "The application to bind this file to." + required: false + type: string + - name: section + in: formData + required: false + type: string + - name: projectPhase + in: formData + description: "The project phase of the file." + required: false + type: string + - name: dateAdded + in: formData + description: "The dateAdded of the file." + required: false + type: string + - name: dateUpdated + in: formData + description: "The dateUpdated of the file." + required: false + type: string + - name: description + in: formData + description: "The description of the file." + required: false + type: string + - name: externalLink + in: formData + description: "The external link of the file." + required: false + type: string + - name: displayName + in: formData + description: "The displayName of the file." + required: false + type: string + - name: checkbox + in: formData + description: "The checkbox state of the file." + required: false + type: string + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + get: + tags: + - link + summary: "Get a list of external links" + operationId: protectedGet + description: "Authenticated access to retreiving an external link." + security: + - Bearer: [] + x-security-scopes: + - sysadmin + - staff + parameters: + - in: query + name: exLinkIds + description: "Search using an array of external link ids." + type: array + required: false + collectionFormat: pipes + items: + type: string + - in: query + name: project + description: "External Links relating to (a) particular Project(s)" + type: array + required: false + collectionFormat: pipes + items: + type: string + - in: query + name: _comment + description: "External Links relating to a particular Comment(s)" + type: array + required: false + collectionFormat: pipes + items: + type: string + - in: query + name: fields + description: "External Links fields to return." + required: false + type: array + collectionFormat: pipes + items: + type: string + enum: *externalLinkFields + - in: query + name: isDeleted + type: boolean + required: false + description: "External Links that are deleted or not" + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + /link/{exLinkId}: + x-swagger-router-controller: externalLink + options: + tags: + - link + summary: "Pre-flight request" + operationId: protectedOptions + description: "Options on External Link GET Route" + parameters: + - name: exLinkId + in: path + description: "ID of external link to get" + required: true + type: string + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + get: + tags: + - link + summary: "Get an external link" + operationId: protectedGet + description: "Authenticated access to retreiving an external link." + security: + - Bearer: [] + x-security-scopes: + - staff + - sysadmin + parameters: + - name: exLinkId + in: path + description: "ID of external link to get" + required: true + type: string + - in: query + name: fields + description: "External link fields to return." + required: false + type: array + collectionFormat: pipes + items: + type: string + enum: *externalLinkFields + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + put: + tags: + - link + summary: "Update/Upload an external link" + operationId: protectedPut + description: "Update an external link object." + security: + - Bearer: [] + x-security-scopes: + - sysadmin + consumes: + - multipart/form-data + parameters: + - name: exLinkId + in: path + description: "ID of external link to update" + required: true + type: string + - name: project + in: formData + description: "The application to bind this document to." + required: false + type: string + - name: section + in: formData + description: "The section to organize the document under." + required: false + type: string + - name: projectPhase + in: formData + description: "The project phase of the file." + required: false + type: string + - name: dateAdded + in: formData + description: "The date on which the file was added." + required: false + type: string + - name: dateUpdated + in: formData + description: "The date on which the file was updated last." + required: false + type: string + - name: description + in: formData + description: "The description of the file." + required: false + type: string + - name: displayName + in: formData + description: "The displayName of the file." + required: false + type: string + - name: externalLink + in: formData + description: "The external link of the file." + required: false + type: string + - name: checkbox + in: formData + description: "The checkbox state of the file." + required: false + type: string + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + delete: + tags: + - link + summary: "Delete an external link" + operationId: protectedDelete + description: "Delete an external link object." + security: + - Bearer: [] + x-security-scopes: + - sysadmin + consumes: + - application/json + parameters: + - name: exLinkId + in: path + description: "ID of external link to delete" + required: true + type: string + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + + /link/{exLinkId}/publish: + x-swagger-router-controller: externalLink + options: + tags: + - link + summary: "Pre-flight request" + operationId: protectedOptions + description: "Options on External Link GET Route" + parameters: + - name: exLinkId + in: path + description: "ID of external link to get" + required: true + type: string + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + put: + tags: + - link + summary: "Publish an external link" + operationId: protectedPublish + description: "Adds the singular instance of the 'public' role to a external link." + security: + - Bearer: [] + x-security-scopes: + - staff + - sysadmin + # TODO: Define publish roles. + parameters: + - name: exLinkId + in: path + description: "ID of external link to update" + required: true + type: string + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + + /link/{exLinkId}/unpublish: + x-swagger-router-controller: externalLink + options: + tags: + - link + summary: "Pre-flight request" + operationId: protectedOptions + description: "Options on ExternalLink GET Route" + parameters: + - name: exLinkId + in: path + description: "ID of external link to get" + required: true + type: string + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + put: + tags: + - link + summary: "UnPublish an external link" + operationId: protectedUnPublish + description: "Removes the singular instance of the 'public' role on an external link." + security: + - Bearer: [] + x-security-scopes: + - staff + - sysadmin + # TODO: Define unpublish roles. + parameters: + - name: exLinkId + in: path + description: "ID of external link to update" + required: true + type: string + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + + /public/link: + x-swagger-router-controller: externalLink + options: + tags: + - link + summary: "Pre-flight request" + operationId: protectedOptions + description: "Options on External Link Route" + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + get: + tags: + - link + summary: "Get a list of external links" + operationId: publicGet + description: "Retreiving public external links." + parameters: + - in: query + name: exLinkIds + description: "Search using an array of external link ids." + type: array + required: false + collectionFormat: pipes + items: + type: string + - in: query + name: project + description: "Documents relating to a particular Project(s)" + type: array + required: false + collectionFormat: pipes + items: + type: string + - in: query + name: fields + description: "Document fields to return." + required: false + type: array + collectionFormat: pipes + items: + type: string + enum: *externalLinkFields + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + + /public/link/{exLinkId}: + x-swagger-router-controller: externalLink + options: + tags: + - link + summary: "Pre-flight request" + operationId: protectedOptions + description: "Options on ExternalLink GET Route" + parameters: + - name: exLinkId + in: path + description: "ID of external link to get" + required: true + type: string + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + get: + tags: + - link + summary: "Get an external link" + operationId: publicGet + description: "Public access to retreiving external links." + parameters: + - name: exLinkId + in: path + description: "ID of external link to get" + required: true + type: string + - in: query + name: fields + description: "External link fields to return." + required: false + type: array + collectionFormat: pipes + items: + type: string + enum: *externalLinkFields + responses: + "200": + description: "Success" + schema: + $ref: "#/definitions/ExLinkObject" + "403": + description: "Access Denied" + schema: + $ref: "#/definitions/Error" + ## Documents Section /documentSection: x-swagger-router-controller: documentSection diff --git a/app.js b/app.js index 08fb3b3..4ef9080 100644 --- a/app.js +++ b/app.js @@ -121,6 +121,7 @@ swaggerTools.initializeMiddleware(swaggerConfig, function(middleware) { require('./api/helpers/models/surveyQuestionAnswer'); require('./api/helpers/models/surveyResponse'); require('./api/helpers/models/document'); + require('./api/helpers/models/externalLink'); require('./api/helpers/models/documentSection'); require('./api/helpers/models/comment'); require('./api/helpers/models/commentperiod'); diff --git a/package.json b/package.json index ed812a4..eb3071c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "landuseplanning-api", - "version": "1.10.0", + "version": "1.11.0", "author": "Mark Lisé", "contributors": [ "Mark Lisé ", From 46d931d1c86bcec1a3731614b30e2435e7f0ade0 Mon Sep 17 00:00:00 2001 From: Jareth Whitney Date: Tue, 14 Jan 2025 10:54:18 -0800 Subject: [PATCH 2/2] feature/deseng751: Removed unneeded comments, unneeded method removed from externalLink controller. --- api/controllers/externalLink.js | 51 ------------------------------ api/helpers/models/externalLink.js | 3 -- 2 files changed, 54 deletions(-) diff --git a/api/controllers/externalLink.js b/api/controllers/externalLink.js index 7841095..1b199f4 100644 --- a/api/controllers/externalLink.js +++ b/api/controllers/externalLink.js @@ -66,52 +66,6 @@ exports.publicGet = async (args, res) => { } }; -exports.unProtectedPost = async (args, res) => { - defaultLog.info('EXTERNAL LINK PUBLIC POST'); - const _comment = args.swagger.params._comment.value; - const project = args.swagger.params.project.value; - try { - Promise.resolve() - .then(async function () { - defaultLog.info('Now saving external link in DB.'); - const ExternalLink = mongoose.model('ExternalLink'); - const extLink = new ExternalLink(); - // Define security tag defaults - extLink.project = mongoose.Types.ObjectId(project); - extLink._comment = _comment; - extLink._addedBy = 'public'; - extLink._createdDate = new Date(); - extLink.read = ['sysadmin', 'staff']; - extLink.write = ['sysadmin', 'staff']; - extLink.delete = ['sysadmin', 'staff']; - extLink.displayName = args.body.displayName; - extLink.dateAdded = new Date(); - extLink.dateUpdated = new Date(); - extLink.externalLink = args.body.externalLink; - extLink.projectPhase = args.body.projectPhase; - extLink.checkbox = 'true' === args.body.checkbox ? true : false; - extLink.save() - .then(async function (link) { - defaultLog.info("Saved new external link object:", link._id); - const Comment = mongoose.model('Comment'); - const c = await Comment.update({ _id: _comment }, { $addToSet: { documents: link._id } }); - defaultLog.info('External link updated:', c); - Utils.recordAction('Post', 'ExternalLink', 'public', link._id); - return Actions.sendResponse(res, 200, link); - }) - .catch(async function (error) { - defaultLog.error(error); - return Actions.sendResponse(res, 400, error); - }); - }); - } catch (e) { - defaultLog.error(e); - // Delete the path details before we return to the caller. - delete e['path']; - return Actions.sendResponse(res, 400, e); - } -}; - exports.protectedHead = (args, res) => { defaultLog.info('EXTERNAL LINK PROTECTED HEAD'); // Build match query if on exLinkId route @@ -141,7 +95,6 @@ exports.protectedHead = (args, res) => { true) // count .then((data) => { Utils.recordAction('Head', 'ExternalLink', args.swagger.params.auth_payload.preferred_username, args.swagger.params.exLinkId?.value || null); - // /api/commentperiod/ route, return 200 OK with 0 items if necessary if (!(args.swagger.params.exLinkId && args.swagger.params.exLinkId.value) || (data && data.length > 0)) { res.setHeader('x-total-count', data?.length > 0 ? data[0].total_items : 0); return Actions.sendResponse(res, 200, data); @@ -191,7 +144,6 @@ exports.protectedPost = async (args, res, next) => { defaultLog.info('EXTERNAL LINK PROTECTED POST'); try { const project = args.swagger.params.project?.value; - // const _comment = args.swagger.params._comment.value; defaultLog.info('Section value:', args.swagger.params.section?.value); Promise.resolve() .then(async () => { @@ -214,9 +166,6 @@ exports.protectedPost = async (args, res, next) => { extLink.description = args.swagger.params.description.value; extLink.projectPhase = args.swagger.params.projectPhase.value; extLink.checkbox = 'true' === args.body.checkbox ? true : false; - // extLink._comment = _comment; - // extLink.alt = args.swagger.params.alt?.value || null; - // extLink.documentAuthor = args.swagger.params.documentAuthor?.value || null; extLink.save() .then((exl) => { Utils.recordAction('Post', 'ExternalLink', args.swagger.params.auth_payload.preferred_username, exl._id); diff --git a/api/helpers/models/externalLink.js b/api/helpers/models/externalLink.js index 6e548c3..b630c24 100644 --- a/api/helpers/models/externalLink.js +++ b/api/helpers/models/externalLink.js @@ -19,7 +19,4 @@ module.exports = require('../models')('ExternalLink', { description: { type: String, default: '' }, projectPhase: { type: String, default: '' }, checkbox: { type: Boolean, default: false }, - - // alt: { type: String, default: '' }, - // documentAuthor: { type: String, default: '' }, }, 'lup');