From 66996a23a1f23b0c76e3c6fc8f59002648788e00 Mon Sep 17 00:00:00 2001
From: Daniel Jordan
Date: Tue, 20 Aug 2024 17:16:11 +0000
Subject: [PATCH 1/6] initial commit, need to implement and check for the
feature flag
---
migrations/app/migrations_manifest.txt | 1 +
.../schema/20240820151043_add_gsr_role.up.sql | 2 +
pkg/factory/role_factory.go | 11 ++
pkg/factory/role_factory_test.go | 13 +++
pkg/handlers/authentication/devlocal.go | 109 ++++++++++++++++--
pkg/handlers/authentication/permissions.go | 16 ++-
pkg/models/roles/roles.go | 2 +
.../OfficeAccountRequestFields.jsx | 6 +
src/constants/routes.js | 2 +-
src/constants/userRoles.js | 3 +
.../Office/RequestAccount/RequestAccount.jsx | 6 +
src/pages/Office/index.jsx | 13 ++-
src/pages/Office/index.test.jsx | 4 +-
.../SelectApplication/SelectApplication.jsx | 1 +
src/utils/validation.js | 8 +-
15 files changed, 176 insertions(+), 21 deletions(-)
create mode 100644 migrations/app/schema/20240820151043_add_gsr_role.up.sql
diff --git a/migrations/app/migrations_manifest.txt b/migrations/app/migrations_manifest.txt
index 934a7ae1a8e..ab0cc2e13f5 100644
--- a/migrations/app/migrations_manifest.txt
+++ b/migrations/app/migrations_manifest.txt
@@ -992,3 +992,4 @@
20240816200315_update_pws_violations_pt2.up.sql
20240819164156_update_pws_violations_pt3.up.sql
20240820125856_allow_pptas_migration.up.sql
+20240820151043_add_gsr_role.up.sql
diff --git a/migrations/app/schema/20240820151043_add_gsr_role.up.sql b/migrations/app/schema/20240820151043_add_gsr_role.up.sql
new file mode 100644
index 00000000000..3dcc9587ad2
--- /dev/null
+++ b/migrations/app/schema/20240820151043_add_gsr_role.up.sql
@@ -0,0 +1,2 @@
+INSERT INTO roles(id, role_type, role_name, created_at, updated_at)
+VALUES ('20d7deea-4010-424e-9f64-714a46e18c3c', 'gsr', 'Government Surveillance Representative', now(), now());
\ No newline at end of file
diff --git a/pkg/factory/role_factory.go b/pkg/factory/role_factory.go
index 9c779bbac31..81214f5ce82 100644
--- a/pkg/factory/role_factory.go
+++ b/pkg/factory/role_factory.go
@@ -152,6 +152,17 @@ func GetTraitHQRole() []Customization {
}
}
+func GetTraitGSRRole() []Customization {
+ return []Customization{
+ {
+ Model: roles.Role{
+ RoleType: roles.RoleTypeGSR,
+ RoleName: "Government Surveillance Representative",
+ },
+ },
+ }
+}
+
// lookup a role by role type, if it doesn't exist make it
func FetchOrBuildRoleByRoleType(db *pop.Connection, roleType roles.RoleType) roles.Role {
roleName := roles.RoleName(cases.Title(language.Und).String(string(roleType)))
diff --git a/pkg/factory/role_factory_test.go b/pkg/factory/role_factory_test.go
index c78f6011dcd..72bee0e5d10 100644
--- a/pkg/factory/role_factory_test.go
+++ b/pkg/factory/role_factory_test.go
@@ -158,6 +158,19 @@ func (suite *FactorySuite) TestBuildRoleTraits() {
suite.Equal(roles.RoleName("Contracting Officer"), role.RoleName)
suite.Equal(roles.RoleTypeContractingOfficer, role.RoleType)
})
+
+ suite.Run("Successful creation of role with GSR trait", func() {
+ // Under test: BuildRole
+ // Set up: Create a Role with a trait (GetTraitGSRRole)
+ // Expected outcome:Role should be created with GSR RoleType and RoleName
+
+ role := BuildRole(suite.DB(), nil,
+ []Trait{
+ GetTraitGSRRole,
+ })
+ suite.Equal(roles.RoleName("Government Surveillance Representative"), role.RoleName)
+ suite.Equal(roles.RoleTypeGSR, role.RoleType)
+ })
}
func (suite *FactorySuite) TestBuildRoleHelpers() {
diff --git a/pkg/handlers/authentication/devlocal.go b/pkg/handlers/authentication/devlocal.go
index bb0eff05090..694991f8854 100644
--- a/pkg/handlers/authentication/devlocal.go
+++ b/pkg/handlers/authentication/devlocal.go
@@ -41,6 +41,8 @@ const (
AdminUserType string = "admin"
// HQOfficeUserType is a type of user for a HQ user
HQOfficeUserType string = "HQ office"
+ // GSROfficeUserType is a type of user for a GSR user
+ GSROfficeUserType string = "GSR office"
)
// UserListHandler handles redirection
@@ -115,6 +117,7 @@ func (h UserListHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
CsrfToken string
QueryLimit int
HQOfficeUserType string
+ GSROfficeUserType string
}
templateData := TemplateData{
@@ -134,6 +137,7 @@ func (h UserListHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
IsAdminApp: auth.AdminApp == appCtx.Session().ApplicationName,
AdminUserType: AdminUserType,
HQOfficeUserType: HQOfficeUserType,
+ GSROfficeUserType: GSROfficeUserType,
// Build CSRF token instead of grabbing from middleware. Otherwise throws errors when accessed directly.
CsrfToken: csrf.Token(r),
QueryLimit: limit,
@@ -269,23 +273,30 @@ func (h UserListHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-
+
+
+
{{end}}
@@ -994,6 +1005,78 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) (
if verrs.HasAny() {
appCtx.Logger().Error("validation errors creating office user", zap.Stringer("errors", verrs))
}
+ case GSROfficeUserType:
+ address := models.Address{
+ StreetAddress1: "1333 Minna St",
+ City: "San Francisco",
+ State: "CA",
+ PostalCode: "94115",
+ County: "SAINT CLAIR",
+ }
+
+ verrs, err := appCtx.DB().ValidateAndSave(&address)
+ if err != nil {
+ appCtx.Logger().Error("could not create address", zap.Error(err))
+ }
+ if verrs.HasAny() {
+ appCtx.Logger().Error("validation errors creating address", zap.Stringer("errors", verrs))
+ }
+
+ role := roles.Role{}
+ err = appCtx.DB().Where("role_type = $1", roles.RoleTypeGSR).First(&role)
+ if err != nil {
+ appCtx.Logger().Error("could not fetch role governemnt service representative", zap.Error(err))
+ }
+
+ usersRole := models.UsersRoles{
+ UserID: user.ID,
+ RoleID: role.ID,
+ }
+
+ verrs, err = appCtx.DB().ValidateAndSave(&usersRole)
+ if err != nil {
+ appCtx.Logger().Error("could not create user role", zap.Error(err))
+ }
+ if verrs.HasAny() {
+ appCtx.Logger().Error("validation errors creating user role", zap.Stringer("errors", verrs))
+ }
+
+ office := models.TransportationOffice{
+ Name: "JPPSO Testy McTest",
+ AddressID: address.ID,
+ Latitude: 37.7678355,
+ Longitude: -122.4199298,
+ Hours: models.StringPointer("0900-1800 Mon-Sat"),
+ Gbloc: gbloc,
+ }
+
+ verrs, err = appCtx.DB().ValidateAndSave(&office)
+ if err != nil {
+ appCtx.Logger().Error("could not create office", zap.Error(err))
+ }
+ if verrs.HasAny() {
+ appCtx.Logger().Error("validation errors creating office", zap.Stringer("errors", verrs))
+ }
+
+ officeUser := models.OfficeUser{
+ FirstName: firstName,
+ LastName: lastName,
+ Telephone: telephone,
+ TransportationOfficeID: office.ID,
+ Email: email,
+ Active: true,
+ }
+ if user.ID != uuid.Nil {
+ officeUser.UserID = &user.ID
+ }
+
+ verrs, err = appCtx.DB().ValidateAndSave(&officeUser)
+ if err != nil {
+ appCtx.Logger().Error("could not create GSR office user", zap.Error(err))
+ }
+ if verrs.HasAny() {
+ appCtx.Logger().Error("validation errors creating GSR office user", zap.Stringer("errors", verrs))
+ }
case MultiRoleOfficeUserType:
// Now create the Truss JPPSO
address := models.Address{
@@ -1016,6 +1099,10 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) (
roles.RoleTypeTIO,
roles.RoleTypeServicesCounselor,
roles.RoleTypePrimeSimulator,
+ roles.RoleTypeQae,
+ roles.RoleTypeCustomerServiceRepresentative,
+ roles.RoleTypeHQ,
+ roles.RoleTypeGSR,
}
var userRoles roles.Roles
err = appCtx.DB().Where("role_type IN (?)", officeUserRoleTypes).All(&userRoles)
@@ -1125,7 +1212,7 @@ func createSession(h devlocalAuthHandler, user *models.User, userType string, _
// Keep the logic for redirection separate from setting the session user ids
switch userType {
- case TOOOfficeUserType, TIOOfficeUserType, ServicesCounselorOfficeUserType, PrimeSimulatorOfficeUserType, QaeOfficeUserType, CustomerServiceRepresentativeOfficeUserType, MultiRoleOfficeUserType, HQOfficeUserType:
+ case TOOOfficeUserType, TIOOfficeUserType, ServicesCounselorOfficeUserType, PrimeSimulatorOfficeUserType, QaeOfficeUserType, CustomerServiceRepresentativeOfficeUserType, MultiRoleOfficeUserType, HQOfficeUserType, GSROfficeUserType:
session.ApplicationName = auth.OfficeApp
session.Hostname = h.AppNames().OfficeServername
active = userIdentity.Active || (userIdentity.OfficeActive != nil && *userIdentity.OfficeActive)
@@ -1214,7 +1301,7 @@ 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 {
+ userType == QaeOfficeUserType || userType == CustomerServiceRepresentativeOfficeUserType || userType == HQOfficeUserType || userType == GSROfficeUserType {
return true
}
return false
diff --git a/pkg/handlers/authentication/permissions.go b/pkg/handlers/authentication/permissions.go
index 53d6a429ace..75efbb75cd0 100644
--- a/pkg/handlers/authentication/permissions.go
+++ b/pkg/handlers/authentication/permissions.go
@@ -9,7 +9,6 @@ import (
"github.com/transcom/mymove/pkg/models/roles"
)
-// TODO: placeholder until we figure out where these should be stored
type RolePermissions struct {
RoleType roles.RoleType
Permissions []string
@@ -112,7 +111,20 @@ var CustomerServiceRepresentative = RolePermissions{
},
}
-var AllRolesPermissions = []RolePermissions{TOO, TIO, ServicesCounselor, QAE, CustomerServiceRepresentative, HQ}
+var GSR = RolePermissions{
+ RoleType: roles.RoleTypeGSR,
+ Permissions: []string{
+ "create.reportViolation",
+ "create.evaluationReport",
+ "read.paymentRequest",
+ "update.evaluationReport",
+ "delete.evaluationReport",
+ "view.closeoutOffice",
+ "read.shipmentsPaymentSITBalance",
+ },
+}
+
+var AllRolesPermissions = []RolePermissions{TOO, TIO, ServicesCounselor, QAE, CustomerServiceRepresentative, HQ, GSR}
// 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/pkg/models/roles/roles.go b/pkg/models/roles/roles.go
index b28fd909768..10fedc99b6e 100644
--- a/pkg/models/roles/roles.go
+++ b/pkg/models/roles/roles.go
@@ -36,6 +36,8 @@ const (
RoleTypePrime RoleType = "prime"
// RoleTypeHQ is the Headquarters Role
RoleTypeHQ RoleType = "headquarters"
+ // RoleTypeGSR is the Government Surveillance Representative Role
+ RoleTypeGSR RoleType = "gsr"
)
// Role represents a Role for users
diff --git a/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx b/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx
index a992197e4bb..dc3d1df10ce 100644
--- a/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx
+++ b/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx
@@ -96,6 +96,12 @@ export const OfficeAccountRequestFields = ({ render }) => {
name="customerSupportRepresentativeCheckBox"
label="Customer Support Representative"
/>
+
>,
)}
diff --git a/src/constants/routes.js b/src/constants/routes.js
index 03236986fa6..f026fee8296 100644
--- a/src/constants/routes.js
+++ b/src/constants/routes.js
@@ -131,7 +131,7 @@ export const tooRoutes = {
CUSTOMER_INFO_EDIT_PATH: 'customer',
};
-// QAE and CSR share all routes, just different permission levels
+// QAE, CSR, and GSR share all routes, just different permission levels
export const qaeCSRRoutes = {
MOVE_SEARCH_PATH: '/qaecsr/search',
BASE_EVALUATION_REPORTS_PATH: `${BASE_MOVES_PATH}/evaluation-reports`,
diff --git a/src/constants/userRoles.js b/src/constants/userRoles.js
index 6d866e6eae2..45739f19da0 100644
--- a/src/constants/userRoles.js
+++ b/src/constants/userRoles.js
@@ -8,6 +8,7 @@ export const roleTypes = {
PRIME_SIMULATOR: 'prime_simulator',
QAE: 'qae',
CUSTOMER_SERVICE_REPRESENTATIVE: 'customer_service_representative',
+ GSR: 'gsr',
HQ: 'headquarters',
};
@@ -20,6 +21,7 @@ export const adminOfficeRoles = [
{ roleType: 'prime_simulator', name: 'Prime Simulator' },
{ roleType: 'qae', name: 'Quality Assurance Evaluator' },
{ roleType: 'customer_service_representative', name: 'Customer Service Representative' },
+ { roleType: 'gsr', name: 'Government Surveillance Representative' },
{ roleType: 'headquarters', name: 'Headquarters' },
];
@@ -31,4 +33,5 @@ export const officeRoles = [
roleTypes.QAE,
roleTypes.HQ,
roleTypes.CUSTOMER_SERVICE_REPRESENTATIVE,
+ roleTypes.GSR,
];
diff --git a/src/pages/Office/RequestAccount/RequestAccount.jsx b/src/pages/Office/RequestAccount/RequestAccount.jsx
index b2ed206b36c..e1b30887fbd 100644
--- a/src/pages/Office/RequestAccount/RequestAccount.jsx
+++ b/src/pages/Office/RequestAccount/RequestAccount.jsx
@@ -68,6 +68,12 @@ export const RequestAccount = ({ setFlashMessage }) => {
roleType: 'customer_service_representative',
});
}
+ if (values.governmentSurveillanceRepresentativeCheckbox) {
+ requestedRoles.push({
+ name: 'Government Surveillance Representative',
+ roleType: 'gsr',
+ });
+ }
let body = {
email: values.officeAccountRequestEmail,
diff --git a/src/pages/Office/index.jsx b/src/pages/Office/index.jsx
index b3b4306e126..89bbff4f572 100644
--- a/src/pages/Office/index.jsx
+++ b/src/pages/Office/index.jsx
@@ -526,12 +526,14 @@ export class OfficeApp extends Component {
}
/>
- {/* QAE/CSR */}
+ {/* QAE/CSR/GSR */}
+
}
@@ -547,6 +549,7 @@ export class OfficeApp extends Component {
roleTypes.TIO,
roleTypes.QAE,
roleTypes.CUSTOMER_SERVICE_REPRESENTATIVE,
+ roleTypes.GSR,
hqRoleFlag ? roleTypes.HQ : undefined,
]}
>
@@ -570,9 +573,9 @@ export class OfficeApp extends Component {
{activeRole === roleTypes.PRIME_SIMULATOR && (
} />
)}
- {(activeRole === roleTypes.QAE || activeRole === roleTypes.CUSTOMER_SERVICE_REPRESENTATIVE) && (
- } />
- )}
+ {(activeRole === roleTypes.QAE ||
+ activeRole === roleTypes.CUSTOMER_SERVICE_REPRESENTATIVE ||
+ activeRole === roleTypes.GSR) && } />}
{/* 404 */}
} />
diff --git a/src/pages/Office/index.test.jsx b/src/pages/Office/index.test.jsx
index 1fe9ddccd9f..eeda78202d1 100644
--- a/src/pages/Office/index.test.jsx
+++ b/src/pages/Office/index.test.jsx
@@ -258,13 +258,15 @@ describe('Office App', () => {
'/simulator/moves/test123/shipments/ship123/reweigh/req123/update',
roleTypes.PRIME_SIMULATOR,
],
+ ['QAE CSR Move Search', '/', roleTypes.QAE],
['QAE CSR Move Search', '/qaecsr/search', roleTypes.QAE],
+ ['QAE CSR Move Search', '/', roleTypes.GSR],
+ ['QAE CSR Move Search', '/qaecsr/search', roleTypes.GSR],
['TXO Move Info', '/moves/move123', roleTypes.TIO],
['Payment Request Queue', '/', roleTypes.TIO],
['Move Queue', '/', roleTypes.TOO],
['Headquarters Queues', '/', roleTypes.HQ],
['Services Counseling Queue', '/', roleTypes.SERVICES_COUNSELOR],
- ['QAE CSR Move Search', '/', roleTypes.QAE],
['Prime Simulator Available Moves Queue', '/', roleTypes.PRIME_SIMULATOR],
['Services Counseling Move Info', '/moves/move123/shipments/:shipmentId/advance', roleTypes.TOO],
])('renders the %s component at %s as a %s with sufficient permissions', async (component, path, role) => {
diff --git a/src/pages/SelectApplication/SelectApplication.jsx b/src/pages/SelectApplication/SelectApplication.jsx
index e1fc5d20fc4..d72f55ac5a4 100644
--- a/src/pages/SelectApplication/SelectApplication.jsx
+++ b/src/pages/SelectApplication/SelectApplication.jsx
@@ -33,6 +33,7 @@ const SelectApplication = ({ userRoles, setActiveRole, activeRole }) => {
roleTypes.PRIME_SIMULATOR,
roleTypes.QAE,
roleTypes.CUSTOMER_SERVICE_REPRESENTATIVE,
+ roleTypes.GSR,
]
.filter((r) => userRoleTypes.find((role) => r === role))
.map((r) => (
diff --git a/src/utils/validation.js b/src/utils/validation.js
index e453b81fd99..ca57253b86d 100644
--- a/src/utils/validation.js
+++ b/src/utils/validation.js
@@ -187,7 +187,8 @@ const validateRoleRequestedMethod = (value, testContext) => {
testContext.parent.transportationContractingOfficerCheckBox ||
testContext.parent.qualityAssuranceEvaluatorCheckBox ||
testContext.parent.headquartersCheckBox ||
- testContext.parent.customerSupportRepresentativeCheckBox
+ testContext.parent.customerSupportRepresentativeCheckBox ||
+ testContext.parent.governmentSurveillanceRepresentativeCheckbox
);
};
@@ -276,4 +277,9 @@ export const officeAccountRequestSchema = Yup.object().shape({
'You must select at least one role.',
validateRoleRequestedMethod,
),
+ governmentSurveillanceRepresentativeCheckbox: Yup.bool().test(
+ 'roleRequestedRequired',
+ 'You must select at least one role.',
+ validateRoleRequestedMethod,
+ ),
});
From ab2c4ff77ee088f8987b5f8c040e131488e535af Mon Sep 17 00:00:00 2001
From: Daniel Jordan
Date: Wed, 21 Aug 2024 08:22:33 -0500
Subject: [PATCH 2/6] adding feature flag mumbo jumbo
---
.circleci/config.yml | 2 ++
.envrc | 3 +++
config/flipt/storage/development.features.yaml | 8 ++++++++
3 files changed, 13 insertions(+)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index c38a70cd377..775872e9ec1 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -872,6 +872,7 @@ commands:
export FEATURE_FLAG_MOVE_LOCK=false
export FEATURE_FLAG_OKTA_DODID_INPUT=false
export FEATURE_FLAG_HEADQUARTERS_ROLE=false
+ export FEATURE_FLAG_GSR_ROLE=false
export FEATURE_FLAG_SAFETY_MOVE=false
export FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
export FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
@@ -911,6 +912,7 @@ commands:
FEATURE_FLAG_MOVE_LOCK: 'false'
FEATURE_FLAG_OKTA_DODID_INPUT: 'false'
FEATURE_FLAG_HEADQUARTERS_ROLE: 'false'
+ FEATURE_FLAG_GSR_ROLE: 'false'
FEATURE_FLAG_SAFETY_MOVE: 'false'
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS: 'false'
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE: 'false'
diff --git a/.envrc b/.envrc
index 8dea08a9025..7af3d7b0aa2 100644
--- a/.envrc
+++ b/.envrc
@@ -142,6 +142,9 @@ export FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
# Feature flag to disable/enable headquarters role
export FEATURE_FLAG_HEADQUARTERS_ROLE=true
+# Feature flag to disable/enable GSR role
+export FEATURE_FLAG_GSR_ROLE=true
+
# Feature flag to disable/enable supervisor queue management
export FEATURE_FLAG_QUEUE_MANAGEMENT=true
diff --git a/config/flipt/storage/development.features.yaml b/config/flipt/storage/development.features.yaml
index b369ff283ff..acad46ec229 100644
--- a/config/flipt/storage/development.features.yaml
+++ b/config/flipt/storage/development.features.yaml
@@ -9,6 +9,14 @@ flags:
- segment:
key: mil-app
value: true
+- key: gsr_role
+ name: Government Surveillance Representative Role feature flag
+ type: BOOLEAN_FLAG_TYPE
+ enabled: false
+ rollouts:
+ - segment:
+ key: mil-app
+ value: false
- key: safety_move
name: Safety Move feature flag
type: BOOLEAN_FLAG_TYPE
From 35164b2e3ded1b24bcf4c149192c827013c194be Mon Sep 17 00:00:00 2001
From: Daniel Jordan
Date: Wed, 21 Aug 2024 15:15:15 +0000
Subject: [PATCH 3/6] updating feature flag configs, some enhancements, and
commenting out checkboxes to be implemented later
---
.envrc | 2 +-
config/env/demo.app-client-tls.env | 1 +
config/env/demo.app.env | 1 +
config/env/exp.app-client-tls.env | 1 +
config/env/exp.app.env | 1 +
config/env/loadtest.app-client-tls.env | 1 +
config/env/loadtest.app.env | 1 +
config/env/prd.app-client-tls.env | 1 +
config/env/prd.app.env | 1 +
config/env/stg.app-client-tls.env | 1 +
config/env/stg.app.env | 1 +
pkg/handlers/adminapi/requested_office_users.go | 3 ++-
.../OfficeAccountRequestFields.jsx | 3 ++-
.../Office/RequestAccount/RequestAccount.jsx | 17 ++++++++++-------
.../RequestAccount/RequestAccount.module.scss | 3 +++
src/pages/Office/index.jsx | 14 ++++++++++++--
16 files changed, 40 insertions(+), 12 deletions(-)
create mode 100644 src/pages/Office/RequestAccount/RequestAccount.module.scss
diff --git a/.envrc b/.envrc
index 7af3d7b0aa2..691b82cf1f4 100644
--- a/.envrc
+++ b/.envrc
@@ -143,7 +143,7 @@ export FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
export FEATURE_FLAG_HEADQUARTERS_ROLE=true
# Feature flag to disable/enable GSR role
-export FEATURE_FLAG_GSR_ROLE=true
+export FEATURE_FLAG_GSR_ROLE=false
# Feature flag to disable/enable supervisor queue management
export FEATURE_FLAG_QUEUE_MANAGEMENT=true
diff --git a/config/env/demo.app-client-tls.env b/config/env/demo.app-client-tls.env
index fc713fc4d4e..cd9dade4cce 100644
--- a/config/env/demo.app-client-tls.env
+++ b/config/env/demo.app-client-tls.env
@@ -41,6 +41,7 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
FEATURE_FLAG_HEADQUARTERS_ROLE=false
+FEATURE_FLAG_GSR_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
diff --git a/config/env/demo.app.env b/config/env/demo.app.env
index a272da9ba3c..da30cd2c224 100644
--- a/config/env/demo.app.env
+++ b/config/env/demo.app.env
@@ -46,6 +46,7 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
FEATURE_FLAG_HEADQUARTERS_ROLE=false
+FEATURE_FLAG_GSR_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
diff --git a/config/env/exp.app-client-tls.env b/config/env/exp.app-client-tls.env
index 119d14c2254..5e8cd63f334 100644
--- a/config/env/exp.app-client-tls.env
+++ b/config/env/exp.app-client-tls.env
@@ -41,6 +41,7 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
FEATURE_FLAG_HEADQUARTERS_ROLE=false
+FEATURE_FLAG_GSR_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
diff --git a/config/env/exp.app.env b/config/env/exp.app.env
index 2a8aa16d201..c018a27ea1d 100644
--- a/config/env/exp.app.env
+++ b/config/env/exp.app.env
@@ -46,6 +46,7 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
FEATURE_FLAG_HEADQUARTERS_ROLE=false
+FEATURE_FLAG_GSR_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
diff --git a/config/env/loadtest.app-client-tls.env b/config/env/loadtest.app-client-tls.env
index 77fb56ca87a..42425ba8802 100644
--- a/config/env/loadtest.app-client-tls.env
+++ b/config/env/loadtest.app-client-tls.env
@@ -39,6 +39,7 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
FEATURE_FLAG_HEADQUARTERS_ROLE=false
+FEATURE_FLAG_GSR_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
diff --git a/config/env/loadtest.app.env b/config/env/loadtest.app.env
index 64f7852aa4a..ea7f9a07aa0 100644
--- a/config/env/loadtest.app.env
+++ b/config/env/loadtest.app.env
@@ -44,6 +44,7 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
FEATURE_FLAG_HEADQUARTERS_ROLE=false
+FEATURE_FLAG_GSR_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
diff --git a/config/env/prd.app-client-tls.env b/config/env/prd.app-client-tls.env
index 670a2419c8d..96da4556ed8 100644
--- a/config/env/prd.app-client-tls.env
+++ b/config/env/prd.app-client-tls.env
@@ -38,6 +38,7 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
FEATURE_FLAG_HEADQUARTERS_ROLE=false
+FEATURE_FLAG_GSR_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
diff --git a/config/env/prd.app.env b/config/env/prd.app.env
index ba68f417a91..4e43c126f45 100644
--- a/config/env/prd.app.env
+++ b/config/env/prd.app.env
@@ -45,6 +45,7 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
FEATURE_FLAG_HEADQUARTERS_ROLE=false
+FEATURE_FLAG_GSR_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
diff --git a/config/env/stg.app-client-tls.env b/config/env/stg.app-client-tls.env
index 9b2210e1323..412d4eeb448 100644
--- a/config/env/stg.app-client-tls.env
+++ b/config/env/stg.app-client-tls.env
@@ -40,6 +40,7 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
FEATURE_FLAG_HEADQUARTERS_ROLE=false
+FEATURE_FLAG_GSR_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
diff --git a/config/env/stg.app.env b/config/env/stg.app.env
index 40822fdb851..5b9f07d738a 100644
--- a/config/env/stg.app.env
+++ b/config/env/stg.app.env
@@ -46,6 +46,7 @@ FEATURE_FLAG_VALIDATION_CODE_REQUIRED=false
FEATURE_FLAG_MOVE_LOCK=false
FEATURE_FLAG_OKTA_DODID_INPUT=false
FEATURE_FLAG_HEADQUARTERS_ROLE=false
+FEATURE_FLAG_GSR_ROLE=false
FEATURE_FLAG_SAFETY_MOVE=false
FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false
FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false
diff --git a/pkg/handlers/adminapi/requested_office_users.go b/pkg/handlers/adminapi/requested_office_users.go
index b5c93836bb6..29a9fb0f446 100644
--- a/pkg/handlers/adminapi/requested_office_users.go
+++ b/pkg/handlers/adminapi/requested_office_users.go
@@ -277,7 +277,8 @@ func (h UpdateRequestedOfficeUserHandler) Handle(params requested_office_users.U
// Only attempt to create an Okta account IF params.Body.Status is APPROVED
// Track if Okta account was successfully created or not
- if params.Body.Status == "APPROVED" {
+ // we will skip this check if using the local dev environment
+ if params.Body.Status == "APPROVED" && appCtx.Session().IDToken != "devlocal" {
oktaAccountCreationResponse, createAccountError := CreateOfficeOktaAccount(appCtx, params)
if createAccountError != nil || oktaAccountCreationResponse.StatusCode != http.StatusOK {
// If there is an error creating the account or there is a respopnse code other than 200 then the account was not succssfully created
diff --git a/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx b/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx
index dc3d1df10ce..85f3491b2f8 100644
--- a/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx
+++ b/src/components/form/OfficeAccountRequestFields/OfficeAccountRequestFields.jsx
@@ -96,12 +96,13 @@ export const OfficeAccountRequestFields = ({ render }) => {
name="customerSupportRepresentativeCheckBox"
label="Customer Support Representative"
/>
+ {/* this will be uncommented in B-20809
+ /> */}
>,
)}
diff --git a/src/pages/Office/RequestAccount/RequestAccount.jsx b/src/pages/Office/RequestAccount/RequestAccount.jsx
index e1b30887fbd..95dfc992e11 100644
--- a/src/pages/Office/RequestAccount/RequestAccount.jsx
+++ b/src/pages/Office/RequestAccount/RequestAccount.jsx
@@ -4,6 +4,8 @@ import { func } from 'prop-types';
import { useNavigate } from 'react-router-dom';
import { Grid, GridContainer, Alert } from '@trussworks/react-uswds';
+import styles from './RequestAccount.module.scss';
+
import { setFlashMessage as setFlashMessageAction } from 'store/flash/actions';
import RequestAccountForm from 'components/Office/RequestAccountForm/RequestAccountForm';
import { createOfficeAccountRequest } from 'services/ghcApi';
@@ -68,12 +70,13 @@ export const RequestAccount = ({ setFlashMessage }) => {
roleType: 'customer_service_representative',
});
}
- if (values.governmentSurveillanceRepresentativeCheckbox) {
- requestedRoles.push({
- name: 'Government Surveillance Representative',
- roleType: 'gsr',
- });
- }
+ // this will be uncommented in B-20809
+ // if (values.governmentSurveillanceRepresentativeCheckbox) {
+ // requestedRoles.push({
+ // name: 'Government Surveillance Representative',
+ // roleType: 'gsr',
+ // });
+ // }
let body = {
email: values.officeAccountRequestEmail,
@@ -150,7 +153,7 @@ export const RequestAccount = ({ setFlashMessage }) => {
)}
-
+
diff --git a/src/pages/Office/RequestAccount/RequestAccount.module.scss b/src/pages/Office/RequestAccount/RequestAccount.module.scss
new file mode 100644
index 00000000000..84ccaa741ac
--- /dev/null
+++ b/src/pages/Office/RequestAccount/RequestAccount.module.scss
@@ -0,0 +1,3 @@
+.formContainer {
+ width: 40vw;
+}
\ No newline at end of file
diff --git a/src/pages/Office/index.jsx b/src/pages/Office/index.jsx
index 89bbff4f572..c0b1b094070 100644
--- a/src/pages/Office/index.jsx
+++ b/src/pages/Office/index.jsx
@@ -111,6 +111,7 @@ export class OfficeApp extends Component {
oktaLoggedOut: undefined,
oktaNeedsLoggedOut: undefined,
hqRoleFlag: !!props.hqRoleFlag,
+ gsrRoleFlag: undefined,
};
}
@@ -147,6 +148,10 @@ export class OfficeApp extends Component {
this.setState({
hqRoleFlag: hqRoleFlagValue,
});
+ const gsrRoleFlagValue = await isBooleanFlagEnabled('gsr_role');
+ this.setState({
+ gsrRoleFlag: gsrRoleFlagValue,
+ });
} catch (error) {
retryPageLoading(error);
}
@@ -166,7 +171,7 @@ export class OfficeApp extends Component {
}
render() {
- const { hasError, error, info, oktaLoggedOut, oktaNeedsLoggedOut, hqRoleFlag } = this.state;
+ const { hasError, error, info, oktaLoggedOut, oktaNeedsLoggedOut, hqRoleFlag, gsrRoleFlag } = this.state;
const {
activeRole,
officeUserId,
@@ -575,7 +580,12 @@ export class OfficeApp extends Component {
)}
{(activeRole === roleTypes.QAE ||
activeRole === roleTypes.CUSTOMER_SERVICE_REPRESENTATIVE ||
- activeRole === roleTypes.GSR) && } />}
+ (activeRole === roleTypes.GSR && gsrRoleFlag)) && (
+ } />
+ )}
+ {activeRole === roleTypes.GSR && !gsrRoleFlag && (
+ } />
+ )}
{/* 404 */}
} />
From 010ab224f25220f6017ae13ca2e564f78fd65f55 Mon Sep 17 00:00:00 2001
From: Daniel Jordan
Date: Wed, 21 Aug 2024 16:04:01 +0000
Subject: [PATCH 4/6] updated devlocal test to account for changes made
---
pkg/handlers/authentication/devlocal_test.go | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/pkg/handlers/authentication/devlocal_test.go b/pkg/handlers/authentication/devlocal_test.go
index 6106e1c7b63..82b2b44bc93 100644
--- a/pkg/handlers/authentication/devlocal_test.go
+++ b/pkg/handlers/authentication/devlocal_test.go
@@ -82,6 +82,12 @@ func (suite *AuthSuite) TestCreateUserHandlerOffice() {
factory.BuildRole(suite.DB(), nil, []factory.Trait{
factory.GetTraitCustomerServiceRepresentativeRole,
})
+ factory.BuildRole(suite.DB(), nil, []factory.Trait{
+ factory.GetTraitHQRole,
+ })
+ factory.BuildRole(suite.DB(), nil, []factory.Trait{
+ factory.GetTraitGSRRole,
+ })
factory.BuildRole(suite.DB(), nil, []factory.Trait{
factory.GetTraitPrimeSimulatorRole,
})
@@ -131,7 +137,7 @@ func (suite *AuthSuite) TestCreateUserHandlerOffice() {
{
userType: MultiRoleOfficeUserType,
roleTypes: []roles.RoleType{roles.RoleTypeTIO, roles.RoleTypeTOO,
- roles.RoleTypeServicesCounselor, roles.RoleTypePrimeSimulator},
+ roles.RoleTypeServicesCounselor, roles.RoleTypePrimeSimulator, roles.RoleTypeGSR, roles.RoleTypeHQ, roles.RoleTypeQae, roles.RoleTypeCustomerServiceRepresentative},
email: "multi_role@example.com",
},
} {
From 55d071ba35520d87e9e4b7ed9a3e65374eca5683 Mon Sep 17 00:00:00 2001
From: Daniel Jordan
Date: Wed, 21 Aug 2024 16:20:19 +0000
Subject: [PATCH 5/6] updating failing ui test
---
src/pages/Office/index.test.jsx | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/pages/Office/index.test.jsx b/src/pages/Office/index.test.jsx
index eeda78202d1..ba68be9c589 100644
--- a/src/pages/Office/index.test.jsx
+++ b/src/pages/Office/index.test.jsx
@@ -10,6 +10,12 @@ import { OfficeApp } from './index';
import { roleTypes } from 'constants/userRoles';
import { configureStore } from 'shared/store';
import { mockPage } from 'testUtils';
+import { isBooleanFlagEnabled } from 'utils/featureFlags';
+
+jest.mock('utils/featureFlags', () => ({
+ ...jest.requireActual('utils/featureFlags'),
+ isBooleanFlagEnabled: jest.fn().mockImplementation(() => Promise.resolve(false)),
+}));
// Mock the components that are routed to from the index, ordered the same as the routes in the index file
mockPage('pages/SignIn/SignIn');
@@ -83,6 +89,7 @@ const createMockStore = (role) => {
// Render the OfficeApp component with routing and Redux setup for the provided route and role
const renderOfficeAppAtRoute = (route, role) => {
+ isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(true));
const mockStore = createMockStore(role);
const userRoles = role ? [{ roleType: role }] : [];
render(
@@ -100,6 +107,7 @@ const renderOfficeAppAtRoute = (route, role) => {
loginIsLoading={!!role}
userIsLoggedIn={!!role}
hqRoleFlag
+ gsrRoleFlag
/>
,
@@ -260,8 +268,8 @@ describe('Office App', () => {
],
['QAE CSR Move Search', '/', roleTypes.QAE],
['QAE CSR Move Search', '/qaecsr/search', roleTypes.QAE],
- ['QAE CSR Move Search', '/', roleTypes.GSR],
- ['QAE CSR Move Search', '/qaecsr/search', roleTypes.GSR],
+ ['QAE CSR Move Search', '/', roleTypes.GSR, true],
+ ['QAE CSR Move Search', '/qaecsr/search', roleTypes.GSR, true],
['TXO Move Info', '/moves/move123', roleTypes.TIO],
['Payment Request Queue', '/', roleTypes.TIO],
['Move Queue', '/', roleTypes.TOO],
From 2397502713be65356516e446790762665b16cf3c Mon Sep 17 00:00:00 2001
From: Daniel Jordan <136510600+danieljordan-caci@users.noreply.github.com>
Date: Tue, 10 Sep 2024 09:09:15 -0500
Subject: [PATCH 6/6] Update RequestAccount.module.scss to solve merge conflict
oopsie
---
src/pages/Office/RequestAccount/RequestAccount.module.scss | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/pages/Office/RequestAccount/RequestAccount.module.scss b/src/pages/Office/RequestAccount/RequestAccount.module.scss
index f95b23b897f..11e528b5a71 100644
--- a/src/pages/Office/RequestAccount/RequestAccount.module.scss
+++ b/src/pages/Office/RequestAccount/RequestAccount.module.scss
@@ -1,5 +1,7 @@
.formContainer {
width: 40vw;
+}
.error {
width: 100%;
+}