Skip to content

Commit

Permalink
TW-1192 Implement a backend for ads replacement management
Browse files Browse the repository at this point in the history
  • Loading branch information
keshan3262 committed Dec 11, 2023
1 parent 1fa0f20 commit 51fc09b
Show file tree
Hide file tree
Showing 8 changed files with 816 additions and 16 deletions.
2 changes: 2 additions & 0 deletions .env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ THREE_ROUTE_API_AUTH_TOKEN=
REDIS_URL=
ADD_NOTIFICATION_USERNAME=
ADD_NOTIFICATION_PASSWORD=
MANAGE_ADS_USERNAME=
MANAGE_ADS_PASSWORD=
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
"express": "^4.18.2",
"firebase-admin": "^10.0.2",
"ioredis": "^5.3.2",
"joi": "^17.11.0",
"lodash": "^4.17.21",
"memoizee": "^0.4.15",
"pino": "^6.11.2",
"pino-http": "^5.5.0",
"pino-pretty": "^4.7.1",
"qs": "^6.10.3",
"semaphore": "^1.1.0"
"semaphore": "^1.1.0",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.0"
},
"scripts": {
"start": "cross-env NODE_ENV=development ts-node-dev --files --quiet src/index.ts",
Expand Down
70 changes: 70 additions & 0 deletions src/advertising/slise.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { redisClient } from '../redis';
import { isDefined } from '../utils/helpers';

export interface SliseAdContainerRule {
urlRegexes: string[];
selector: {
isMultiple: boolean;
cssString: string;
shouldUseResultParent: boolean;
};
}

const SLISE_AD_CONTAINERS_RULES_KEY = 'slise_ad_containers_rules';
const SLISE_HEURISTIC_URL_REGEXES_KEY = 'slise_heuristic_url_regexes_key';
const SLISE_HEURISTIC_SELECTORS_KEY = 'slise_heuristic_selectors_key';

export const getSliseAdContainerRulesByDomain = async (domain: string) => {
const rule = await redisClient.hget(SLISE_AD_CONTAINERS_RULES_KEY, domain);

return isDefined(rule)
? (JSON.parse(rule) as SliseAdContainerRule[])
: [
{
urlRegexes: [],
selector: {
isMultiple: false,
cssString: '*',
shouldUseResultParent: false
}
}
];
};

export const getAllSliseAdContainerRules = async () => {
const rules = await redisClient.hgetall(SLISE_AD_CONTAINERS_RULES_KEY);

const parsedRules: { [domain: string]: SliseAdContainerRule[] } = {};
for (const domainName in rules) {
parsedRules[domainName] = JSON.parse(rules[domainName]);
}

return parsedRules;
};

export const upsertSliseAdContainerRules = async (rules: Record<string, SliseAdContainerRule[]>) => {
// Failed to set the arrays as values in Redis, so stringifying them
await redisClient.hmset(
SLISE_AD_CONTAINERS_RULES_KEY,
Object.fromEntries(Object.entries(rules).map(([domain, rules]) => [domain, JSON.stringify(rules)]))
);
};

export const removeSliseAdContainerRules = async (domains: string[]) =>
redisClient.hdel(SLISE_AD_CONTAINERS_RULES_KEY, ...domains);

export const getSliseHeuristicUrlRegexes = async () => redisClient.smembers(SLISE_HEURISTIC_URL_REGEXES_KEY);

export const addSliseHeuristicUrlRegexes = async (regexes: string[]) =>
redisClient.sadd(SLISE_HEURISTIC_URL_REGEXES_KEY, ...regexes);

export const removeSliseHeuristicUrlRegexes = async (regexes: string[]) =>
redisClient.srem(SLISE_HEURISTIC_URL_REGEXES_KEY, ...regexes);

export const getSliseHeuristicSelectors = async () => redisClient.smembers(SLISE_HEURISTIC_SELECTORS_KEY);

export const addSliseHeuristicSelectors = async (selectors: string[]) =>
redisClient.sadd(SLISE_HEURISTIC_SELECTORS_KEY, ...selectors);

export const removeSliseHeuristicSelectors = async (selectors: string[]) =>
redisClient.srem(SLISE_HEURISTIC_SELECTORS_KEY, ...selectors);
10 changes: 6 additions & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ export const MIN_IOS_APP_VERSION = '1.10.445';
export const MIN_ANDROID_APP_VERSION = '1.10.445';

export const EnvVars = {
MOONPAY_SECRET_KEY: getEnv('MOONPAY_SECRET_KEY'),
ALICE_BOB_PRIVATE_KEY: getEnv('ALICE_BOB_PRIVATE_KEY'),
ALICE_BOB_PUBLIC_KEY: getEnv('ALICE_BOB_PUBLIC_KEY'),
MOONPAY_SECRET_KEY: '', // getEnv('MOONPAY_SECRET_KEY'),
ALICE_BOB_PRIVATE_KEY: '', // getEnv('ALICE_BOB_PRIVATE_KEY'),
ALICE_BOB_PUBLIC_KEY: '', // getEnv('ALICE_BOB_PUBLIC_KEY'),
THREE_ROUTE_API_URL: getEnv('THREE_ROUTE_API_URL'),
THREE_ROUTE_API_AUTH_TOKEN: getEnv('THREE_ROUTE_API_AUTH_TOKEN'),
REDIS_URL: getEnv('REDIS_URL'),
ADD_NOTIFICATION_USERNAME: getEnv('ADD_NOTIFICATION_USERNAME'),
ADD_NOTIFICATION_PASSWORD: getEnv('ADD_NOTIFICATION_PASSWORD')
ADD_NOTIFICATION_PASSWORD: getEnv('ADD_NOTIFICATION_PASSWORD'),
MANAGE_ADS_USERNAME: getEnv('MANAGE_ADS_USERNAME'),
MANAGE_ADS_PASSWORD: getEnv('MANAGE_ADS_PASSWORD')
};

for (const name in EnvVars) {
Expand Down
22 changes: 20 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ import express, { Request, Response } from 'express';
import firebaseAdmin from 'firebase-admin';
import { stdSerializers } from 'pino';
import pinoHttp from 'pino-http';
import swaggerJSDoc from 'swagger-jsdoc';
import swaggerUi from 'swagger-ui-express';

import { getAdvertisingInfo } from './advertising/advertising';
import { MIN_ANDROID_APP_VERSION, MIN_IOS_APP_VERSION } from './config';
import getDAppsStats from './getDAppsStats';
import { basicAuth } from './middlewares/basic-auth.middleware';
import { basicAuth, BasicAuthRights } from './middlewares/basic-auth.middleware';
import { Notification, PlatformType } from './notifications/notification.interface';
import { getImageFallback } from './notifications/utils/get-image-fallback.util';
import { getNotifications } from './notifications/utils/get-notifications.util';
import { getParsedContent } from './notifications/utils/get-parsed-content.util';
import { getPlatforms } from './notifications/utils/get-platforms.util';
import { redisClient } from './redis';
import { sliseRulesRouter } from './routers/slise-rules-router';
import { getABData } from './utils/ab-test';
import { cancelAliceBobOrder } from './utils/alice-bob/cancel-alice-bob-order';
import { createAliceBobOrder } from './utils/alice-bob/create-alice-bob-order';
Expand Down Expand Up @@ -115,7 +118,7 @@ app.get('/api/notifications', async (_req, res) => {
}
});

app.post('/api/notifications', basicAuth, async (req, res) => {
app.post('/api/notifications', basicAuth(BasicAuthRights.AddNotification), async (req, res) => {
try {
const {
mobile,
Expand Down Expand Up @@ -322,6 +325,21 @@ app.get('/api/advertising-info', (_req, res) => {
}
});

app.use('/api/slise-ad-container-rules', sliseRulesRouter);

const swaggerOptions = {
swaggerDefinition: {
openapi: '3.0.0',
info: {
title: 'Temple Wallet backend',
version: '1.0.0'
}
},
apis: ['./src/index.ts', './src/routers/*.ts']
};
const swaggerSpec = swaggerJSDoc(swaggerOptions);
app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));

// start the server listening for requests
const port = Boolean(process.env.PORT) ? process.env.PORT : 3000;
app.listen(port, () => console.info(`Server is running on port ${port}...`));
21 changes: 19 additions & 2 deletions src/middlewares/basic-auth.middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,30 @@ import { Request, Response, NextFunction } from 'express';
import { EnvVars } from '../config';
import { isDefined } from '../utils/helpers';

export const basicAuth = (req: Request, res: Response, next: NextFunction) => {
export enum BasicAuthRights {
AddNotification = 'add-notification',
ManageAds = 'manage-ads'
}

const credentials = {
[BasicAuthRights.AddNotification]: {
username: EnvVars.ADD_NOTIFICATION_USERNAME,
password: EnvVars.ADD_NOTIFICATION_PASSWORD
},
[BasicAuthRights.ManageAds]: {
username: EnvVars.MANAGE_ADS_USERNAME,
password: EnvVars.MANAGE_ADS_PASSWORD
}
};

export const basicAuth = (rights: BasicAuthRights) => (req: Request, res: Response, next: NextFunction) => {
const base64EncodedCredentials = req.get('Authorization');

if (isDefined(base64EncodedCredentials)) {
const [username, password] = Buffer.from(base64EncodedCredentials.split(' ')[1], 'base64').toString().split(':');
const { username: correctUsername, password: correctPassword } = credentials[rights];

if (!(username === EnvVars.ADD_NOTIFICATION_USERNAME && password === EnvVars.ADD_NOTIFICATION_PASSWORD)) {
if (!(username === correctUsername && password === correctPassword)) {
handleNotAuthenticated(res, next);
}
next();
Expand Down
Loading

0 comments on commit 51fc09b

Please sign in to comment.