diff --git a/src/constants/common.js b/src/constants/common.js index e3b3e1c41..2589ecb24 100644 --- a/src/constants/common.js +++ b/src/constants/common.js @@ -98,8 +98,10 @@ module.exports = { DEFAULT_ORGANISATION_POLICY: { session_visibility_policy: 'CURRENT', mentor_visibility_policy: 'CURRENT', + mentee_visibility_policy: 'CURRENT', external_session_visibility_policy: 'CURRENT', external_mentor_visibility_policy: 'CURRENT', + external_mentee_visibility_policy: 'CURRENT', allow_mentor_override: false, approval_required_for: [], }, diff --git a/src/controllers/v1/profile.js b/src/controllers/v1/profile.js index af450f9a5..5ef9f32e3 100644 --- a/src/controllers/v1/profile.js +++ b/src/controllers/v1/profile.js @@ -110,6 +110,7 @@ module.exports = class Mentees { try { const filterList = await menteesService.getFilterList( req.query.entity_types ? req.query.entity_types : '', + req.query.filter_type ? req.query.filter_type : '', req.decodedToken ) return filterList diff --git a/src/database/migrations/20240221051434-add-mentee-visibility-policies.js b/src/database/migrations/20240221051434-add-mentee-visibility-policies.js new file mode 100644 index 000000000..b0465b2f0 --- /dev/null +++ b/src/database/migrations/20240221051434-add-mentee-visibility-policies.js @@ -0,0 +1,33 @@ +'use strict' + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.addColumn('organization_extension', 'mentee_visibility_policy', { + type: Sequelize.STRING, + defaultValue: 'CURRENT', + }) + + await queryInterface.addColumn('organization_extension', 'external_mentee_visibility_policy', { + type: Sequelize.STRING, + defaultValue: 'CURRENT', + }) + + await queryInterface.addColumn('user_extensions', 'external_mentee_visibility', { + type: Sequelize.STRING, + defaultValue: 'CURRENT', + }) + + await queryInterface.addColumn('mentor_extensions', 'external_mentee_visibility', { + type: Sequelize.STRING, + defaultValue: 'CURRENT', + }) + }, + + async down(queryInterface, Sequelize) { + await queryInterface.removeColumn('organization_extension', 'mentee_visibility_policy') + await queryInterface.removeColumn('organization_extension', 'external_mentee_visibility_policy') + await queryInterface.removeColumn('user_extensions', 'external_mentee_visibility') + await queryInterface.removeColumn('mentor_extensions', 'external_mentee_visibility') + }, +} diff --git a/src/database/migrations/20240221100109-update-forms-detaultTemplate.js b/src/database/migrations/20240221100109-update-forms-detaultTemplate.js new file mode 100644 index 000000000..93b150629 --- /dev/null +++ b/src/database/migrations/20240221100109-update-forms-detaultTemplate.js @@ -0,0 +1,686 @@ +'use strict' + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + const defaultOrgId = queryInterface.sequelize.options.defaultOrgId + if (!defaultOrgId) { + throw new Error('Default org ID is undefined. Please make sure it is set in sequelize options.') + } + let res = await queryInterface.bulkUpdate( + 'forms', + { + data: JSON.stringify({ + fields: { + controls: [ + { + name: 'title', + label: 'Session title', + value: '', + class: 'ion-no-margin', + type: 'text', + placeHolder: 'Ex. Name of your session', + position: 'floating', + errorMessage: { + required: 'Enter session title', + }, + validators: { + required: true, + maxLength: 255, + }, + }, + { + name: 'description', + label: 'Description', + value: '', + class: 'ion-no-margin', + type: 'textarea', + placeHolder: 'Tell the community something about your session', + position: 'floating', + errorMessage: { + required: 'Enter description', + }, + validators: { + required: true, + maxLength: 255, + }, + }, + { + name: 'type', + label: 'Session type', + class: 'ion-no-margin', + type: 'select', + value: '', + dependedChild: 'mentees', + position: 'floating', + info: [ + { + header: 'Public session', + message: 'Discoverable. Mentees can enroll and attend', + }, + { + header: 'Private session', + message: 'Non-discoverable. Invited mentee can attend', + }, + ], + errorMessage: { + required: 'Please select your session type', + }, + validators: { + required: true, + }, + meta: { + errorLabel: 'Location', + disabledChildren: ['mentees', 'mentor_id'], + }, + multiple: false, + options: [ + { + label: 'Private', + value: 'PRIVATE', + }, + { + label: 'Public', + value: 'PUBLIC', + }, + ], + }, + { + name: 'mentor_id', + label: 'Add mentor', + value: '', + class: 'ion-no-margin', + type: 'search', + position: 'floating', + disabled: true, + meta: { + multiSelect: false, + disableIfSelected: true, + searchLabel: 'Search for mentor', + searchData: [], + url: 'MENTORS_LIST', + labelArrayForSingleSelect: ['mentor_name', 'organization.name'], + filters: { + entity_types: [ + { + key: 'designation', + label: 'Designation', + type: 'checkbox', + }, + ], + organizations: [ + { + isEnabled: true, + key: 'organizations', + type: 'checkbox', + }, + ], + }, + filterType: 'mentor', + }, + info: [ + { + message: 'Click to select Mentor for this session', + }, + ], + errorMessage: { + required: 'Please add a mentor for the session', + }, + validators: { + required: true, + }, + }, + { + name: 'mentees', + label: 'Add mentee', + value: '', + class: 'ion-no-margin', + disabled: true, + type: 'search', + meta: { + multiSelect: true, + url: 'MENTEES_LIST', + searchLabel: 'Search for mentee', + searchData: [], + maxCount: 'MAX_MENTEE_ENROLLMENT_COUNT', + labelForListButton: 'View Mentee List', + labelForAddButton: 'Add New Mentee', + filters: { + entity_types: [ + { + key: 'designation', + label: 'Designation', + type: 'checkbox', + }, + ], + organizations: [ + { + isEnabled: true, + key: 'organizations', + type: 'checkbox', + }, + ], + }, + filterType: 'mentee', + }, + position: 'floating', + info: [ + { + message: 'Click to select Mentee(s) for this session', + }, + ], + errorMessage: { + required: 'Please add mentee for the session', + }, + validators: { + required: true, + }, + }, + { + name: 'start_date', + label: 'Start date', + class: 'ion-no-margin', + value: '', + displayFormat: 'DD/MMM/YYYY HH:mm', + dependedChild: 'end_date', + type: 'date', + placeHolder: 'YYYY-MM-DD hh:mm', + errorMessage: { + required: 'Enter start date', + }, + position: 'floating', + validators: { + required: true, + }, + }, + { + name: 'end_date', + label: 'End date', + class: 'ion-no-margin', + position: 'floating', + value: '', + displayFormat: 'DD/MMM/YYYY HH:mm', + dependedParent: 'start_date', + type: 'date', + placeHolder: 'YYYY-MM-DD hh:mm', + errorMessage: { + required: 'Enter end date', + }, + validators: { + required: true, + }, + }, + { + name: 'recommended_for', + label: 'Recommended for', + class: 'ion-no-margin', + value: '', + type: 'chip', + position: '', + disabled: false, + errorMessage: { + required: 'Enter recommended for', + }, + validators: { + required: true, + }, + options: [ + { + label: 'District education officer', + value: 'deo', + }, + { + label: 'Block education officer', + value: 'beo', + }, + { + label: 'Head master', + value: 'hm', + }, + { + label: 'Teacher', + value: 'te', + }, + { + label: 'Cluster officials', + value: 'co', + }, + ], + meta: { + entityType: 'recommended_for', + addNewPopupHeader: 'Recommended for', + addNewPopupSubHeader: 'Who is this session for?', + showSelectAll: true, + showAddOption: true, + }, + multiple: true, + }, + { + name: 'categories', + label: 'Categories', + class: 'ion-no-margin', + value: '', + type: 'chip', + position: '', + disabled: false, + errorMessage: { + required: 'Enter categories', + }, + validators: { + required: true, + }, + options: [ + { + label: 'Educational leadership', + value: 'educational_leadership', + }, + { + label: 'School process', + value: 'school_process', + }, + { + label: 'Communication', + value: 'communication', + }, + { + label: 'SQAA', + value: 'sqaa', + }, + { + label: 'Professional development', + value: 'professional_development', + }, + ], + meta: { + entityType: 'categories', + addNewPopupHeader: 'Add a new category', + showSelectAll: true, + showAddOption: true, + }, + multiple: true, + }, + { + name: 'medium', + label: 'Select medium', + alertLabel: 'medium', + class: 'ion-no-margin', + value: '', + type: 'chip', + position: '', + disabled: false, + errorMessage: { + required: 'Enter select medium', + }, + validators: { + required: true, + }, + options: [ + { + label: 'English', + value: 'en_in', + }, + { + label: 'Hindi', + value: 'hi', + }, + ], + meta: { + entityType: 'medium', + addNewPopupHeader: 'Add new language', + showSelectAll: true, + showAddOption: true, + }, + multiple: true, + }, + ], + }, + template_name: 'defaultTemplate', + }), + + updated_at: new Date(), + }, + { type: 'managersSession', sub_type: 'managersSessionForm', organization_id: defaultOrgId } + ) + }, + + async down(queryInterface, Sequelize) { + const defaultOrgId = queryInterface.sequelize.options.defaultOrgId + if (!defaultOrgId) { + throw new Error('Default org ID is undefined. Please make sure it is set in sequelize options.') + } + let res = await queryInterface.bulkUpdate( + 'forms', + + { + data: JSON.stringify({ + fields: { + controls: [ + { + name: 'title', + label: 'Session title', + value: '', + class: 'ion-no-margin', + type: 'text', + placeHolder: 'Ex. Name of your session', + position: 'floating', + errorMessage: { + required: 'Enter session title', + }, + validators: { + required: true, + maxLength: 255, + }, + }, + { + name: 'description', + label: 'Description', + value: '', + class: 'ion-no-margin', + type: 'textarea', + placeHolder: 'Tell the community something about your session', + position: 'floating', + errorMessage: { + required: 'Enter description', + }, + validators: { + required: true, + maxLength: 255, + }, + }, + { + name: 'type', + label: 'Session type', + class: 'ion-no-margin', + type: 'select', + dependedChild: 'mentees', + position: 'floating', + value: '', + info: [ + { + header: 'Public session', + message: 'Discoverable. Mentees can enroll and attend', + }, + { + header: 'Private session', + message: 'Non-discoverable. Invited mentee can attend', + }, + ], + errorMessage: { + required: 'Please select your session type', + }, + validators: { + required: true, + }, + meta: { + errorLabel: 'Location', + disabledChildren: ['mentees', 'mentor_id'], + }, + multiple: false, + options: [ + { + label: 'Private', + value: 'PRIVATE', + }, + { + label: 'Public', + value: 'PUBLIC', + }, + ], + }, + { + name: 'mentor_id', + label: 'Add mentor', + value: '', + class: 'ion-no-margin', + type: 'search', + position: 'floating', + disabled: true, + meta: { + multiSelect: false, + disableIfSelected: true, + searchLabel: 'Search for mentor', + searchData: [], + url: 'MENTORS_LIST', + labelArrayForSingleSelect: ['mentor_name', 'organization.name'], + filters: { + entity_types: [ + { + key: 'designation', + label: 'Designation', + type: 'checkbox', + }, + ], + organizations: [ + { + isEnabled: true, + key: 'organizations', + type: 'checkbox', + }, + ], + }, + }, + info: [ + { + message: 'Click to select Mentor for this session', + }, + ], + errorMessage: { + required: 'Please add a mentor for the session', + }, + validators: { + required: true, + }, + }, + { + name: 'mentees', + label: 'Add mentee', + value: '', + class: 'ion-no-margin', + disabled: true, + type: 'search', + meta: { + multiSelect: true, + url: 'MENTEES_LIST', + searchLabel: 'Search for mentee', + searchData: [], + maxCount: 'MAX_MENTEE_ENROLLMENT_COUNT', + labelForListButton: 'View Mentee List', + labelForAddButton: 'Add New Mentee', + filters: { + entity_types: [ + { + key: 'designation', + label: 'Designation', + type: 'checkbox', + }, + ], + organizations: [ + { + isEnabled: true, + key: 'organizations', + type: 'checkbox', + }, + ], + }, + }, + position: 'floating', + info: [ + { + message: 'Click to select Mentee(s) for this session', + }, + ], + errorMessage: { + required: 'Please add mentee for the session', + }, + validators: { + required: true, + }, + }, + { + name: 'start_date', + label: 'Start date', + class: 'ion-no-margin', + value: '', + displayFormat: 'DD/MMM/YYYY HH:mm', + dependedChild: 'end_date', + type: 'date', + placeHolder: 'YYYY-MM-DD hh:mm', + errorMessage: { + required: 'Enter start date', + }, + position: 'floating', + validators: { + required: true, + }, + }, + { + name: 'end_date', + label: 'End date', + class: 'ion-no-margin', + position: 'floating', + value: '', + displayFormat: 'DD/MMM/YYYY HH:mm', + dependedParent: 'start_date', + type: 'date', + placeHolder: 'YYYY-MM-DD hh:mm', + errorMessage: { + required: 'Enter end date', + }, + validators: { + required: true, + }, + }, + { + name: 'recommended_for', + label: 'Recommended for', + class: 'ion-no-margin', + value: '', + type: 'chip', + position: '', + disabled: false, + errorMessage: { + required: 'Enter recommended for', + }, + validators: { + required: true, + }, + options: [ + { + label: 'Block education officer', + value: 'beo', + }, + { + label: 'Cluster officials', + value: 'co', + }, + { + label: 'District education officer', + value: 'deo', + }, + { + label: 'Head master', + value: 'hm', + }, + { + label: 'Teacher', + value: 'te', + }, + ], + meta: { + entityType: 'recommended_for', + addNewPopupHeader: 'Recommended for', + addNewPopupSubHeader: 'Who is this session for?', + showSelectAll: true, + showAddOption: true, + }, + multiple: true, + }, + { + name: 'categories', + label: 'Categories', + class: 'ion-no-margin', + value: '', + type: 'chip', + position: '', + disabled: false, + errorMessage: { + required: 'Enter categories', + }, + validators: { + required: true, + }, + options: [ + { + label: 'Communication', + value: 'communication', + }, + { + label: 'Educational leadership', + value: 'educational_leadership', + }, + { + label: 'Professional development', + value: 'professional_development', + }, + { + label: 'School process', + value: 'school_process', + }, + { + label: 'SQAA', + value: 'sqaa', + }, + ], + meta: { + entityType: 'categories', + addNewPopupHeader: 'Add a new category', + showSelectAll: true, + showAddOption: true, + }, + multiple: true, + }, + { + name: 'medium', + label: 'Select medium', + alertLabel: 'medium', + class: 'ion-no-margin', + value: '', + type: 'chip', + position: '', + disabled: false, + errorMessage: { + required: 'Enter select medium', + }, + validators: { + required: true, + }, + options: [ + { + label: 'English', + value: 'en_in', + }, + { + label: 'Hindi', + value: 'hi', + }, + ], + meta: { + entityType: 'medium', + addNewPopupHeader: 'Add new language', + showSelectAll: true, + showAddOption: true, + }, + multiple: true, + }, + ], + }, + template_name: 'defaultTemplate', + }), + + updated_at: new Date(), + }, + + { type: 'managersSession', sub_type: 'managersSessionForm', organization_id: defaultOrgId } + ) + }, +} diff --git a/src/database/models/mentorExtension.js b/src/database/models/mentorExtension.js index aaba519c9..07efc9b4d 100644 --- a/src/database/models/mentorExtension.js +++ b/src/database/models/mentorExtension.js @@ -54,6 +54,10 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.INTEGER, allowNull: false, }, + external_mentee_visibility: { + type: DataTypes.STRING, + defaultValue: 'CURRENT', + }, }, { sequelize, diff --git a/src/database/models/organizationExtension.js b/src/database/models/organizationExtension.js index e14b77ff9..06e0dc18c 100644 --- a/src/database/models/organizationExtension.js +++ b/src/database/models/organizationExtension.js @@ -33,6 +33,8 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.STRING, defaultValue: 'MENTOR_QS2', }, + mentee_visibility_policy: { type: DataTypes.STRING }, + external_mentee_visibility_policy: { type: DataTypes.STRING }, }, { sequelize, diff --git a/src/database/models/userExtension.js b/src/database/models/userExtension.js index d938d4ffc..b5d2460d3 100644 --- a/src/database/models/userExtension.js +++ b/src/database/models/userExtension.js @@ -54,6 +54,10 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.INTEGER, allowNull: false, }, + external_mentee_visibility: { + type: DataTypes.STRING, + defaultValue: 'CURRENT', + }, }, { sequelize, diff --git a/src/locales/en.json b/src/locales/en.json index 01f582d88..3d57a72e6 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -65,9 +65,10 @@ "FORM_VERSION_FETCHED_SUCCESSFULLY": "Form versions fetched successfully", "ACCESS_TOKEN_EXPIRED": "Session expired. Please login again.", "INVALID_TIME_SELECTION": "You already have a session '{{sessionName}}' scheduled at this time. Please select a different time.", - "SESSION_DELETION_FAILED": "Session can't be deleted", + "CANNOT_DELETE_LIVE_SESSION": "Cannot delete ongoing session.", "MEETING_SERVICE_INFO_NOT_FOUND": "BBB is currently disabled. Please provide an alternative meeting platform.", "SESSION_EDIT_WINDOW": "Session editing is only allowed up to {{editWindow}} minutes before the session start time.", + "CANNOT_EDIT_LIVE_SESSION": "Cannot edit ongoing session.", "SESSION_SEAT_FULL": "Session seats full.", "APP_CONFIG_FETCHED_SUCCESSFULLY": "App config fetched successfully.", "USER_REMOVED_SUCCESSFULLY": "User details removed successfully.", @@ -155,5 +156,6 @@ "ORG_EXTENSION_CREATED_SUCCESSFULLY": "Organization Extension Created Successfully", "PERMISSIONS_NOT_FOUND": "permissions not found", "SESSION_MENTOR_ADDED_TO_MENTEE_LIST": "You have added the Session Mentor in the Mentee list. Please go back and select another mentee.", - "INVALID_DATA_PASSED": "Invalid data passed for creation" + "INVALID_DATA_PASSED": "Invalid data passed for creation", + "PROFILE_UPDATE_FAILED": "Profile update failed. Please try again." } diff --git a/src/services/mentees.js b/src/services/mentees.js index f6749d4ce..99a27132f 100644 --- a/src/services/mentees.js +++ b/src/services/mentees.js @@ -633,6 +633,8 @@ module.exports = class MenteesHelper { ...data, ...saasPolicyData, visible_to_organizations: userOrgDetails.data.result.related_orgs, + visibility: organisationPolicy.mentee_visibility_policy, + external_mentee_visibility: organisationPolicy.external_mentee_visibility_policy, } const response = await menteeQueries.createMenteeExtension(data) @@ -702,7 +704,7 @@ module.exports = class MenteesHelper { let res = utils.validateInput(data, validationData, userExtensionsModelName) if (!res.success) { return responses.failureResponse({ - message: 'SESSION_CREATION_FAILED', + message: 'PROFILE_UPDATE_FAILED', statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR', result: res.errors, @@ -830,17 +832,20 @@ module.exports = class MenteesHelper { * @param {Boolean} queryParams - queryParams * @returns {JSON} - Filter list. */ - static async getFilterList(queryParams, tokenInformation) { + static async getFilterList(entity_type, filterType, tokenInformation) { try { let result = { organizations: [], entity_types: {}, } + const filter_type = filterType !== '' ? filterType : common.MENTOR_ROLE + let organization_ids = [] const organizations = await this.getOrganizationIdBasedOnPolicy( tokenInformation.id, - tokenInformation.organization_id + tokenInformation.organization_id, + filter_type ) if (organizations.success && organizations.result.length > 0) { @@ -858,7 +863,7 @@ module.exports = class MenteesHelper { // get entity type with entities list const getEntityTypesWithEntities = await this.getEntityTypeWithEntitiesBasedOnOrg( organization_ids, - queryParams, + entity_type, defaultOrgId ? defaultOrgId : '' ) @@ -890,39 +895,52 @@ module.exports = class MenteesHelper { } } - static async getOrganizationIdBasedOnPolicy(userId, organization_id) { + static async getOrganizationIdBasedOnPolicy(userId, organization_id, filter_type) { try { let organization_ids = [] + const attributes = + filter_type.toLowerCase() == common.MENTEE_ROLE + ? ['organization_id', 'external_mentee_visibility_policy'] + : ['organization_id', 'external_mentor_visibility_policy'] + const orgPolicies = await organisationExtensionQueries.findOne( { organization_id }, { - attributes: ['organization_id', 'external_mentor_visibility_policy'], + attributes: attributes, } ) + const visibilityPolicy = + filter_type.toLowerCase() == common.MENTEE_ROLE + ? orgPolicies.external_mentee_visibility_policy + : orgPolicies.external_mentor_visibility_policy + if (orgPolicies?.organization_id) { - if (orgPolicies.external_mentor_visibility_policy === common.CURRENT) { + if (visibilityPolicy === common.CURRENT) { organization_ids.push(orgPolicies.organization_id) - } else if ( - orgPolicies.external_mentor_visibility_policy === common.ASSOCIATED || - orgPolicies.external_mentor_visibility_policy === common.ALL - ) { + } else if (visibilityPolicy === common.ASSOCIATED || visibilityPolicy === common.ALL) { organization_ids.push(orgPolicies.organization_id) let relatedOrgs = [] let userOrgDetails = await userRequests.fetchDefaultOrgDetails(orgPolicies.organization_id) if (userOrgDetails.success && userOrgDetails.data?.result?.related_orgs?.length > 0) { relatedOrgs = userOrgDetails.data.result.related_orgs } - if (orgPolicies.external_mentor_visibility_policy === common.ASSOCIATED) { + if (visibilityPolicy === common.ASSOCIATED) { organization_ids.push(...relatedOrgs) } else { + const filterQuery = + filter_type.toLowerCase() == common.MENTEE_ROLE + ? { + external_mentee_visibility_policy: common.ALL, + } + : { + mentor_visibility_policy: common.ALL, + } const organizationExtension = await organisationExtensionQueries.findAll( { [Op.or]: [ - { - mentor_visibility_policy: common.ALL, - }, + filterQuery, { organization_id: { [Op.in]: [...relatedOrgs, orgPolicies.organization_id], @@ -1191,9 +1209,17 @@ module.exports = class MenteesHelper { : ['external_mentor_visibility', 'organization_id'] const userPolicyDetails = isAMentor - ? await mentorQueries.getMentorExtension(userId, extensionColumns) - : await menteeQueries.getMenteeExtension(userId, extensionColumns) + ? await mentorQueries.getMentorExtension(userId, ['organization_id']) + : await menteeQueries.getMenteeExtension(userId, ['organization_id']) + const getOrgPolicy = await organisationExtensionQueries.findOne( + { + organization_id: userPolicyDetails.organization_id, + }, + { + attributes: ['external_mentee_visibility_policy', 'organization_id'], + } + ) // Throw error if mentor/mentee extension not found if (!userPolicyDetails || Object.keys(userPolicyDetails).length === 0) { return responses.failureResponse({ @@ -1209,37 +1235,37 @@ module.exports = class MenteesHelper { if (organization_ids.length !== 0) { additionalFilter = `AND "organization_id" in (${organization_ids.join(',')})` } - if (userPolicyDetails.external_mentor_visibility && userPolicyDetails.organization_id) { - const externalVisibilityPolicy = userPolicyDetails[extensionColumns[0]] + if (getOrgPolicy.external_mentee_visibility_policy && userPolicyDetails.organization_id) { + const visibilityPolicy = getOrgPolicy.external_mentee_visibility_policy // Filter user data based on policy // generate filter based on condition - if (externalVisibilityPolicy === common.CURRENT) { + if (visibilityPolicy === common.CURRENT) { /** * if user external_mentor_visibility is current. He can only see his/her organizations mentors * so we will check mentor's organization_id and user organization_id are matching */ filter = `AND "organization_id" = ${userPolicyDetails.organization_id}` - } else if (externalVisibilityPolicy === common.ASSOCIATED) { + } else if (visibilityPolicy === common.ASSOCIATED) { /** * If user external_mentor_visibility is associated * <> first we need to check if mentor's visible_to_organizations contain the user organization_id and verify mentor's visibility is not current (if it is ALL and ASSOCIATED it is accessible) */ filter = additionalFilter + - `AND ( (${userPolicyDetails.organization_id} = ANY("visible_to_organizations") AND "visibility" != 'CURRENT')` + `AND ( (${userPolicyDetails.organization_id} = ANY("visible_to_organizations") AND "external_mentee_visibility_policy" != 'CURRENT')` if (additionalFilter.length === 0) filter += ` OR organization_id = ${userPolicyDetails.organization_id} )` else filter += `)` - } else if (externalVisibilityPolicy === common.ALL) { + } else if (visibilityPolicy === common.ALL) { /** * We need to check if mentor's visible_to_organizations contain the user organization_id and verify mentor's visibility is not current (if it is ALL and ASSOCIATED it is accessible) * OR if mentor visibility is ALL that mentor is also accessible */ filter = additionalFilter + - `AND ((${userPolicyDetails.organization_id} = ANY("visible_to_organizations") AND "visibility" != 'CURRENT' ) OR "visibility" = 'ALL' OR "organization_id" = ${userPolicyDetails.organization_id})` + `AND ((${userPolicyDetails.organization_id} = ANY("visible_to_organizations") AND "external_mentee_visibility_policy" != 'CURRENT' ) OR "external_mentee_visibility_policy" = 'ALL' OR "organization_id" = ${userPolicyDetails.organization_id})` } } diff --git a/src/services/mentors.js b/src/services/mentors.js index 249d26530..3e9119858 100644 --- a/src/services/mentors.js +++ b/src/services/mentors.js @@ -364,6 +364,8 @@ module.exports = class MentorsHelper { ...data, ...saasPolicyData, visible_to_organizations: userOrgDetails.data.result.related_orgs, + visibility: organisationPolicy.mentee_visibility_policy, + external_mentee_visibility: organisationPolicy.external_mentee_visibility_policy, } const response = await mentorQueries.createMentorExtension(data) @@ -431,6 +433,16 @@ module.exports = class MentorsHelper { const validationData = removeDefaultOrgEntityTypes(entityTypes, orgId) let mentorExtensionsModel = await mentorQueries.getColumns() + let res = utils.validateInput(data, validationData, mentorExtensionsModelName) + if (!res.success) { + return responses.failureResponse({ + message: 'PROFILE_UPDATE_FAILED', + statusCode: httpStatusCode.bad_request, + responseCode: 'CLIENT_ERROR', + result: res.errors, + }) + } + data = utils.restructureBody(data, validationData, mentorExtensionsModel) const [updateCount, updatedMentor] = await mentorQueries.updateMentorExtension(userId, data, { diff --git a/src/services/org-admin.js b/src/services/org-admin.js index aa6fc8110..a0d325e3a 100644 --- a/src/services/org-admin.js +++ b/src/services/org-admin.js @@ -210,6 +210,15 @@ module.exports = class OrgAdminService { responseCode: 'UNAUTHORIZED', }) } + + if (!policies.hasOwnProperty('mentee_visibility_policy')) { + policies['mentee_visibility_policy'] = 'CURRENT' + } + + if (!policies.hasOwnProperty('external_mentee_visibility_policy')) { + policies['external_mentee_visibility_policy'] = 'CURRENT' + } + const orgPolicies = await organisationExtensionQueries.upsert({ organization_id: decodedToken.organization_id, ...policies, @@ -485,6 +494,7 @@ module.exports = class OrgAdminService { mentor_visibility_policy, external_session_visibility_policy, external_mentor_visibility_policy, + external_mentee_visibility_policy, organization_id, } = organisationPolicy // create policy object @@ -492,6 +502,7 @@ module.exports = class OrgAdminService { visibility: mentor_visibility_policy, external_session_visibility: external_session_visibility_policy, external_mentor_visibility: external_mentor_visibility_policy, + external_mentee_visibility: external_mentee_visibility_policy, } // add org_ id value if requested if (addOrgId) { diff --git a/src/services/sessions.js b/src/services/sessions.js index d41d27c99..e3b837a2b 100644 --- a/src/services/sessions.js +++ b/src/services/sessions.js @@ -473,11 +473,7 @@ module.exports = class SessionsHelper { let message const sessionRelatedJobIds = common.notificationJobIdPrefixes.map((element) => element + sessionDetail.id) if (method == common.DELETE_METHOD) { - let statTime = moment.unix(sessionDetail.start_date) - const current = moment.utc() - let diff = statTime.diff(current, 'minutes') - - if (sessionDetail.status == common.PUBLISHED_STATUS && diff > 10) { + if (sessionDetail.status == common.PUBLISHED_STATUS) { await sessionQueries.deleteSession({ id: sessionId, }) @@ -490,7 +486,7 @@ module.exports = class SessionsHelper { } } else { return responses.failureResponse({ - message: 'SESSION_DELETION_FAILED', + message: 'CANNOT_DELETE_LIVE_SESSION', statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR', }) @@ -1122,16 +1118,7 @@ module.exports = class SessionsHelper { responseCode: 'CLIENT_ERROR', }) } - // check if the session is accessible to the user - let isAccessible = await this.checkIfSessionIsAccessible(session, userId, isAMentor) - if (!isAccessible) { - return responses.failureResponse({ - message: 'INVALID_PERMISSION', - statusCode: httpStatusCode.bad_request, - responseCode: 'CLIENT_ERROR', - }) - } const sessionAttendeeExist = await sessionAttendeesQueries.findOne({ session_id: sessionId, mentee_id: userId,