diff --git a/.circleci/config.yml b/.circleci/config.yml
index f158f16a88d..67c0a948633 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -871,6 +871,7 @@ commands:
export FEATURE_FLAG_COAST_GUARD_EMPLID=true
export FEATURE_FLAG_MOVE_LOCK=false
export FEATURE_FLAG_OKTA_DODID_INPUT=false
+ export FEATURE_FLAG_HEADQUARTERS_ROLE=false
export FEATURE_FLAG_SAFETY_MOVE=false
export FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
@@ -906,6 +907,7 @@ commands:
FEATURE_FLAG_COAST_GUARD_EMPLID: 'true'
FEATURE_FLAG_MOVE_LOCK: 'false'
FEATURE_FLAG_OKTA_DODID_INPUT: 'false'
+ FEATURE_FLAG_HEADQUARTERS_ROLE: 'false'
FEATURE_FLAG_SAFETY_MOVE: 'false'
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS: 'false'
command: |
diff --git a/.envrc b/.envrc
index 469b8aa9abe..a37faa98f6a 100644
--- a/.envrc
+++ b/.envrc
@@ -133,6 +133,8 @@ export FEATURE_FLAG_MOVE_LOCK=false
export FEATURE_FLAG_OKTA_DODID_INPUT=false
export FEATURE_FLAG_SAFETY_MOVE=true
+# Feature flag to disable/enable headquarters role
+export FEATURE_FLAG_HEADQUARTERS_ROLE=true
# Feature flag for additional supporting documents uploaded by customer
export FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=true
diff --git a/config/env/demo.app-client-tls.env b/config/env/demo.app-client-tls.env
index 08d06a17154..79d364694fd 100644
--- a/config/env/demo.app-client-tls.env
+++ b/config/env/demo.app-client-tls.env
@@ -38,5 +38,6 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_COAST_GUARD_EMPLID=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
+FEATURE_FLAG_HEADQUARTERS_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
diff --git a/config/env/demo.app.env b/config/env/demo.app.env
index b862ee8b2ff..ba745bd144e 100644
--- a/config/env/demo.app.env
+++ b/config/env/demo.app.env
@@ -44,5 +44,6 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_COAST_GUARD_EMPLID=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
+FEATURE_FLAG_HEADQUARTERS_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
diff --git a/config/env/exp.app-client-tls.env b/config/env/exp.app-client-tls.env
index 374d8703065..6c4b7529d61 100644
--- a/config/env/exp.app-client-tls.env
+++ b/config/env/exp.app-client-tls.env
@@ -38,5 +38,6 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_COAST_GUARD_EMPLID=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
+FEATURE_FLAG_HEADQUARTERS_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
diff --git a/config/env/exp.app.env b/config/env/exp.app.env
index fc28cfa0279..4a724476a71 100644
--- a/config/env/exp.app.env
+++ b/config/env/exp.app.env
@@ -44,5 +44,6 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_COAST_GUARD_EMPLID=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
+FEATURE_FLAG_HEADQUARTERS_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
diff --git a/config/env/loadtest.app-client-tls.env b/config/env/loadtest.app-client-tls.env
index 75653d1c217..6193f09f1f1 100644
--- a/config/env/loadtest.app-client-tls.env
+++ b/config/env/loadtest.app-client-tls.env
@@ -36,5 +36,6 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_COAST_GUARD_EMPLID=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
+FEATURE_FLAG_HEADQUARTERS_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
diff --git a/config/env/loadtest.app.env b/config/env/loadtest.app.env
index 229b4625373..14bebecf623 100644
--- a/config/env/loadtest.app.env
+++ b/config/env/loadtest.app.env
@@ -42,5 +42,6 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_COAST_GUARD_EMPLID=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
+FEATURE_FLAG_HEADQUARTERS_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
diff --git a/config/env/prd.app-client-tls.env b/config/env/prd.app-client-tls.env
index 3a1054eb475..990eb2861c8 100644
--- a/config/env/prd.app-client-tls.env
+++ b/config/env/prd.app-client-tls.env
@@ -35,5 +35,6 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_COAST_GUARD_EMPLID=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
+FEATURE_FLAG_HEADQUARTERS_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
diff --git a/config/env/prd.app.env b/config/env/prd.app.env
index 4ca8b3bd756..8914cca5e36 100644
--- a/config/env/prd.app.env
+++ b/config/env/prd.app.env
@@ -43,5 +43,6 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_COAST_GUARD_EMPLID=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
+FEATURE_FLAG_HEADQUARTERS_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
diff --git a/config/env/stg.app-client-tls.env b/config/env/stg.app-client-tls.env
index 9b14e4d8028..448e777fbea 100644
--- a/config/env/stg.app-client-tls.env
+++ b/config/env/stg.app-client-tls.env
@@ -37,5 +37,6 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_COAST_GUARD_EMPLID=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
+FEATURE_FLAG_HEADQUARTERS_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
diff --git a/config/env/stg.app.env b/config/env/stg.app.env
index 1f00064f3c0..e74bb3c1def 100644
--- a/config/env/stg.app.env
+++ b/config/env/stg.app.env
@@ -44,5 +44,6 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_COAST_GUARD_EMPLID=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
+FEATURE_FLAG_HEADQUARTERS_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
diff --git a/config/flipt/storage/development.features.yaml b/config/flipt/storage/development.features.yaml
index e06b68a7df3..32c48c75263 100644
--- a/config/flipt/storage/development.features.yaml
+++ b/config/flipt/storage/development.features.yaml
@@ -1,6 +1,14 @@
version: "1.2"
namespace: development
flags:
+- key: headquarters_role
+ name: Headquarters Role feature flag
+ type: BOOLEAN_FLAG_TYPE
+ enabled: true
+ rollouts:
+ - segment:
+ key: mil-app
+ value: true
- key: safety_move
name: Safety Move feature flag
type: BOOLEAN_FLAG_TYPE
diff --git a/pkg/handlers/authentication/devlocal.go b/pkg/handlers/authentication/devlocal.go
index 345613fd966..e3cf32b15dd 100644
--- a/pkg/handlers/authentication/devlocal.go
+++ b/pkg/handlers/authentication/devlocal.go
@@ -1141,7 +1141,8 @@ func loginUser(h devlocalAuthHandler, user *models.User, userType string, w http
}
func isOfficeUser(userType string) bool {
- if userType == TOOOfficeUserType || userType == TIOOfficeUserType || userType == ServicesCounselorOfficeUserType || userType == QaeOfficeUserType || userType == CustomerServiceRepresentativeOfficeUserType || userType == HQOfficeUserType {
+ if userType == TOOOfficeUserType || userType == TIOOfficeUserType || userType == ServicesCounselorOfficeUserType ||
+ userType == QaeOfficeUserType || userType == CustomerServiceRepresentativeOfficeUserType || userType == HQOfficeUserType {
return true
}
return false
diff --git a/pkg/handlers/authentication/permissions.go b/pkg/handlers/authentication/permissions.go
index ab4e56de2ba..907e8746d38 100644
--- a/pkg/handlers/authentication/permissions.go
+++ b/pkg/handlers/authentication/permissions.go
@@ -124,7 +124,7 @@ var CustomerServiceRepresentative = RolePermissions{
},
}
-var AllRolesPermissions = []RolePermissions{TOO, TIO, ServicesCounselor, QAE, HQ, CustomerServiceRepresentative}
+var AllRolesPermissions = []RolePermissions{TOO, TIO, ServicesCounselor, QAE, CustomerServiceRepresentative, HQ}
// check if a [user.role] has permissions on a given object
func checkUserPermission(appCtx appcontext.AppContext, session *auth.Session, permission string) (bool, error) {
diff --git a/src/components/Office/RequestAccountForm/RequestAccountForm.test.jsx b/src/components/Office/RequestAccountForm/RequestAccountForm.test.jsx
index a0239602bb2..f684a6a0968 100644
--- a/src/components/Office/RequestAccountForm/RequestAccountForm.test.jsx
+++ b/src/components/Office/RequestAccountForm/RequestAccountForm.test.jsx
@@ -90,10 +90,6 @@ describe('RequestAccountForm component', () => {
const qsaCheckbox = screen.getByTestId('qualityAssuranceEvaluatorCheckBox');
expect(qsaCheckbox).toBeInstanceOf(HTMLInputElement);
expect(qsaCheckbox).not.toBeChecked(false);
-
- const hqCheckbox = screen.getByTestId('headquartersCheckBox');
- expect(hqCheckbox).toBeInstanceOf(HTMLInputElement);
- expect(hqCheckbox).not.toBeChecked(false);
});
it('cancels requesting office account when cancel button is clicked', async () => {
@@ -149,51 +145,6 @@ describe('RequestAccountForm component', () => {
expect(testProps.onSubmit).toHaveBeenCalled();
});
- it('submits Headquarters office account form when submit button is clicked', async () => {
- const mockOfficeId = '3210a533-19b8-4805-a564-7eb452afce10';
- const mockHeadquartersOffice = {
- address: {
- city: 'Test City',
- country: 'United States',
- id: 'a13806fc-0e7d-4dc3-91ca-b802d9da50f1',
- postalCode: '85309',
- state: 'AZ',
- streetAddress1: '7383 N Litchfield Rd',
- streetAddress2: 'Rm 1122',
- },
- created_at: '2018-05-28T14:27:39.198Z',
- gbloc: 'KKFA',
- id: mockOfficeId,
- name: 'Tester',
- phone_lines: [],
- updated_at: '2018-05-28T14:27:39.198Z',
- };
-
- const mockSearchHeadquartersOfficesOpen = () => Promise.resolve([mockHeadquartersOffice]);
- searchTransportationOfficesOpen.mockImplementation(mockSearchHeadquartersOfficesOpen);
-
- renderWithRouter();
-
- await userEvent.type(screen.getByLabelText('First Name'), 'Bob');
- await userEvent.type(screen.getByLabelText('Last Name'), 'Banks');
- await userEvent.type(screen.getByLabelText('Email'), 'banks@gmail.com');
- await userEvent.type(screen.getByLabelText('Telephone'), '333-333-3333');
- await userEvent.type(screen.getByTestId('officeAccountRequestEdipi'), '1111111111');
- await userEvent.type(screen.getByTestId('officeAccountRequestOtherUniqueId'), '1111111111');
-
- const transportationOfficeInput = screen.getByLabelText('Transportation Office');
- fireEvent.change(transportationOfficeInput, { target: { value: 'Tester' } });
- await act(() => selectEvent.select(transportationOfficeInput, /Tester/));
-
- const tooCheckbox = screen.getByTestId('headquartersCheckBox');
- await userEvent.click(tooCheckbox);
-
- const submitButton = await screen.getByTestId('requestOfficeAccountSubmitButton');
- await userEvent.click(submitButton);
-
- expect(testProps.onSubmit).toHaveBeenCalled();
- });
-
it('shows policy error when both TOO and TIO checkboxes are both selected, and goes away after unselecting one of them', async () => {
renderWithRouter();
diff --git a/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx b/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx
index 7ad5bd51f49..a992197e4bb 100644
--- a/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx
+++ b/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx
@@ -96,12 +96,6 @@ export const OfficeAccountRequestFields = ({ render }) => {
name="customerSupportRepresentativeCheckBox"
label="Customer Support Representative"
/>
-
>,
)}
diff --git a/src/constants/userRoles.js b/src/constants/userRoles.js
index 9429c6b0228..245e8542c3a 100644
--- a/src/constants/userRoles.js
+++ b/src/constants/userRoles.js
@@ -6,9 +6,9 @@ export const roleTypes = {
CONTRACTING_OFFICER: 'contracting_officer',
SERVICES_COUNSELOR: 'services_counselor',
PRIME_SIMULATOR: 'prime_simulator',
+ QAE: 'qae',
HQ: 'headquarters',
CUSTOMER_SERVICE_REPRESENTATIVE: 'customer_service_representative',
- QAE: 'qae',
};
export const adminOfficeRoles = [
@@ -18,9 +18,9 @@ export const adminOfficeRoles = [
{ roleType: 'contracting_officer', name: 'Contracting Officer' },
{ roleType: 'services_counselor', name: 'Services Counselor' },
{ roleType: 'prime_simulator', name: 'Prime Simulator' },
+ { roleType: 'qae', name: 'Quality Assurance Evaluator' },
{ roleType: 'headquarters', name: 'Headquarters' },
{ roleType: 'customer_service_representative', name: 'Customer Service Representative' },
- { roleType: 'qae', name: 'Quality Assurance Evaluator' },
];
export const officeRoles = [
@@ -28,7 +28,7 @@ export const officeRoles = [
roleTypes.TIO,
roleTypes.SERVICES_COUNSELOR,
roleTypes.PRIME_SIMULATOR,
+ roleTypes.QAE,
roleTypes.HQ,
roleTypes.CUSTOMER_SERVICE_REPRESENTATIVE,
- roleTypes.QAE,
];
diff --git a/src/pages/Office/RequestAccount/RequestAccount.jsx b/src/pages/Office/RequestAccount/RequestAccount.jsx
index 124f2dc3705..b2ed206b36c 100644
--- a/src/pages/Office/RequestAccount/RequestAccount.jsx
+++ b/src/pages/Office/RequestAccount/RequestAccount.jsx
@@ -62,12 +62,6 @@ export const RequestAccount = ({ setFlashMessage }) => {
roleType: 'qae',
});
}
- if (values.headquartersCheckBox) {
- requestedRoles.push({
- name: 'Headquarters',
- roleType: 'headquarters',
- });
- }
if (values.customerSupportRepresentativeCheckBox) {
requestedRoles.push({
name: 'Customer Service Representative',
diff --git a/src/scenes/SystemAdmin/shared/RolesPrivilegesCheckboxes.jsx b/src/scenes/SystemAdmin/shared/RolesPrivilegesCheckboxes.jsx
index 24d09541f48..5887bc53021 100644
--- a/src/scenes/SystemAdmin/shared/RolesPrivilegesCheckboxes.jsx
+++ b/src/scenes/SystemAdmin/shared/RolesPrivilegesCheckboxes.jsx
@@ -1,13 +1,22 @@
-import React from 'react';
+import React, { useState, useEffect } from 'react';
import { CheckboxGroupInput } from 'react-admin';
-import { adminOfficeRoles } from 'constants/userRoles';
-import { officeUserPrivileges } from 'constants/userPrivileges';
+import { adminOfficeRoles, roleTypes } from 'constants/userRoles';
+import { officeUserPrivileges, elevatedPrivilegeTypes } from 'constants/userPrivileges';
+import { isBooleanFlagEnabled } from 'utils/featureFlags';
const RolesPrivilegesCheckboxInput = (props) => {
let rolesSelected = [];
let privilegesSelected = [];
+ const [isHeadquartersRoleFF, setHeadquartersRoleFF] = useState(false);
+
+ useEffect(() => {
+ isBooleanFlagEnabled('headquarters_role')?.then((enabled) => {
+ setHeadquartersRoleFF(enabled);
+ });
+ }, []);
+
const makeRoleTypeArray = (roles) => {
if (!roles || roles.length === 0) {
rolesSelected = [];
@@ -15,7 +24,9 @@ const RolesPrivilegesCheckboxInput = (props) => {
}
return roles.reduce((rolesArray, role) => {
if (role.roleType) {
- rolesArray.push(role.roleType);
+ if (isHeadquartersRoleFF || (!isHeadquartersRoleFF && role.roleType !== roleTypes.HQ)) {
+ rolesArray.push(role.roleType);
+ }
}
rolesSelected = rolesArray;
@@ -24,16 +35,35 @@ const RolesPrivilegesCheckboxInput = (props) => {
};
const parseRolesCheckboxInput = (input) => {
- if (privilegesSelected.includes('supervisor') || privilegesSelected.includes('safety')) {
+ if (
+ privilegesSelected.includes(elevatedPrivilegeTypes.SUPERVISOR) ||
+ privilegesSelected.includes(elevatedPrivilegeTypes.SAFETY)
+ ) {
var index;
- if (input.includes('customer')) {
- index = input.indexOf('customer');
+ if (input.includes(roleTypes.CUSTOMER)) {
+ index = input.indexOf(roleTypes.CUSTOMER);
if (index !== -1) {
input.splice(index, 1);
}
}
- if (input.includes('contracting_officer')) {
- index = input.indexOf('contracting_officer');
+ if (input.includes(roleTypes.CONTRACTING_OFFICER)) {
+ index = input.indexOf(roleTypes.CONTRACTING_OFFICER);
+ if (index !== -1) {
+ input.splice(index, 1);
+ }
+ }
+ }
+
+ if (!isHeadquartersRoleFF && input.includes(roleTypes.HQ)) {
+ if (input.includes(roleTypes.HQ)) {
+ index = input.indexOf(roleTypes.HQ);
+ if (index !== -1) {
+ input.splice(index, 1);
+ }
+ }
+ } else if (isHeadquartersRoleFF && privilegesSelected.includes(elevatedPrivilegeTypes.SAFETY)) {
+ if (input.includes(roleTypes.HQ)) {
+ index = input.indexOf(roleTypes.HQ);
if (index !== -1) {
input.splice(index, 1);
}
@@ -62,17 +92,26 @@ const RolesPrivilegesCheckboxInput = (props) => {
};
const parsePrivilegesCheckboxInput = (input) => {
- if (rolesSelected.includes('customer') || rolesSelected.includes('contracting_officer')) {
+ if (rolesSelected.includes(roleTypes.CUSTOMER) || rolesSelected.includes(roleTypes.CONTRACTING_OFFICER)) {
var index;
- if (input.includes('supervisor')) {
- index = input.indexOf('supervisor');
+ if (input.includes(elevatedPrivilegeTypes.SUPERVISOR)) {
+ index = input.indexOf(elevatedPrivilegeTypes.SUPERVISOR);
if (index !== -1) {
input.splice(index, 1);
}
}
- if (input.includes('safety')) {
- index = input.indexOf('safety');
+ if (input.includes(elevatedPrivilegeTypes.SAFETY)) {
+ index = input.indexOf(elevatedPrivilegeTypes.SAFETY);
+ if (index !== -1) {
+ input.splice(index, 1);
+ }
+ }
+ }
+
+ if (isHeadquartersRoleFF && rolesSelected.includes(roleTypes.HQ)) {
+ if (input.includes(elevatedPrivilegeTypes.SAFETY)) {
+ index = input.indexOf(elevatedPrivilegeTypes.SAFETY);
if (index !== -1) {
input.splice(index, 1);
}