diff --git a/backend/src/app.js b/backend/src/app.js index 290c181af..8578b1752 100644 --- a/backend/src/app.js +++ b/backend/src/app.js @@ -42,6 +42,7 @@ const analyticsRouter = require('./routes/analytics-router'); const nominalRollRouter = require('./routes/nominal-roll'); const edxRouter = require('./routes/edx-router'); const instituteRouter = require('./routes/institute'); +const sdcRouter = require('./routes/sdc'); const cacheRouter = require('./routes/cache-router'); const promMid = require('express-prometheus-middleware'); const Redis = require('./util/redis/redis-client'); @@ -183,6 +184,7 @@ apiRouter.use('/analytics', analyticsRouter); apiRouter.use('/nominal-roll', nominalRollRouter); apiRouter.use('/edx', edxRouter); apiRouter.use('/institute', instituteRouter); +apiRouter.use('/sdc', sdcRouter); apiRouter.use('/cache', cacheRouter); // Prevent unhandled errors from crashing application process.on('unhandledRejection', err => { diff --git a/backend/src/components/sdc/sdc.js b/backend/src/components/sdc/sdc.js new file mode 100644 index 000000000..41a51095e --- /dev/null +++ b/backend/src/components/sdc/sdc.js @@ -0,0 +1,173 @@ +'use strict'; +const { logApiError, getData, deleteData, errorResponse, getBackendToken, validateAccessToken, putData} = require('../utils'); +const HttpStatus = require('http-status-codes'); +const config = require('../../config'); +const cacheService = require('../cache-service'); +const utils = require('../utils'); + +async function getFundingGroupDataForSchool(req, res) { + try { + const accessToken = getBackendToken(req); + validateAccessToken(accessToken, res); + + let school = cacheService.getSchoolBySchoolID(req.params.schoolID); + + if(!hasSchoolAdminRole(req, school)){ + return res.status(HttpStatus.UNAUTHORIZED).json({ + message: 'You do not have the required access for this function' + }); + } + + const data = await getData(accessToken, `${config.get('sdc:fundingGroupDataURL')}/search/${req.params.schoolID}`); + return res.status(HttpStatus.OK).json(data); + } catch (e) { + logApiError(e, 'getFundingGroupDataForSchool', 'Error getting funding data for this school'); + return errorResponse(res); + } +} + +async function getSnapshotFundingDataForSchool(req, res) { + try { + const accessToken = getBackendToken(req); + validateAccessToken(accessToken, res); + + let school = cacheService.getSchoolBySchoolID(req.params.schoolID); + + if(!hasSchoolAdminRole(req, school)){ + return res.status(HttpStatus.UNAUTHORIZED).json({ + message: 'You do not have the required access for this function' + }); + } + + const data = await getData(accessToken, `${config.get('sdc:fundingGroupDataURL')}/snapshot/${req.params.schoolID}/${req.params.collectionID}`); + return res.status(HttpStatus.OK).json(data); + } catch (e) { + logApiError(e, 'getSnapshotFundingDataForSchool', 'Error getting funding snapshot data for this school'); + return errorResponse(res); + } +} + +async function getFundingGroupsForSchool(req, res) { + try { + const accessToken = getBackendToken(req); + validateAccessToken(accessToken, res); + + const data = await getData(accessToken, `${config.get('sdc:fundingGroupsURL')}`); + return res.status(HttpStatus.OK).json(data); + } catch (e) { + logApiError(e, 'getFundingGroupsForSchool', 'Error getting funding groups'); + return errorResponse(res); + } +} + +async function deleteFundingDataForSchool(req, res) { + try { + const accessToken = getBackendToken(req); + validateAccessToken(accessToken, res); + + let school = cacheService.getSchoolBySchoolID(req.params.schoolID); + + if(!hasSchoolAdminRole(req, school)){ + return res.status(HttpStatus.UNAUTHORIZED).json({ + message: 'You do not have the required access for this function' + }); + } + + const data = await deleteData(accessToken, `${config.get('sdc:fundingGroupDataURL')}/${req.params.schoolFundingGroupID}`); + return res.status(HttpStatus.OK).json(data); + } catch (e) { + logApiError(e, 'deleteFundingDataForSchool', 'Error removing funding data for this school'); + return errorResponse(res); + } +} + +async function updateFundingDataForSchool(req, res) { + try { + const accessToken = getBackendToken(req); + validateAccessToken(accessToken, res); + + let school = cacheService.getSchoolBySchoolID(req.params.schoolID); + + if(!hasSchoolAdminRole(req, school)){ + return res.status(HttpStatus.UNAUTHORIZED).json({ + message: 'You do not have the required access for this function' + }); + } + + const payload = req.body; + payload.updateDate = null; + payload.createDate = null; + payload.updateUser = utils.getUser(req).idir_username; + + const data = await putData(accessToken, `${config.get('sdc:fundingGroupDataURL')}/${req.params.schoolFundingGroupID}`, payload); + return res.status(HttpStatus.OK).json(data); + } catch (e) { + logApiError(e, 'updateFundingDataForSchool', 'Error updating funding data for this school'); + return errorResponse(res); + } +} + +async function addNewFundingForSchool(req, res) { + try { + const accessToken = getBackendToken(req); + validateAccessToken(accessToken, res); + + let school = cacheService.getSchoolBySchoolID(req.params.schoolID); + + if(!hasSchoolAdminRole(req, school)){ + return res.status(HttpStatus.UNAUTHORIZED).json({ + message: 'You do not have the required access for this function' + }); + } + + const payload = req.body; + payload.createUser = utils.getUser(req).idir_username; + payload.schoolID = req.params.schoolID; + + const data = await utils.postData(accessToken, `${config.get('sdc:fundingGroupDataURL')}`, payload); + return res.status(HttpStatus.OK).json(data); + } catch (e) { + logApiError(e, 'addNewFundingForSchool', 'Error adding funding data for this school'); + return errorResponse(res); + } +} + +async function getAllCollectionsForSchool(req, res) { + try { + const accessToken = getBackendToken(req); + validateAccessToken(accessToken, res); + + let school = cacheService.getSchoolBySchoolID(req.params.schoolID); + + if(!hasSchoolAdminRole(req, school)){ + return res.status(HttpStatus.UNAUTHORIZED).json({ + message: 'You do not have the required access for this function' + }); + } + + const data = await getData(accessToken, `${config.get('sdc:schoolCollectionURL')}/searchAll/${req.params.schoolID}`); + return res.status(HttpStatus.OK).json(data); + } catch (e) { + logApiError(e, 'getFundingGroupDataForSchool', 'Error getting funding data for this school'); + return errorResponse(res); + } +} + +function hasSchoolAdminRole(req, school){ + if(school.schoolCategoryCode === 'INDEPEND' || school.schoolCategoryCode === 'INDP_FNS'){ + return req.session.roles.includes('SCHOOL_ADMIN') || req.session.roles.includes('SCHOOL_INDEPENDENT_ADMIN'); + } + + return req.session.roles.includes('SCHOOL_ADMIN'); +} + + +module.exports = { + getFundingGroupsForSchool, + getFundingGroupDataForSchool, + deleteFundingDataForSchool, + updateFundingDataForSchool, + getSnapshotFundingDataForSchool, + addNewFundingForSchool, + getAllCollectionsForSchool +}; diff --git a/backend/src/config/index.js b/backend/src/config/index.js index 929c152b6..8081c1c2f 100644 --- a/backend/src/config/index.js +++ b/backend/src/config/index.js @@ -178,5 +178,11 @@ nconf.defaults({ bannerColor: process.env.BANNER_COLOR, webSocketURL: process.env.WEB_SOCKET_URL }, + sdc: { + rootURL: process.env.SDC_API_URL, + schoolCollectionURL: process.env.SDC_API_URL + '/sdcSchoolCollection', + fundingGroupsURL: process.env.SDC_API_URL + '/funding-group-codes', + fundingGroupDataURL: process.env.SDC_API_URL + '/schoolFundingGroup' + } }); module.exports = nconf; diff --git a/backend/src/routes/sdc.js b/backend/src/routes/sdc.js new file mode 100644 index 000000000..c0a86721a --- /dev/null +++ b/backend/src/routes/sdc.js @@ -0,0 +1,19 @@ +const passport = require('passport'); +const express = require('express'); +const router = express.Router(); +const utils = require('../components/utils'); +const extendSession = utils.extendSession(); +const { getFundingGroupsForSchool, getFundingGroupDataForSchool, deleteFundingDataForSchool, updateFundingDataForSchool, + getSnapshotFundingDataForSchool, addNewFundingForSchool, getAllCollectionsForSchool} = require('../components/sdc/sdc'); +const auth = require('../components/auth'); + +router.post('/funding-groups/:schoolID', passport.authenticate('jwt', {session: false}, undefined), auth.isLoggedInUser, extendSession, addNewFundingForSchool); +router.get('/funding-groups/:schoolID', passport.authenticate('jwt', {session: false}, undefined), auth.isLoggedInUser, extendSession, getFundingGroupDataForSchool); +router.delete('/funding-groups/:schoolID/funding/:schoolFundingGroupID', passport.authenticate('jwt', {session: false}, undefined), auth.isLoggedInUser, extendSession, deleteFundingDataForSchool); +router.put('/funding-groups/:schoolID/funding/:schoolFundingGroupID', passport.authenticate('jwt', {session: false}, undefined), auth.isLoggedInUser, extendSession, updateFundingDataForSchool); +router.get('/funding-groups/snapshot/:schoolID/:collectionID', passport.authenticate('jwt', {session: false}, undefined), auth.isLoggedInUser, extendSession, getSnapshotFundingDataForSchool); + +router.get('/funding-groups', passport.authenticate('jwt', {session: false}, undefined), auth.isLoggedInUser, extendSession, getFundingGroupsForSchool); +router.get('/sdcSchoolCollection/:schoolID', passport.authenticate('jwt', {session: false}, undefined), auth.isLoggedInUser, extendSession, getAllCollectionsForSchool); +module.exports = router; + diff --git a/frontend/src/components/institute/SchoolDetails.vue b/frontend/src/components/institute/SchoolDetails.vue index c3f9c1f7d..85023c9ed 100644 --- a/frontend/src/components/institute/SchoolDetails.vue +++ b/frontend/src/components/institute/SchoolDetails.vue @@ -138,7 +138,10 @@ Moves - + Funding @@ -177,7 +180,9 @@ /> -

Funding Tab

+
@@ -202,6 +207,7 @@ import Details from './common/Details.vue'; import SchoolHistory from './common/SchoolHistory.vue'; import SchoolContacts from './common/SchoolContacts.vue'; import SchoolMove from './common/SchoolMove.vue'; +import SchoolFunding from './common/SchoolFunding.vue'; import {authStore} from '@/store/modules/auth'; import {notificationsStore} from '@/store/modules/notifications'; import InstituteNotes from '@/components/institute/common/InstituteNotes.vue'; @@ -213,7 +219,8 @@ export default { Details, SchoolHistory, SchoolContacts, - SchoolMove + SchoolMove, + SchoolFunding }, mixins: [alertMixin], props: { @@ -334,6 +341,9 @@ export default { } return this.SCHOOL_ADMIN_ROLE; }, + canViewFundingTab() { + return this.independentArray.includes(this.school.schoolCategoryCode); + }, saveNewSchoolNote(schoolNote) { this.noteRequestCount += 1; const payload = { diff --git a/frontend/src/components/institute/common/AddSchoolFunding.vue b/frontend/src/components/institute/common/AddSchoolFunding.vue new file mode 100644 index 000000000..da99ea153 --- /dev/null +++ b/frontend/src/components/institute/common/AddSchoolFunding.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/frontend/src/components/institute/common/SchoolFunding.vue b/frontend/src/components/institute/common/SchoolFunding.vue new file mode 100644 index 000000000..a22dae7f1 --- /dev/null +++ b/frontend/src/components/institute/common/SchoolFunding.vue @@ -0,0 +1,421 @@ + + + + + + + diff --git a/frontend/src/utils/constants.js b/frontend/src/utils/constants.js index 8113cb848..4d2650968 100644 --- a/frontend/src/utils/constants.js +++ b/frontend/src/utils/constants.js @@ -16,6 +16,7 @@ const nominalRollRoot= baseRoot+'/nominal-roll'; const edxRoot= baseRoot+'/edx'; const instituteRoot = baseRoot + '/institute'; const cacheRoot = baseRoot + '/cache'; +const sdcRoot = baseRoot + '/sdc'; let object = { LOGIN: authRoot + '/login', @@ -165,6 +166,10 @@ let object = { PRIMARY_ACTIVATION_CODE_URL: edxRoot + '/users/activation-code/primary', NEW_SCHOOL_USER_ACTIVATION_INVITE: edxRoot + '/school-user-activation-invite', NEW_DISTRICT_USER_ACTIVATION_INVITE: edxRoot + '/district-user-activation-invite' + }, + sdc: { + FUNDING_DATA_URL: sdcRoot + '/funding-groups', + SDC_SCHOOL_COLLECTION: sdcRoot + '/sdcSchoolCollection' } }; diff --git a/tools/config/update-configmap.sh b/tools/config/update-configmap.sh index 1392f5ef1..5038110c1 100644 --- a/tools/config/update-configmap.sh +++ b/tools/config/update-configmap.sh @@ -278,7 +278,7 @@ BANNER_COLOR="$bannerColor" WEB_SOCKET_URL="wss://$SERVER_FRONTEND/api/socket" echo Creating config map $APP_NAME-backend-config-map -oc create -n $PEN_NAMESPACE-$envValue configmap $APP_NAME-backend-config-map --from-literal=WEB_SOCKET_URL="$WEB_SOCKET_URL" --from-literal=BANNER_COLOR="$BANNER_COLOR" --from-literal=BANNER_ENVIRONMENT="$BANNER_ENVIRONMENT" --from-literal=TZ=$TZVALUE --from-literal=UI_PRIVATE_KEY="$UI_PRIVATE_KEY_VAL" --from-literal=SITEMINDER_LOGOUT_ENDPOINT="$siteMinderLogoutUrl" --from-literal=UI_PUBLIC_KEY="$UI_PUBLIC_KEY_VAL" --from-literal=ID=$APP_NAME-soam --from-literal=SECRET=$studentAdminClientSecret --from-literal=SERVER_FRONTEND=https://$SERVER_FRONTEND --from-literal=ISSUER=STUDENT_ADMIN_APPLICATION --from-literal=SOAM_PUBLIC_KEY="$formattedPublicKey" --from-literal=PEN_REQUEST_EMAIL_API_URL="http://student-profile-email-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/gmp" --from-literal=PEN_REQUEST_API_URL="http://pen-request-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/pen-request" --from-literal=DISCOVERY=https://$SOAM_KC/auth/realms/$SOAM_KC_REALM_ID/.well-known/openid-configuration --from-literal=KC_DOMAIN=https://$SOAM_KC/auth/realms/$SOAM_KC_REALM_ID --from-literal=PEN_DEMOGRAPHICS_URL="http://pen-demographics-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080" --from-literal=DIGITAL_ID_URL="http://digitalid-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/digital-id" --from-literal=STUDENT_API_URL="http://student-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/student" --from-literal=LOG_LEVEL=info --from-literal=IDIR_IDP_HINT=keycloak_bcdevexchange_idir --from-literal=REDIS_HOST=redis --from-literal=REDIS_PORT=6379 --from-literal=STUDENT_PROFILE_API_URL="http://student-profile-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/student-profile" --from-literal=SCHOOL_API_URL="http://school-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1" --from-literal=STUDENT_PROFILE_EMAIL_API_URL="http://student-profile-email-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/ump" --from-literal=PROFILE_REQUEST_SAGA_API_URL="http://student-profile-saga-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/student-profile-saga" --from-literal=NATS_URL="$NATS_URL" --from-literal=NATS_CLUSTER="$NATS_CLUSTER" --from-literal=UMP_ROLES="STUDENT_PROFILE_ADMIN,STUDENT_PROFILE_READ_ONLY" --from-literal=GMP_ROLES="STUDENT_ADMIN,STUDENT_ADMIN_READ_ONLY" --from-literal=STUDENT_SEARCH_ADMIN="STUDENT_SEARCH_ADMIN" --from-literal=STUDENT_SEARCH_ROLES="STUDENT_SEARCH_ADMIN,STUDENT_SEARCH_READ_ONLY" --from-literal=STUDENT_ADMIN_ADMINISTRATOR="STUDENT_ADMIN_ADMINISTRATOR" --from-literal=UMP_ROLE_ADMIN="STUDENT_PROFILE_ADMIN" --from-literal=GMP_ROLE_ADMIN="STUDENT_ADMIN" --from-literal=PEN_REQUEST_BATCH_ADMIN="PEN_REQUEST_BATCH_ADMIN" --from-literal=EDX_ADMIN="EDX_ADMIN" --from-literal=PEN_REQUEST_BATCH_API_URL="http://pen-reg-batch-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1" --from-literal=PEN_MATCH_API_URL="http://pen-match-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/pen-match" --from-literal=SESSION_MAX_AGE=$sessionMaxAge --from-literal=TOKEN_EXPIRES_IN=$tokenExpiresIn --from-literal=SCHEDULER_CRON_STALE_SAGA_RECORD_REDIS="0/30 * * * * *" --from-literal=MIN_TIME_BEFORE_SAGA_IS_STALE_IN_SECONDS=10 --from-literal=PEN_SERVICES_API_URL="http://pen-services-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/pen-services" --from-literal=PEN_TRAX_API_URL="http://pen-trax-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1" --from-literal=SLD_API_URL="http://sld-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1" --from-literal=QUEUE_GROUP_NAME="student-admin-node-queue-group" --from-literal=STAN_ENABLED="true" --from-literal=NODE_ENV="openshift" --from-literal=SCHEDULER_CRON_DOC_TYPE_MIGRATION="$SCHEDULER_CRON_DOC_TYPE_MIGRATION" --from-literal=ENABLE_PRR_STUDENT_DEMOGRAPHICS="$ENABLE_PRR_STUDENT_DEMOGRAPHICS" --from-literal=NOMINAL_ROLL="NOMINAL_ROLL_EDIT" --from-literal=MACRO_API_URL="http://macro-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/macro" --from-literal=NOMINAL_ROLL_API_URL="http://pen-nominal-roll-api-main.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/nominal-roll" --from-literal=STUDENT_ANALYTICS_STUDENT_PROFILE="STUDENT_ANALYTICS_STUDENT_PROFILE" --from-literal=STUDENT_ANALYTICS_BATCH="STUDENT_ANALYTICS_BATCH" --from-literal=NOMINAL_ROLL_ROLES="NOMINAL_ROLL,NOMINAL_ROLL_EDIT" --from-literal=EDX_API_URL="http://edx-api-master.$EDX_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/edx" --from-literal=INSTITUTE_API_URL="http://institute-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/institute" --from-literal=EDX_PEN_TEAM_ROLES="PEN_TEAM_ROLE" --dry-run -o yaml | oc apply -f - +oc create -n $PEN_NAMESPACE-$envValue configmap $APP_NAME-backend-config-map --from-literal=WEB_SOCKET_URL="$WEB_SOCKET_URL" --from-literal=BANNER_COLOR="$BANNER_COLOR" --from-literal=BANNER_ENVIRONMENT="$BANNER_ENVIRONMENT" --from-literal=TZ=$TZVALUE --from-literal=UI_PRIVATE_KEY="$UI_PRIVATE_KEY_VAL" --from-literal=SITEMINDER_LOGOUT_ENDPOINT="$siteMinderLogoutUrl" --from-literal=UI_PUBLIC_KEY="$UI_PUBLIC_KEY_VAL" --from-literal=ID=$APP_NAME-soam --from-literal=SECRET=$studentAdminClientSecret --from-literal=SERVER_FRONTEND=https://$SERVER_FRONTEND --from-literal=ISSUER=STUDENT_ADMIN_APPLICATION --from-literal=SOAM_PUBLIC_KEY="$formattedPublicKey" --from-literal=PEN_REQUEST_EMAIL_API_URL="http://student-profile-email-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/gmp" --from-literal=PEN_REQUEST_API_URL="http://pen-request-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/pen-request" --from-literal=DISCOVERY=https://$SOAM_KC/auth/realms/$SOAM_KC_REALM_ID/.well-known/openid-configuration --from-literal=KC_DOMAIN=https://$SOAM_KC/auth/realms/$SOAM_KC_REALM_ID --from-literal=PEN_DEMOGRAPHICS_URL="http://pen-demographics-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080" --from-literal=DIGITAL_ID_URL="http://digitalid-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/digital-id" --from-literal=STUDENT_API_URL="http://student-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/student" --from-literal=LOG_LEVEL=info --from-literal=IDIR_IDP_HINT=keycloak_bcdevexchange_idir --from-literal=REDIS_HOST=redis --from-literal=REDIS_PORT=6379 --from-literal=STUDENT_PROFILE_API_URL="http://student-profile-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/student-profile" --from-literal=SCHOOL_API_URL="http://school-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1" --from-literal=STUDENT_PROFILE_EMAIL_API_URL="http://student-profile-email-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/ump" --from-literal=PROFILE_REQUEST_SAGA_API_URL="http://student-profile-saga-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/student-profile-saga" --from-literal=NATS_URL="$NATS_URL" --from-literal=NATS_CLUSTER="$NATS_CLUSTER" --from-literal=UMP_ROLES="STUDENT_PROFILE_ADMIN,STUDENT_PROFILE_READ_ONLY" --from-literal=GMP_ROLES="STUDENT_ADMIN,STUDENT_ADMIN_READ_ONLY" --from-literal=STUDENT_SEARCH_ADMIN="STUDENT_SEARCH_ADMIN" --from-literal=STUDENT_SEARCH_ROLES="STUDENT_SEARCH_ADMIN,STUDENT_SEARCH_READ_ONLY" --from-literal=STUDENT_ADMIN_ADMINISTRATOR="STUDENT_ADMIN_ADMINISTRATOR" --from-literal=UMP_ROLE_ADMIN="STUDENT_PROFILE_ADMIN" --from-literal=GMP_ROLE_ADMIN="STUDENT_ADMIN" --from-literal=PEN_REQUEST_BATCH_ADMIN="PEN_REQUEST_BATCH_ADMIN" --from-literal=EDX_ADMIN="EDX_ADMIN" --from-literal=PEN_REQUEST_BATCH_API_URL="http://pen-reg-batch-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1" --from-literal=PEN_MATCH_API_URL="http://pen-match-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/pen-match" --from-literal=SESSION_MAX_AGE=$sessionMaxAge --from-literal=TOKEN_EXPIRES_IN=$tokenExpiresIn --from-literal=SCHEDULER_CRON_STALE_SAGA_RECORD_REDIS="0/30 * * * * *" --from-literal=MIN_TIME_BEFORE_SAGA_IS_STALE_IN_SECONDS=10 --from-literal=PEN_SERVICES_API_URL="http://pen-services-api-master.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/pen-services" --from-literal=PEN_TRAX_API_URL="http://pen-trax-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1" --from-literal=SLD_API_URL="http://sld-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1" --from-literal=QUEUE_GROUP_NAME="student-admin-node-queue-group" --from-literal=STAN_ENABLED="true" --from-literal=NODE_ENV="openshift" --from-literal=SCHEDULER_CRON_DOC_TYPE_MIGRATION="$SCHEDULER_CRON_DOC_TYPE_MIGRATION" --from-literal=ENABLE_PRR_STUDENT_DEMOGRAPHICS="$ENABLE_PRR_STUDENT_DEMOGRAPHICS" --from-literal=NOMINAL_ROLL="NOMINAL_ROLL_EDIT" --from-literal=MACRO_API_URL="http://macro-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/macro" --from-literal=NOMINAL_ROLL_API_URL="http://pen-nominal-roll-api-main.$PEN_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/nominal-roll" --from-literal=STUDENT_ANALYTICS_STUDENT_PROFILE="STUDENT_ANALYTICS_STUDENT_PROFILE" --from-literal=STUDENT_ANALYTICS_BATCH="STUDENT_ANALYTICS_BATCH" --from-literal=NOMINAL_ROLL_ROLES="NOMINAL_ROLL,NOMINAL_ROLL_EDIT" --from-literal=EDX_API_URL="http://edx-api-master.$EDX_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/edx" --from-literal=SDC_API_URL="http://student-data-collection-api-master.$OPENSHIFT_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/student-data-collection" --from-literal=INSTITUTE_API_URL="http://institute-api-master.$COMMON_NAMESPACE-$envValue.svc.cluster.local:8080/api/v1/institute" --from-literal=EDX_PEN_TEAM_ROLES="PEN_TEAM_ROLE" --dry-run -o yaml | oc apply -f - echo echo Setting environment variables for $APP_NAME-backend-$SOAM_KC_REALM_ID application oc -n $PEN_NAMESPACE-$envValue set env --from=configmap/$APP_NAME-backend-config-map dc/$APP_NAME-backend-$SOAM_KC_REALM_ID