Skip to content

Commit cf5da80

Browse files
authored
[IOPLT-1003] Add support for x-user token in bearerSessionTokenStrategy (#1204)
* Update bearerSessionTokenStrategy to use x-user header Add FF_IO_X_USER_TOKEN_ENABLED feature flag Add proxy:io-auth models Remove bearerMyPortalTokenStrategy and MyPortal references * Update proxy:io-auth commit id * Fix linting Add changeset * Update app.test * Fix import for tests * Add x-user-token tests Fix linting * Update x-user feature flag Update logic for enabled users * Fix tests * Fix linting * Remove unused code * Update getUser code * Refactor bearerSessionTokenStrategy * Collapse the conditions into a single if * Update readme * Update documentation
1 parent 45c810d commit cf5da80

19 files changed

+247
-152
lines changed

.changeset/shiny-mails-reply.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pagopa/io-backend": minor
3+
---
4+
5+
Add support for x-user token in bearerSessionTokenStrategy

.env.example

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@ REDIS_PORT=put_the_azure_redis_port_here
1010
REDIS_PASSWORD=put_the_azure_redis_password_here
1111
PRE_SHARED_KEY="12345"
1212
ALLOW_NOTIFY_IP_SOURCE_RANGE="::ffff:ac13:1/112"
13-
ALLOW_MYPORTAL_IP_SOURCE_RANGE="::ffff:ac13:1/112"
1413
ALLOW_SESSION_HANDLER_IP_SOURCE_RANGE="::ffff:ac13:1/112"
1514
AUTHENTICATION_BASE_PATH=""
16-
MYPORTAL_BASE_PATH=/myportal/api/v1
1715
PAGOPA_API_URL_PROD="https://pagopa-proxy-prod"
1816
PAGOPA_API_KEY_PROD=foo
1917
PAGOPA_API_URL_TEST="https://pagopa-proxy-test"
@@ -113,6 +111,13 @@ FF_ROUTING_PUSH_NOTIF="ALL"
113111
FF_ROUTING_PUSH_NOTIF_BETA_TESTER_SHA_LIST=foo
114112
FF_ROUTING_PUSH_NOTIF_CANARY_SHA_USERS_REGEX="XYZ"
115113

114+
# ------------------------------------
115+
# IO_X_USER_TOKEN
116+
# ------------------------------------
117+
FF_IO_X_USER_TOKEN=ALL
118+
FF_IO_X_USER_TOKEN_BETA_TESTER_SHA_LIST=foo
119+
FF_IO_X_USER_TOKEN_CANARY_SHA_USERS_REGEX="XYZ"
120+
116121
# ------------------------------------
117122
# LOLLIPOP
118123
# ------------------------------------

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,12 @@ Those are all Environment variables needed by the application:
114114
| ALLOW_NOTIFY_IP_SOURCE_RANGE | The range in CIDR form of allowed IPs for the webhook notifications | string |
115115
| NOTIFICATIONS_STORAGE_CONNECTION_STRING | Connection string to Azure queue storage for notification hub messages | string |
116116
| NOTIFICATIONS_QUEUE_NAME | Queue name of Azure queue storage for notification hub messages | string |
117-
| ALLOW_MYPORTAL_IP_SOURCE_RANGE | The range in CIDR form of allowed IPs for the MyPortal API | string |
118117
| ALLOW_SESSION_HANDLER_IP_SOURCE_RANGE | The range in CIDR form of IPs of service allowed to handle user sessions | string |
119118
| AUTHENTICATION_BASE_PATH | The root path for the authentication endpoints | string |
120119
| PAGOPA_API_URL_PROD | The url for the PagoPA api endpoints in prod mode | string |
121120
| PAGOPA_API_KEY_PROD | The api-key needed to call the pagopa proxy API | string |
122121
| PAGOPA_API_URL_TEST | The url for the PagoPA api endpoints in test mode | string |
123122
| PAGOPA_API_KEY_UAT | The api-key needed to call the pagopa proxy API for UAT instance | string |
124-
| MYPORTAL_BASE_PATH | The root path for the MyPortal endpoints | string |
125123
| CACHE_MAX_AGE_SECONDS | The value in seconds for duration of in-memory api cache | int |
126124
| APICACHE_DEBUG | When is `true` enable the apicache debug mode | boolean |
127125
| GITHUB_TOKEN | The value of your Github Api Key, used in build phase | string |
@@ -164,6 +162,9 @@ Those are all Environment variables needed by the application:
164162
| TRIAL_SYSTEM_API_BASE_PATH | Trial System Api Base path | string |
165163
| TRIAL_SYSTEM_API_URL | Trial System FunctionApp Api url | string |
166164
| TRIAL_SYSTEM_API_KEY | The key used to authenticate to the Trial System API | string |
165+
| FF_IO_X_USER_TOKEN | Enables/disables the use of the x-user header | string (enum: NONE, BETA, ALL) |
166+
| FF_IO_X_USER_TOKEN_BETA_TESTER_SHA_LIST | List of fiscal codes enabled for the feature | csv |
167+
| FF_IO_X_USER_TOKEN_CANARY_SHA_USERS_REGEX | Regex used to identify canary users enabled for the feature | regex |
167168
168169
Notes:
169170
* `FETCH_KEEPALIVE_ENABLED` should be enabled when deploying on Azure App Service to avoid [SNAT Exhaustion](https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-outbound-connections)

helm/values-prod01.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,14 @@ microservice-chart:
7474
FF_PN_ACTIVATION_ENABLED: '1'
7575
FF_ROUTING_PUSH_NOTIF: 'ALL'
7676
FF_ROUTING_PUSH_NOTIF_CANARY_SHA_USERS_REGEX: '^([(0-9)|(a-f)|(A-F)]{63}[(0-4)]{1})$'
77+
FF_IO_X_USER_TOKEN: 'ALL'
78+
FF_IO_X_USER_TOKEN_CANARY_SHA_USERS_REGEX: '^([(0-9)|(a-f)|(A-F)]{63}[(0-4)]{1})$'
7779
IO_SIGN_API_BASE_PATH: '/api/v1/sign'
7880
IO_SIGN_API_URL: 'https://io-p-sign-user-func.azurewebsites.net'
7981
IO_SIGN_SERVICE_ID: '01GQQZ9HF5GAPRVKJM1VDAVFHM'
8082
IS_APPBACKENDLI: 'true'
8183
JWT_SUPPORT_TOKEN_EXPIRATION: '1209600'
8284
JWT_SUPPORT_TOKEN_ISSUER: 'app-backend.io.italia.it'
83-
MYPORTAL_BASE_PATH: '/myportal/api/v1'
8485
NODE_ENV: 'production'
8586
NOTIFICATIONS_QUEUE_NAME: 'push-notifications'
8687
PAGOPA_API_URL_PROD: 'https://api.platform.pagopa.it/checkout/auth/payments/v1'
@@ -122,9 +123,9 @@ microservice-chart:
122123
PRE_SHARED_KEY: 'appbackend-PRE-SHARED-KEY'
123124
PAGOPA_API_KEY_PROD: 'appbackend-PAGOPA-API-KEY-PROD-PRIMARY'
124125
PAGOPA_API_KEY_UAT: 'appbackend-PAGOPA-API-KEY-UAT-PRIMARY'
125-
ALLOW_MYPORTAL_IP_SOURCE_RANGE: 'appbackend-ALLOW-MYPORTAL-IP-SOURCE-RANGE'
126126
JWT_SUPPORT_TOKEN_PRIVATE_RSA_KEY: 'appbackend-JWT-SUPPORT-TOKEN-PRIVATE-RSA-KEY'
127127
FF_ROUTING_PUSH_NOTIF_BETA_TESTER_SHA_LIST: 'appbackend-APP-MESSAGES-BETA-FISCAL-CODES'
128+
FF_IO_X_USER_TOKEN_BETA_TESTER_SHA_LIST: 'appbackend-X-USER-TOKEN-BETA-FISCAL-CODES'
128129
PECSERVER_TOKEN_SECRET: 'appbackend-PECSERVER-TOKEN-SECRET'
129130
PECSERVERS_poste_secret: 'appbackend-PECSERVER-TOKEN-SECRET'
130131
PECSERVERS_aruba_secret: 'appbackend-PECSERVER-ARUBA-TOKEN-SECRET'

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"generate:proxy:io-sign-models": "rimraf generated/io-sign && gen-api-models --api-spec api_io_sign.yaml --out-dir generated/io-sign",
4545
"generate:proxy:io-fims-models": "rimraf generated/io-fims && gen-api-models --api-spec api_io_fims.yaml --out-dir generated/io-fims",
4646
"generate:proxy:cgn-operator-search-models": "rimraf generated/cgn-operator-search && gen-api-models --api-spec api_cgn_operator_search.yaml --out-dir generated/cgn-operator-search",
47+
"generate:proxy:io-auth": "rimraf generated/io-auth && gen-api-models --api-spec https://raw.githubusercontent.com/pagopa/io-auth-n-identity-domain/4d9ee9a6a141943ce7d167698b204456a2874d28/apps/io-session-manager/api/token_introspection.yaml --no-strict --out-dir generated/io-auth --request-types",
4748
"generate:api:io-bonus": "rimraf generated/io-bonus-api && gen-api-models --api-spec openapi/consumed/fn_bonus.yaml --no-strict --out-dir generated/io-bonus-api --request-types --response-decoders --client",
4849
"generate:api:io-sign": "rimraf generated/io-sign-api && gen-api-models --api-spec https://raw.githubusercontent.com/pagopa/io-sign/0a9124b7c782b2569dd82c094496e50a17b418f4/apps/io-func-sign-user/openapi.yaml --no-strict --out-dir generated/io-sign-api --request-types --response-decoders --client",
4950
"generate:api:io-fims": "rimraf generated/io-fims-api && gen-api-models --api-spec https://raw.githubusercontent.com/pagopa/io-fims/44c478f9b9ca024aa4db963873a85f8d9c37f5d3/apps/user-func/openapi.yaml --no-strict --out-dir generated/io-fims-api --request-types --response-decoders --client",

src/__mocks__/user_mock.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
ZendeskToken,
2020
} from "../types/token";
2121
import { User } from "../types/user";
22+
import { UserIdentity } from "../../generated/io-auth/UserIdentity";
2223

2324
export const aTimestamp = 1518010929530;
2425
export const aFiscalCode = "GRBGPP87L04L741X" as FiscalCode;
@@ -60,6 +61,16 @@ export const mockedUser: User = {
6061
session_tracking_id: aSessionTrackingId,
6162
};
6263

64+
export const mockedUserIdentity: UserIdentity = {
65+
family_name: aValidFamilyname,
66+
fiscal_code: aFiscalCode,
67+
name: aValidName,
68+
date_of_birth: aValidDateofBirth,
69+
spid_email: aSpidEmailAddress,
70+
spid_level: aValidSpidLevel,
71+
session_tracking_id: aSessionTrackingId,
72+
};
73+
6374
export const aCustomEmailAddress = "custom-email@example.com" as EmailAddress;
6475

6576
export const anIsInboxEnabled = true as IsInboxEnabled;

src/__tests__/app.test.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ const X_FORWARDED_PROTO_HEADER = "X-Forwarded-Proto";
6161

6262
const aAPIBasePath = "/api/v1";
6363
const aBonusAPIBasePath = "/bonus/api/v1";
64-
const aMyPortalBasePath = "/myportal/api/v1";
6564
const aCgnAPIBasePath = "/api/v1/cgn";
6665
const aCgnOperatorSearchAPIBasePath = "/api/v1/cgn-operator-search";
6766
const aEuCovidCertAPIBasePath = "/api/v1/eucovidcert";
@@ -84,10 +83,8 @@ describe("Success app start", () => {
8483
IoFimsAPIBasePath: aIoFimsAPIBasePath,
8584
IoSignAPIBasePath: aIoSignAPIBasePath,
8685
IoWalletAPIBasePath: aIoWalletAPIBasePath,
87-
MyPortalBasePath: aMyPortalBasePath,
8886
ServicesAppBackendBasePath: aServicesAppBackendBasePath,
8987
TrialSystemBasePath: aTrialSystemBasePath,
90-
allowMyPortalIPSourceRange: [aValidCIDR],
9188
allowNotifyIPSourceRange: [aValidCIDR],
9289
allowSessionHandleIPSourceRange: [aValidCIDR],
9390
authenticationBasePath: "",
@@ -193,10 +190,8 @@ describe("Failure app start", () => {
193190
IoFimsAPIBasePath: aIoFimsAPIBasePath,
194191
IoSignAPIBasePath: aIoSignAPIBasePath,
195192
IoWalletAPIBasePath: aIoWalletAPIBasePath,
196-
MyPortalBasePath: aMyPortalBasePath,
197193
ServicesAppBackendBasePath: aServicesAppBackendBasePath,
198194
TrialSystemBasePath: aTrialSystemBasePath,
199-
allowMyPortalIPSourceRange: [aValidCIDR],
200195
allowNotifyIPSourceRange: [aValidCIDR],
201196
allowSessionHandleIPSourceRange: [aValidCIDR],
202197
authenticationBasePath: "",

src/app.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ import {
3434
FF_IO_FIMS_ENABLED,
3535
FF_IO_SIGN_ENABLED,
3636
FF_IO_WALLET_ENABLED,
37+
FF_IO_X_USER_TOKEN,
38+
FF_IO_X_USER_TOKEN_BETA_TESTER_SHA_LIST,
39+
FF_IO_X_USER_TOKEN_CANARY_SHA_USERS_REGEX,
3740
FF_ROUTING_PUSH_NOTIF,
3841
FF_ROUTING_PUSH_NOTIF_BETA_TESTER_SHA_LIST,
3942
FF_ROUTING_PUSH_NOTIF_CANARY_SHA_USERS_REGEX,
@@ -70,7 +73,6 @@ import { registerFirstLollipopConsumer } from "./routes/firstLollipopConsumerRou
7073
import { registerIoFimsAPIRoutes } from "./routes/ioFimsRoutes";
7174
import { registerIoSignAPIRoutes } from "./routes/ioSignRoutes";
7275
import { registerIoWalletAPIRoutes } from "./routes/ioWalletRoutes";
73-
import { registerMyPortalRoutes } from "./routes/myportalRoutes";
7476
import { registerPNRoutes } from "./routes/pnRoutes";
7577
import { registerPublicRoutes } from "./routes/publicRoutes";
7678
import { registerServicesAppBackendRoutes } from "./routes/servicesRoutes";
@@ -97,7 +99,6 @@ import RedisUserMetadataStorage from "./services/redisUserMetadataStorage";
9799
import ServicesAppBackendService from "./services/servicesAppBackendService";
98100
import TrialService from "./services/trialService";
99101
import UserDataProcessingService from "./services/userDataProcessingService";
100-
import bearerMyPortalTokenStrategy from "./strategies/bearerMyPortalTokenStrategy";
101102
import bearerSessionTokenStrategy from "./strategies/bearerSessionTokenStrategy";
102103
import { User } from "./types/user";
103104
import { attachTrackingData } from "./utils/appinsights";
@@ -117,12 +118,10 @@ export interface IAppFactoryParameters {
117118
readonly env: NodeEnvironment;
118119
readonly appInsightsClient?: appInsights.TelemetryClient;
119120
readonly allowNotifyIPSourceRange: ReadonlyArray<CIDR>;
120-
readonly allowMyPortalIPSourceRange: ReadonlyArray<CIDR>;
121121
readonly allowSessionHandleIPSourceRange: ReadonlyArray<CIDR>;
122122
readonly authenticationBasePath: string;
123123
readonly APIBasePath: string;
124124
readonly BonusAPIBasePath: string;
125-
readonly MyPortalBasePath: string;
126125
readonly CGNAPIBasePath: string;
127126
readonly CGNOperatorSearchAPIBasePath: string;
128127
readonly IoSignAPIBasePath: string;
@@ -136,13 +135,11 @@ export interface IAppFactoryParameters {
136135
export async function newApp({
137136
env,
138137
allowNotifyIPSourceRange,
139-
allowMyPortalIPSourceRange,
140138
allowSessionHandleIPSourceRange,
141139
appInsightsClient,
142140
authenticationBasePath,
143141
APIBasePath,
144142
BonusAPIBasePath,
145-
MyPortalBasePath,
146143
CGNAPIBasePath,
147144
IoSignAPIBasePath,
148145
IoFimsAPIBasePath,
@@ -168,20 +165,20 @@ export async function newApp({
168165
// Add the strategy to authenticate proxy clients.
169166
passport.use(
170167
"bearer.session",
171-
bearerSessionTokenStrategy(SESSION_STORAGE, attachTrackingData)
168+
bearerSessionTokenStrategy(
169+
FF_IO_X_USER_TOKEN_BETA_TESTER_SHA_LIST,
170+
FF_IO_X_USER_TOKEN_CANARY_SHA_USERS_REGEX,
171+
FF_IO_X_USER_TOKEN,
172+
SESSION_STORAGE,
173+
attachTrackingData
174+
)
172175
);
173176

174-
// Add the strategy to authenticate MyPortal clients.
175-
passport.use("bearer.myportal", bearerMyPortalTokenStrategy(SESSION_STORAGE));
176-
177177
// Add the strategy to authenticate webhook calls.
178178
passport.use(URL_TOKEN_STRATEGY);
179179

180180
// Creates middlewares for each implemented strategy
181181
const authMiddlewares = {
182-
bearerMyPortal: passport.authenticate("bearer.myportal", {
183-
session: false
184-
}),
185182
bearerSession: passport.authenticate("bearer.session", {
186183
session: false
187184
}),
@@ -495,13 +492,6 @@ export async function newApp({
495492
);
496493
}
497494

498-
registerMyPortalRoutes(
499-
app,
500-
MyPortalBasePath,
501-
allowMyPortalIPSourceRange,
502-
authMiddlewares.bearerMyPortal
503-
);
504-
505495
registerServicesAppBackendRoutes(
506496
app,
507497
ServicesAppBackendBasePath,

src/config.ts

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,6 @@ export const ALLOW_NOTIFY_IP_SOURCE_RANGE = pipe(
9494
})
9595
);
9696

97-
// IP(s) or CIDR(s) allowed for myportal endpoint
98-
export const ALLOW_MYPORTAL_IP_SOURCE_RANGE = pipe(
99-
process.env.ALLOW_MYPORTAL_IP_SOURCE_RANGE,
100-
decodeCIDRs,
101-
E.getOrElseW((errs) => {
102-
log.error(
103-
`Missing or invalid ALLOW_MYPORTAL_IP_SOURCE_RANGE environment variable: ${readableReport(
104-
errs
105-
)}`
106-
);
107-
return process.exit(1);
108-
})
109-
);
110-
11197
// IP(s) or CIDR(s) allowed for handling sessions
11298
export const ALLOW_SESSION_HANDLER_IP_SOURCE_RANGE = pipe(
11399
process.env.ALLOW_SESSION_HANDLER_IP_SOURCE_RANGE,
@@ -354,8 +340,6 @@ export const AUTHENTICATION_BASE_PATH = getRequiredENVVar(
354340
"AUTHENTICATION_BASE_PATH"
355341
);
356342

357-
export const MYPORTAL_BASE_PATH = getRequiredENVVar("MYPORTAL_BASE_PATH");
358-
359343
export const SERVICES_APP_BACKEND_BASE_PATH = getRequiredENVVar(
360344
"SERVICES_APP_BACKEND_BASE_PATH"
361345
);
@@ -615,3 +599,26 @@ export const IO_WALLET_API_CLIENT = IoWalletAPIClient(
615599
export const FF_IO_WALLET_ENABLED = process.env.FF_IO_WALLET_ENABLED === "1";
616600
export const FF_IO_WALLET_TRIAL_ENABLED =
617601
process.env.FF_IO_WALLET_TRIAL_ENABLED === "1";
602+
603+
export const FF_IO_X_USER_TOKEN = pipe(
604+
process.env.FF_IO_X_USER_TOKEN,
605+
FeatureFlag.decode,
606+
E.getOrElse(() => FeatureFlagEnum.NONE)
607+
);
608+
export const FF_IO_X_USER_TOKEN_BETA_TESTER_SHA_LIST = pipe(
609+
process.env.FF_IO_X_USER_TOKEN_BETA_TESTER_SHA_LIST,
610+
CommaSeparatedListOf(NonEmptyString).decode,
611+
E.getOrElseW((errs) => {
612+
log.error(
613+
`Missing or invalid FF_IO_X_USER_TOKEN_BETA_TESTER_SHA_LIST environment variable: ${readableReport(
614+
errs
615+
)}`
616+
);
617+
return process.exit(1);
618+
})
619+
);
620+
export const FF_IO_X_USER_TOKEN_CANARY_SHA_USERS_REGEX = pipe(
621+
process.env.FF_IO_X_USER_TOKEN_CANARY_SHA_USERS_REGEX,
622+
NonEmptyString.decode,
623+
E.getOrElse(() => "XYZ" as NonEmptyString)
624+
);

src/routes/myportalRoutes.ts

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/server.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import * as path from "path";
1616

1717
import { newApp } from "./app";
1818
import {
19-
ALLOW_MYPORTAL_IP_SOURCE_RANGE,
2019
ALLOW_NOTIFY_IP_SOURCE_RANGE,
2120
ALLOW_SESSION_HANDLER_IP_SOURCE_RANGE,
2221
API_BASE_PATH,
@@ -29,7 +28,6 @@ import {
2928
IO_FIMS_API_BASE_PATH,
3029
IO_SIGN_API_BASE_PATH,
3130
IO_WALLET_API_BASE_PATH,
32-
MYPORTAL_BASE_PATH,
3331
SERVER_PORT,
3432
SERVICES_APP_BACKEND_BASE_PATH,
3533
TRIAL_SYSTEM_API_BASE_PATH,
@@ -47,7 +45,6 @@ import { TimeTracer } from "./utils/timer";
4745
const authenticationBasePath = AUTHENTICATION_BASE_PATH;
4846
const APIBasePath = API_BASE_PATH;
4947
const BonusAPIBasePath = BONUS_API_BASE_PATH;
50-
const MyPortalBasePath = MYPORTAL_BASE_PATH;
5148
const CGNAPIBasePath = CGN_API_BASE_PATH;
5249
const IoSignAPIBasePath = IO_SIGN_API_BASE_PATH;
5350
const IoFimsAPIBasePath = IO_FIMS_API_BASE_PATH;
@@ -103,10 +100,8 @@ newApp({
103100
IoFimsAPIBasePath,
104101
IoSignAPIBasePath,
105102
IoWalletAPIBasePath,
106-
MyPortalBasePath,
107103
ServicesAppBackendBasePath,
108104
TrialSystemBasePath,
109-
allowMyPortalIPSourceRange: ALLOW_MYPORTAL_IP_SOURCE_RANGE,
110105
allowNotifyIPSourceRange: ALLOW_NOTIFY_IP_SOURCE_RANGE,
111106
allowSessionHandleIPSourceRange: ALLOW_SESSION_HANDLER_IP_SOURCE_RANGE,
112107
appInsightsClient: O.toUndefined(maybeAppInsightsClient),

src/services/notificationServiceFactory.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,11 @@ import { FiscalCode } from "../../generated/io-bonus-api/FiscalCode";
66
import { toFiscalCodeHash } from "../types/notification";
77
import {
88
FeatureFlag,
9+
getIsUserACanaryTestUser,
910
getIsUserEligibleForNewFeature
1011
} from "../utils/featureFlag";
1112
import NotificationService from "./notificationService";
1213

13-
/**
14-
*
15-
* @param regex The regex to use
16-
* @returns
17-
*/
18-
const getIsUserACanaryTestUser = (
19-
regex: string
20-
): ((sha: NonEmptyString) => boolean) => {
21-
const regExp = new RegExp(regex);
22-
return (sha: NonEmptyString): boolean => regExp.test(sha);
23-
};
24-
25-
// ------------------------------------------
26-
2714
export type NotificationServiceFactory = (
2815
fiscalCode: FiscalCode
2916
) => NotificationService;

0 commit comments

Comments
 (0)