Skip to content

Commit

Permalink
Add app config 'requireAccessCode' for users to lock access to online…
Browse files Browse the repository at this point in the history
… surveys
  • Loading branch information
esurface committed May 31, 2024
1 parent a92d271 commit 69fce19
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@
<h2>Instructions: </h2>

<div>
In the Unpublished Surveys section, click the
<button class="info-button">
<i class="material-icons tangy-location-list-icon">published_with_changes</i>
</button>
button to "Publish" an online survey. It will then be listed in the Published Surveys section.
</div>

<div>
In the Published Surveys section, use the link
In the <strong>Published Surveys</strong> section, use the link
<button class="info-button">
<i class="material-icons tangy-location-list-icon">link</i>
</button>
Expand All @@ -21,14 +13,40 @@ <h2>Instructions: </h2>
<i class="material-icons tangy-location-list-icon">unpublished</i>
</button>
button to "Un-publish" an online survey.
The
<button class="info-button">
<i class="material-icons tangy-location-list-icon">lock</i>
</button> button appears for surveys that require a Device User and Access Code.
</div>

<div>
In the <strong>Unpublish Surveys</strong> section, click the
<button class="info-button">
<i class="material-icons tangy-location-list-icon">published_with_changes</i>
</button>
button to "Publish" an online survey. It will then be listed in the Published Surveys section.
To 'Publish' a survey and require a Device User to provide an Access Code, click the
<button class="info-button">
<i class="material-icons tangy-location-list-icon">lock</i>
</button> button.
</div>

<div>

</div>

</div>
<h2 class="tangy-foreground-secondary">{{'Published Surveys'|translate}}</h2>
<mat-list class="drag-list">
<mat-list-item class="drag-item" *ngFor="let form of publishedSurveys; let index=index">
<span>{{index+1}}</span>
<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span>&nbsp;&nbsp;</span>
<span class="tangy-spacer" [innerHTML]="form.title|unsanitizeHtml"></span>
<span *ngIf="form.locked">
<button mat-icon-button class="lock-button">
<i class="material-icons mat-32 tangy-location-list-icon">lock</i>
</button>
</span>
<span>{{form.updatedOn|date :'medium'}}
</span>

Expand All @@ -49,9 +67,12 @@ <h2 class="tangy-foreground-secondary">{{'Unpublished Surveys'|translate}}</h2>
<span class="tangy-spacer" [innerHTML]="form.title|unsanitizeHtml"></span>

<span *appHasAPermission="let i;group:group._id; permission:'can_manage_forms'">
<button mat-icon-button (click)="publishSurvey(form.id, form.title)">
<button mat-icon-button (click)="publishSurvey(form.id, form.title, false)">
<i class="material-icons mat-32 tangy-location-list-icon">published_with_changes</i>
</button>
<button mat-icon-button (click)="publishSurvey(form.id, form.title, true)">
<i class="material-icons mat-32 tangy-location-list-icon">lock</i>
</button>
</span>

<span >{{form.updatedOn|date :'medium'}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ export class ReleaseOnlineSurveyComponent implements OnInit {
this.publishedSurveys = surveyData.filter(e => e.published);
this.unPublishedSurveys = surveyData.filter(e => !e.published);
}
async publishSurvey(formId, appName) {
async publishSurvey(formId, appName, locked) {
try {
await this.groupService.publishSurvey(this.groupId, formId, 'prod', appName);
await this.groupService.publishSurvey(this.groupId, formId, 'prod', appName, locked);
await this.getForms();
this.errorHandler.handleError(_TRANSLATE('Survey Published Successfully.'));
} catch (error) {
Expand Down
7 changes: 4 additions & 3 deletions editor/src/app/groups/services/groups.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,10 +398,11 @@ export class GroupsService {
}
}

async publishSurvey(groupId, formId, releaseType = 'prod', appName) {
async publishSurvey(groupId, formId, releaseType = 'prod', appName, locked=false) {
try {
const response = await this.httpClient.post(`/onlineSurvey/publish/${groupId}/${formId}`, {groupId, formId}, {observe: 'response'}).toPromise();
await this.httpClient.get(`/editor/release-online-survey-app/${groupId}/${formId}/${releaseType}/${appName}/${response.body['uploadKey']}`).toPromise()
const response = await this.httpClient.post(`/onlineSurvey/publish/${groupId}/${formId}`, {groupId, formId, locked}, {observe: 'response'}).toPromise();
const uploadKey = response.body['uploadKey']
await this.httpClient.post(`/editor/release-online-survey-app/${groupId}/${formId}/${releaseType}/${appName}`, {uploadKey, locked}).toPromise()
} catch (error) {
this.errorHandler.handleError(_TRANSLATE('Could Not Contact Server.'));
}
Expand Down
17 changes: 12 additions & 5 deletions online-survey-app/src/app/core/auth/_guards/login-guard.service.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { AuthenticationService } from '../_services/authentication.service';
import { AppConfigService } from 'src/app/shared/_services/app-config.service';

@Injectable()
export class LoginGuard implements CanActivate {

constructor(
private router: Router,
private authenticationService: AuthenticationService
private authenticationService: AuthenticationService,
private appConfigService: AppConfigService
) { }
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (await this.authenticationService.isLoggedIn()) {
return true;
const config = await this.appConfigService.getAppConfig();
if (config['requireAccessCode'] === 'true') {
if (await this.authenticationService.isLoggedIn()) {
return true;
}
this.router.navigate(['survey-login'], { queryParams: { returnUrl: state.url } });
return false;
}
this.router.navigate(['survey-login'], { queryParams: { returnUrl: state.url } });
return false;

return true;
}
}
3 changes: 2 additions & 1 deletion online-survey-app/src/assets/app-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"groupId":"GROUP_ID",
"languageDirection": "ltr",
"languageCode": "en",
"appName":"APP_NAME"
"appName":"APP_NAME",
"requireAccessCode": "REQUIRE_ACCESS_CODE"
}
5 changes: 4 additions & 1 deletion server/src/express-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ app.get('/users/groupPermissionsByGroupName/:groupName', isAuthenticated, getUse
* User Profile API
*/

app.post('/userProfile/create/:groupId', createUserProfile);
app.post('/userProfile/createUserProfile/:groupId', createUserProfile);

/**
* Case API routes
Expand Down Expand Up @@ -321,8 +321,11 @@ app.post('/editor/release-apk/:group', isAuthenticated, releaseAPK)

app.post('/editor/release-pwa/:group/', isAuthenticated, releasePWA)

// TODO @deprice: This route should be removed.
app.use('/editor/release-online-survey-app/:groupId/:formId/:releaseType/:appName/:uploadKey/', isAuthenticated, releaseOnlineSurveyApp)

app.post('/editor/release-online-survey-app/:groupId/:formId/:releaseType/:appName/', isAuthenticated, releaseOnlineSurveyApp)

app.use('/editor/unrelease-online-survey-app/:groupId/:formId/:releaseType/', isAuthenticated, unreleaseOnlineSurveyApp)

app.post('/editor/file/save', isAuthenticated, async function (req, res) {
Expand Down
3 changes: 3 additions & 0 deletions server/src/online-survey.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const GROUPS_DB = new DB('groups');
const { v4: uuidV4 } = require('uuid');
const createFormKey = () => uuidV4();
const { createAccessCodeJWT } = require('./auth-utils');
const { log } = require('console');

const login = async (req, res) => {
try {
Expand Down Expand Up @@ -100,6 +101,7 @@ const publishSurvey = async (req, res) => {
let surveyInfo = {}
try {
const { formId, groupId } = req.params;
const locked = req.body.locked || false;
const data = (await GROUPS_DB.get(groupId));
data.onlineSurveys = data.onlineSurveys ? data.onlineSurveys : [];
let surveysIndex = data.onlineSurveys.findIndex((e) => e.formId === formId);
Expand All @@ -109,6 +111,7 @@ const publishSurvey = async (req, res) => {
updatedOn: new Date(),
updatedBy: req.user.name,
uploadKey: createFormKey(),
locked: locked
};
if (surveysIndex < 0) {
data.onlineSurveys = [...data.onlineSurveys, surveyInfo];
Expand Down
13 changes: 11 additions & 2 deletions server/src/releases.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,23 @@ const releasePWA = async (req, res)=>{

const releaseOnlineSurveyApp = async(req, res) => {
// @TODO Make sure user is member of group.
debugger;
const groupId = sanitize(req.params.groupId)
const formId = sanitize(req.params.formId)
const releaseType = sanitize(req.params.releaseType)
const appName = sanitize(req.params.appName)
const uploadKey = sanitize(req.params.uploadKey)

let uploadKey;
if (req.params.uploadKey) {
uploadKey = sanitize(req.params.uploadKey)
} else {
uploadKey = sanitize(req.body.uploadKey)
}
debugger;
const requireAccessCode = req.body.locked ? req.body.locked : false

try {
const cmd = `release-online-survey-app ${groupId} ${formId} ${releaseType} "${appName}" ${uploadKey} `
const cmd = `release-online-survey-app ${groupId} ${formId} ${releaseType} "${appName}" ${uploadKey} ${requireAccessCode}`
log.info(`RELEASING Online survey app: ${cmd}`)
await exec(cmd)
res.send({ statusCode: 200, data: 'ok' })
Expand Down
10 changes: 9 additions & 1 deletion server/src/scripts/release-online-survey-app.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ FORM_ID="$2"
RELEASE_TYPE="$3"
APP_NAME=$(echo "$4" | sed "s/ /_/g") # sanitize spaces in app name
UPLOAD_KEY="$5"
REQUIRE_ACCESS_CODE="$6"

if [ "$2" = "--help" ] || [ "$GROUP_ID" = "" ] || [ "$FORM_ID" = "" ] || [ "$RELEASE_TYPE" = "" ]; then
echo ""
echo "RELEASE Online Survey App"
echo "A command for releasing the Online Survey App for a specific form in a group."
echo ""
echo "./release-online-survey-app.sh <groupId> <formId> <releaseType> <appName> <uploadKey>"
echo "./release-online-survey-app.sh <groupId> <formId> <releaseType> <appName> <uploadKey> [requireAccessCode]"
echo ""
echo "Release type is either qa or prod."
echo ""
Expand Down Expand Up @@ -54,10 +55,17 @@ cp /tangerine/translations/*.json $RELEASE_DIRECTORY/assets/

FORM_UPLOAD_URL="/onlineSurvey/saveResponse/$GROUP_ID/$FORM_ID"

if [[ $REQUIRE_ACCESS_CODE == 'true' ]]; then
REQUIRE_ACCESS_CODE="true"
else
REQUIRE_ACCESS_CODE="false"
fi

# NOTE: App Config does NOT come from the app-config.json file in the release directory
sed -i -e "s#GROUP_ID#"$GROUP_ID"#g" $RELEASE_DIRECTORY/assets/app-config.json
sed -i -e "s#FORM_UPLOAD_URL#"$FORM_UPLOAD_URL"#g" $RELEASE_DIRECTORY/assets/app-config.json
sed -i -e "s#UPLOAD_KEY#"$UPLOAD_KEY"#g" $RELEASE_DIRECTORY/assets/app-config.json
sed -i -e "s#APP_NAME#"$APP_NAME"#g" $RELEASE_DIRECTORY/assets/app-config.json
sed -i -e "s#REQUIRE_ACCESS_CODE#"$REQUIRE_ACCESS_CODE"#g" $RELEASE_DIRECTORY/assets/app-config.json

echo "Release with UUID of $UUID to $RELEASE_DIRECTORY with Build ID of $BUILD_ID, channel of $RELEASE_TYPE"

0 comments on commit 69fce19

Please sign in to comment.