diff --git a/CSETWebApi/CSETWeb_Api/CSETWeb_ApiCore/Controllers/ProtectedFeatureController.cs b/CSETWebApi/CSETWeb_Api/CSETWeb_ApiCore/Controllers/ProtectedFeatureController.cs
index b967600586..7e7f2d8c14 100644
--- a/CSETWebApi/CSETWeb_Api/CSETWeb_ApiCore/Controllers/ProtectedFeatureController.cs
+++ b/CSETWebApi/CSETWeb_Api/CSETWeb_ApiCore/Controllers/ProtectedFeatureController.cs
@@ -12,8 +12,7 @@
using CSETWebCore.DataLayer.Model;
using CSETWebCore.Model.Module;
using CSETWebCore.Interfaces.Helpers;
-using CSETWebCore.Helpers;
-using Namotion.Reflection;
+using Microsoft.AspNetCore.Authorization;
namespace CSETWebCore.Api.Controllers
{
@@ -116,9 +115,10 @@ public IActionResult SetCisaAssessorWorkflow([FromBody] bool cisaWorkflowEnabled
}
[HttpGet]
+ [AllowAnonymous]
[Route("api/EnableProtectedFeature/getCisaAssessorWorkflow")]
///
- /// Marks the FAA set as 'unlocked.'
+ /// Gets the status of the CISA assessor workflow for the current user.
///
///
public IActionResult GetCisaAssessorWorkflow()
@@ -126,6 +126,7 @@ public IActionResult GetCisaAssessorWorkflow()
var userId = _tokenManager.GetCurrentUserId();
var ak = _tokenManager.GetAccessKey();
+ // Assume false if we can't find the user or access key (they are probably on the login page).
bool cisaWorkflowEnabled = false;
if (userId != null)
diff --git a/CSETWebNg/src/app/dialogs/enable-protected/enable-protected.component.html b/CSETWebNg/src/app/dialogs/enable-protected/enable-protected.component.html
index 0719705522..2bbb868ead 100644
--- a/CSETWebNg/src/app/dialogs/enable-protected/enable-protected.component.html
+++ b/CSETWebNg/src/app/dialogs/enable-protected/enable-protected.component.html
@@ -38,7 +38,7 @@
-
+
diff --git a/CSETWebNg/src/app/dialogs/enable-protected/enable-protected.component.ts b/CSETWebNg/src/app/dialogs/enable-protected/enable-protected.component.ts
index 233fc094e0..19cc7439fa 100644
--- a/CSETWebNg/src/app/dialogs/enable-protected/enable-protected.component.ts
+++ b/CSETWebNg/src/app/dialogs/enable-protected/enable-protected.component.ts
@@ -39,6 +39,7 @@ export class EnableProtectedComponent implements OnInit {
message: any;
enableFeatureButtonClick: boolean = false;
cisaWorkflowEnabled: boolean = false;
+ cisaWorkflowStatusLoaded: boolean = false;
constructor(private dialog: MatDialogRef
,
private featureSvc: EnableFeatureService,
@@ -54,6 +55,7 @@ export class EnableProtectedComponent implements OnInit {
this.configSvc.getCisaAssessorWorkflow().subscribe((cisaWorkflowEnabled: boolean) => {
this.cisaWorkflowEnabled = cisaWorkflowEnabled;
+ this.cisaWorkflowStatusLoaded = true;
});
}
diff --git a/CSETWebNg/src/app/services/authentication.service.ts b/CSETWebNg/src/app/services/authentication.service.ts
index 7d4ce48f85..198abe4f80 100644
--- a/CSETWebNg/src/app/services/authentication.service.ts
+++ b/CSETWebNg/src/app/services/authentication.service.ts
@@ -28,7 +28,6 @@ import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Router } from '@angular/router';
-
import { JwtParser } from '../helpers/jwt-parser';
import { ChangePassword } from '../models/reset-pass.model';
import { CreateUser } from './../models/user.model';
@@ -36,332 +35,360 @@ import { ConfigService } from './config.service';
import { environment } from '../../environments/environment';
export interface LoginResponse {
- token: string;
- resetRequired: boolean;
- isPasswordExpired: boolean;
- isSuperUser: boolean;
- userLastName: string;
- userFirstName: string;
- userId?: number;
- email: string;
- accessKey?: string;
- exportExtension: string;
- importExtensions: string;
- linkerTime: string;
+ token: string;
+ resetRequired: boolean;
+ isPasswordExpired: boolean;
+ isSuperUser: boolean;
+ userLastName: string;
+ userFirstName: string;
+ userId?: number;
+ email: string;
+ accessKey?: string;
+ exportExtension: string;
+ importExtensions: string;
+ linkerTime: string;
}
const headers = {
- headers: new HttpHeaders()
- .set('Content-Type', 'application/json'),
- params: new HttpParams()
+ headers: new HttpHeaders().set('Content-Type', 'application/json'),
+ params: new HttpParams()
};
@Injectable()
export class AuthenticationService {
- isLocal: boolean;
- private initialized = false;
- private parser = new JwtParser();
-
- isAuthenticated = false;
-
- constructor(
- private http: HttpClient,
- private router: Router,
- private configSvc: ConfigService,
- public dialog: MatDialog
- ) {
- if (!this.initialized) {
- this.initialized = true;
- }
- }
-
- /**
- * Indicates if the user has agreed to the privacy warning.
- * Returns true if not running as "CSET Online".
- *
- * Only CSET Online requires the user agreement.
- * If not currently running as CSET Online, always returns true.
- */
- hasUserAgreedToPrivacyWarning() {
- if (!this.configSvc.config.behaviors.showPrivacyWarning) {
- return true;
- }
-
- return (sessionStorage.getItem('hasUserAgreedToPrivacyWarning') == 'true');
+ isLocal: boolean;
+ private initialized = false;
+ private parser = new JwtParser();
+
+ isAuthenticated = false;
+
+ constructor(
+ private http: HttpClient,
+ private router: Router,
+ private configSvc: ConfigService,
+ public dialog: MatDialog
+ ) {
+ if (!this.initialized) {
+ this.initialized = true;
}
-
- /**
- *
- */
- checkLocal() {
- return this.http.post(this.configSvc.apiUrl + 'auth/login/standalone',
- JSON.stringify(
- {
- TzOffset: new Date().getTimezoneOffset().toString(),
- // If InstallationMode isn't empty, use it. Otherwise default to environment.appCode
- Scope: (this.configSvc.installationMode || '') !== '' ? this.configSvc.installationMode : environment.appCode
- }
- ), headers)
- .toPromise().then(
- (response: LoginResponse) => {
-
- if (response?.email === null || response?.email === undefined) {
- this.isLocal = false;
- } else {
- this.isLocal = true;
- this.storeUserData(response);
- }
-
- localStorage.setItem('cset.isLocal', (this.isLocal + ''));
-
- localStorage.setItem('cset.linkerDate', response?.linkerTime);
- },
- error => {
- console.warn('Error getting stand-alone status. Assuming non-stand-alone mode.');
- this.isLocal = false;
- });
+ }
+
+ /**
+ * Indicates if the user has agreed to the privacy warning.
+ * Returns true if not running as "CSET Online".
+ *
+ * Only CSET Online requires the user agreement.
+ * If not currently running as CSET Online, always returns true.
+ */
+ hasUserAgreedToPrivacyWarning() {
+ if (!this.configSvc.config.behaviors.showPrivacyWarning) {
+ return true;
}
- /**
- * Calls the API to find out whether this is a local install
- */
- checkLocalInstallStatus() {
- return this.http.get(this.configSvc.apiUrl + 'auth/islocal', headers);
- }
-
- /**
- *
- * @param user
- */
- storeUserData(user: LoginResponse) {
- if (user.token != null) {
- localStorage.setItem('userToken', user.token);
- }
- localStorage.setItem('firstName', user.userFirstName);
- localStorage.setItem('lastName', user.userLastName);
- localStorage.setItem('superUser', '' + user.isSuperUser);
- localStorage.setItem('userId', '' + user.userId);
- localStorage.setItem('email', user.email);
- localStorage.setItem('exportExtension', user.exportExtension);
- localStorage.setItem('importExtensions', user.importExtensions)
- localStorage.setItem('developer', String(false));
-
-
- // schedule the first token refresh event
- this.scheduleTokenRefresh(this.http, user.token);
- }
-
- /**
- *
- * @param email
- * @param password
- */
- login(email: string, password: string) {
- localStorage.clear();
- localStorage.setItem('email', email);
-
- // set the scope (application)
- let scope: string;
-
- switch (this.configSvc.installationMode || '') {
- case 'ACET':
- scope = 'ACET';
- break;
- case 'TSA':
- scope = 'TSA';
- break;
- case 'RRA':
- scope = 'RRA';
- break;
- case 'CF':
- scope = 'CF';
- break;
- case 'IOD':
- scope = 'IOD';
- break;
- default:
- scope = environment.appCode
+ return sessionStorage.getItem('hasUserAgreedToPrivacyWarning') == 'true';
+ }
+
+ /**
+ *
+ */
+ checkLocal() {
+ return this.http
+ .post(
+ this.configSvc.apiUrl + 'auth/login/standalone',
+ JSON.stringify({
+ TzOffset: new Date().getTimezoneOffset().toString(),
+ // If InstallationMode isn't empty, use it. Otherwise default to environment.appCode
+ Scope: (this.configSvc.installationMode || '') !== '' ? this.configSvc.installationMode : environment.appCode
+ }),
+ headers
+ )
+ .toPromise()
+ .then(
+ (response: LoginResponse) => {
+ if (response?.email === null || response?.email === undefined) {
+ this.isLocal = false;
+ } else {
+ this.isLocal = true;
+ this.storeUserData(response);
+ }
+
+ localStorage.setItem('cset.isLocal', this.isLocal + '');
+
+ localStorage.setItem('cset.linkerDate', response?.linkerTime);
+ },
+ (error) => {
+ console.warn('Error getting stand-alone status. Assuming non-stand-alone mode.');
+ this.isLocal = false;
}
-
- return this.http.post(this.configSvc.apiUrl + 'auth/login',
- JSON.stringify(
- {
- Email: email,
- Password: password,
- TzOffset: new Date().getTimezoneOffset().toString(),
- Scope: scope
- }
- ), headers).pipe(
- map((user: LoginResponse) => {
- // store user details and jwt token in local storage to keep user logged in between page refreshes
- this.storeUserData(user);
-
- this.isAuthenticated = true;
-
- return user;
- }));
- }
-
-
- logout() {
- this.isAuthenticated = false;
- this.router.navigate(['/home/logout'], { queryParamsHandling: "preserve" });
- }
-
- /**
- * TODO: This is not working correctly - the local storage stuff
- * hangs around even if we are sitting on the login page again
- */
- // isAuthenticated() {
- // const uid = localStorage.getItem('userId');
- // return !!uid;
- // }
-
-
- /**
- * Schedules an HTTP transaction to refresh the JWT.
- * @param http The current HttpClient instance.
- * @param token A JWT string.
- */
- scheduleTokenRefresh(http: HttpClient, token: string) {
- const refresh = timer(this.calcTokenRefreshTimeout(token));
- refresh.subscribe(
- val => {
- // only schedule a refresh if the user is currently logged on
- if (localStorage.getItem('userToken') != null) {
-
- http.get(this.configSvc.apiUrl + 'auth/token?refresh')
- .subscribe((resp: LoginResponse) => {
- localStorage.removeItem('userToken');
- localStorage.setItem('userToken', resp.token);
-
- // schedule the next refresh
- this.scheduleTokenRefresh(this.http, resp.token);
- }, error => {
- console.log(error.message);
- });
- }
- });
- }
-
-
- /**
- * Returns the timeout interval in milliseconds
- * @param token A JWT string.
- */
- calcTokenRefreshTimeout(token: string): number {
- // extract the expiration timestamp from the token
- const jwt = new JwtParser();
- const parsedToken = jwt.decodeToken(token);
- const expTimeUnix = parsedToken.exp;
-
- const nowUtcUnix = Math.floor((new Date()).getTime() / 1000);
-
- // how many seconds from now until expiry?
- const secondsUntilExpiration = expTimeUnix - nowUtcUnix;
-
- // refresh at 60 seconds lead time before expiry
- const leadSeconds = 60;
- const refreshIntervalMs = (secondsUntilExpiration - leadSeconds) * 1000;
-
- return refreshIntervalMs;
- }
-
- /**
- * Requests a JWT with a short lifespan.
- */
- getShortLivedToken() {
- return this.http.get(this.configSvc.apiUrl + 'auth/token?expSeconds=30000');
- }
-
- getShortLivedTokenForAssessment(assessment_id: number) {
- return this.http.get(this.configSvc.apiUrl + 'auth/token?assessmentId=' + assessment_id + '&expSeconds=30000');
- }
-
- changePassword(data: ChangePassword) {
- return this.http.post(this.configSvc.apiUrl + 'ResetPassword/ChangePassword', JSON.stringify(data), { 'headers': headers.headers, params: headers.params, responseType: 'text' });
- }
-
- checkPassword(data: ChangePassword): Observable {
- return this.http.post(this.configSvc.apiUrl + 'ResetPassword/CheckPassword', JSON.stringify(data), { 'headers': headers.headers, params: headers.params, responseType: 'text' });
- }
-
- updateUser(data: CreateUser): Observable {
- return this.http.post(this.configSvc.apiUrl + 'contacts/UpdateUser', data, headers);
- }
-
- getUserInfo(): Observable {
- return this.http.get(this.configSvc.apiUrl + 'contacts/GetUserInfo');
- }
-
- passwordStatus() {
- return this.http.get(this.configSvc.apiUrl + 'ResetPassword/ResetPasswordStatus/', headers);
- }
-
- getSecurityQuestionsList(email: string) {
- return this.http.get(this.configSvc.apiUrl + 'ResetPassword/SecurityQuestions?email=' + email + '&appCode=' + environment.appCode);
- }
-
- getSecurityQuestionsPotentialList() {
- return this.http.get(this.configSvc.apiUrl + 'ResetPassword/PotentialQuestions');
- }
-
- userToken() {
- return localStorage.getItem('userToken');
+ );
+ }
+
+ /**
+ * Calls the API to find out whether this is a local install
+ */
+ checkLocalInstallStatus() {
+ return this.http.get(this.configSvc.apiUrl + 'auth/islocal', headers);
+ }
+
+ /**
+ *
+ * @param user
+ */
+ storeUserData(user: LoginResponse) {
+ if (user.token != null) {
+ localStorage.setItem('userToken', user.token);
}
-
- userId(): number {
- return parseInt(localStorage.getItem('userId'), 10);
- }
-
- accessKey(): string {
- return localStorage.getItem('accessKey');
- }
-
- email() {
- return localStorage.getItem('email');
- }
-
- firstName() {
- return localStorage.getItem('firstName');
+ localStorage.setItem('firstName', user.userFirstName);
+ localStorage.setItem('lastName', user.userLastName);
+ localStorage.setItem('superUser', '' + user.isSuperUser);
+ localStorage.setItem('userId', '' + user.userId);
+ localStorage.setItem('email', user.email);
+ localStorage.setItem('exportExtension', user.exportExtension);
+ localStorage.setItem('importExtensions', user.importExtensions);
+ localStorage.setItem('developer', String(false));
+
+ // schedule the first token refresh event
+ this.scheduleTokenRefresh(this.http, user.token);
+ }
+
+ /**
+ *
+ * @param email
+ * @param password
+ */
+ login(email: string, password: string) {
+ localStorage.clear();
+ localStorage.setItem('email', email);
+
+ // set the scope (application)
+ let scope: string;
+
+ switch (this.configSvc.installationMode || '') {
+ case 'ACET':
+ scope = 'ACET';
+ break;
+ case 'TSA':
+ scope = 'TSA';
+ break;
+ case 'RRA':
+ scope = 'RRA';
+ break;
+ case 'CF':
+ scope = 'CF';
+ break;
+ case 'IOD':
+ scope = 'IOD';
+ break;
+ default:
+ scope = environment.appCode;
}
- lastName() {
- return localStorage.getItem('lastName');
- }
-
- setUserInfo(info: CreateUser) {
- localStorage.setItem('firstName', info.firstName);
- localStorage.setItem('lastName', info.lastName);
- localStorage.setItem('email', info.primaryEmail);
- }
-
- /**
- *
- */
- loginWithAccessKey(loginKey) {
- const req = JSON.stringify(
- {
- accessKey: loginKey,
- tzOffset: new Date().getTimezoneOffset().toString(),
- Scope: 'CSET'
- }
- )
-
- return this.http.post(this.configSvc.apiUrl + 'auth/login/accesskey', req, headers)
- .pipe(
- map((user: LoginResponse) => {
- // store user details and jwt token in local storage to keep user logged in between page refreshes
- this.storeUserData(user);
-
- return user;
- }));;
- }
-
- /**
- *
- */
- generateAccessKey() {
- return this.http.get(this.configSvc.apiUrl + 'auth/accesskey', { responseType: 'text' });
- }
+ return this.http
+ .post(
+ this.configSvc.apiUrl + 'auth/login',
+ JSON.stringify({
+ Email: email,
+ Password: password,
+ TzOffset: new Date().getTimezoneOffset().toString(),
+ Scope: scope
+ }),
+ headers
+ )
+ .pipe(
+ map((user: LoginResponse) => {
+ // store user details and jwt token in local storage to keep user logged in between page refreshes
+ this.storeUserData(user);
+
+ this.isAuthenticated = true;
+
+ return this.configureCisaAssessorWorkflow(user);
+ })
+ );
+ }
+
+ logout() {
+ this.isAuthenticated = false;
+ this.router.navigate(['/home/logout'], { queryParamsHandling: 'preserve' });
+ }
+
+ /**
+ * TODO: This is not working correctly - the local storage stuff
+ * hangs around even if we are sitting on the login page again
+ */
+ // isAuthenticated() {
+ // const uid = localStorage.getItem('userId');
+ // return !!uid;
+ // }
+
+ /**
+ * Schedules an HTTP transaction to refresh the JWT.
+ * @param http The current HttpClient instance.
+ * @param token A JWT string.
+ */
+ scheduleTokenRefresh(http: HttpClient, token: string) {
+ const refresh = timer(this.calcTokenRefreshTimeout(token));
+ refresh.subscribe((val) => {
+ // only schedule a refresh if the user is currently logged on
+ if (localStorage.getItem('userToken') != null) {
+ http.get(this.configSvc.apiUrl + 'auth/token?refresh').subscribe(
+ (resp: LoginResponse) => {
+ localStorage.removeItem('userToken');
+ localStorage.setItem('userToken', resp.token);
+
+ // schedule the next refresh
+ this.scheduleTokenRefresh(this.http, resp.token);
+ },
+ (error) => {
+ console.log(error.message);
+ }
+ );
+ }
+ });
+ }
+
+ /**
+ * Returns the timeout interval in milliseconds
+ * @param token A JWT string.
+ */
+ calcTokenRefreshTimeout(token: string): number {
+ // extract the expiration timestamp from the token
+ const jwt = new JwtParser();
+ const parsedToken = jwt.decodeToken(token);
+ const expTimeUnix = parsedToken.exp;
+
+ const nowUtcUnix = Math.floor(new Date().getTime() / 1000);
+
+ // how many seconds from now until expiry?
+ const secondsUntilExpiration = expTimeUnix - nowUtcUnix;
+
+ // refresh at 60 seconds lead time before expiry
+ const leadSeconds = 60;
+ const refreshIntervalMs = (secondsUntilExpiration - leadSeconds) * 1000;
+
+ return refreshIntervalMs;
+ }
+
+ /**
+ * Requests a JWT with a short lifespan.
+ */
+ getShortLivedToken() {
+ return this.http.get(this.configSvc.apiUrl + 'auth/token?expSeconds=30000');
+ }
+
+ getShortLivedTokenForAssessment(assessment_id: number) {
+ return this.http.get(this.configSvc.apiUrl + 'auth/token?assessmentId=' + assessment_id + '&expSeconds=30000');
+ }
+
+ changePassword(data: ChangePassword) {
+ return this.http.post(this.configSvc.apiUrl + 'ResetPassword/ChangePassword', JSON.stringify(data), {
+ headers: headers.headers,
+ params: headers.params,
+ responseType: 'text'
+ });
+ }
+
+ checkPassword(data: ChangePassword): Observable {
+ return this.http.post(this.configSvc.apiUrl + 'ResetPassword/CheckPassword', JSON.stringify(data), {
+ headers: headers.headers,
+ params: headers.params,
+ responseType: 'text'
+ });
+ }
+
+ updateUser(data: CreateUser): Observable {
+ return this.http.post(this.configSvc.apiUrl + 'contacts/UpdateUser', data, headers);
+ }
+
+ getUserInfo(): Observable {
+ return this.http.get(this.configSvc.apiUrl + 'contacts/GetUserInfo');
+ }
+
+ passwordStatus() {
+ return this.http.get(this.configSvc.apiUrl + 'ResetPassword/ResetPasswordStatus/', headers);
+ }
+
+ getSecurityQuestionsList(email: string) {
+ return this.http.get(
+ this.configSvc.apiUrl + 'ResetPassword/SecurityQuestions?email=' + email + '&appCode=' + environment.appCode
+ );
+ }
+
+ getSecurityQuestionsPotentialList() {
+ return this.http.get(this.configSvc.apiUrl + 'ResetPassword/PotentialQuestions');
+ }
+
+ userToken() {
+ return localStorage.getItem('userToken');
+ }
+
+ userId(): number {
+ return parseInt(localStorage.getItem('userId'), 10);
+ }
+
+ accessKey(): string {
+ return localStorage.getItem('accessKey');
+ }
+
+ email() {
+ return localStorage.getItem('email');
+ }
+
+ firstName() {
+ return localStorage.getItem('firstName');
+ }
+
+ lastName() {
+ return localStorage.getItem('lastName');
+ }
+
+ setUserInfo(info: CreateUser) {
+ localStorage.setItem('firstName', info.firstName);
+ localStorage.setItem('lastName', info.lastName);
+ localStorage.setItem('email', info.primaryEmail);
+ }
+
+ /**
+ * Checks and sets the current user's cisa assessor workflow option.
+ */
+ configureCisaAssessorWorkflow(user) {
+ return this.configSvc
+ .getCisaAssessorWorkflow()
+ .toPromise()
+ .then((cisaAssessorWorkflowEnabled) => {
+ if (cisaAssessorWorkflowEnabled) {
+ return this.configSvc.enableCisaAssessorWorkflow().then(() => {
+ return user;
+ });
+ } else {
+ return user;
+ }
+ });
+ }
+
+ /**
+ *
+ */
+ loginWithAccessKey(loginKey) {
+ const req = JSON.stringify({
+ accessKey: loginKey,
+ tzOffset: new Date().getTimezoneOffset().toString(),
+ Scope: 'CSET'
+ });
+
+ return this.http.post(this.configSvc.apiUrl + 'auth/login/accesskey', req, headers).pipe(
+ map((user: LoginResponse) => {
+ // store user details and jwt token in local storage to keep user logged in between page refreshes
+ this.storeUserData(user);
+
+ return this.configureCisaAssessorWorkflow(user);
+ })
+ );
+ }
+
+ /**
+ *
+ */
+ generateAccessKey() {
+ return this.http.get(this.configSvc.apiUrl + 'auth/accesskey', { responseType: 'text' });
+ }
}
diff --git a/CSETWebNg/src/app/services/config.service.ts b/CSETWebNg/src/app/services/config.service.ts
index 180ffa81e9..e543f6556a 100644
--- a/CSETWebNg/src/app/services/config.service.ts
+++ b/CSETWebNg/src/app/services/config.service.ts
@@ -104,15 +104,9 @@ export class ConfigService {
.toPromise()
.then((cisaAssessorWorkflowEnabled) => {
if (cisaAssessorWorkflowEnabled) {
- return this.http
- .get('assets/settings/config.IOD.json')
- .toPromise()
- .then((iodConfig) => {
- merge(this.config, iodConfig);
- localStorage.setItem('installationMode', this.config.installationMode.toUpperCase());
- this.setConfigPropertiesForLocalService();
- });
+ return this.enableCisaAssessorWorkflow()
}
+
localStorage.setItem('installationMode', this.config.installationMode.toUpperCase());
});
});
@@ -123,6 +117,17 @@ export class ConfigService {
}
}
+ enableCisaAssessorWorkflow() {
+ return this.http
+ .get('assets/settings/config.IOD.json')
+ .toPromise()
+ .then((iodConfig) => {
+ merge(this.config, iodConfig);
+ localStorage.setItem('installationMode', this.config.installationMode.toUpperCase());
+ this.setConfigPropertiesForLocalService();
+ });
+ }
+
/**
*
*/
@@ -225,10 +230,7 @@ export class ConfigService {
}
setCisaAssessorWorkflow(cisaAssessorWorkflowEnabled: boolean) {
- return this.http.post(
- this.apiUrl + 'EnableProtectedFeature/setCisaAssessorWorkflow',
- cisaAssessorWorkflowEnabled
- );
+ return this.http.post(this.apiUrl + 'EnableProtectedFeature/setCisaAssessorWorkflow', cisaAssessorWorkflowEnabled);
}
switchConfigsForMode(installationMode) {