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) {

-

- - - ` + gblocSelectHTML + ` - + + + ` + gblocSelectHTML + ` +

-
+

- + ` + gblocSelectHTML + ` - +

-
+ +
+

+ + + ` + gblocSelectHTML + ` + +

+
{{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%; +}