Skip to content

Commit 6500fb2

Browse files
feat: add http proxy endpoints
1 parent 105ab29 commit 6500fb2

23 files changed

Lines changed: 3899 additions & 2052 deletions

data/init.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,24 @@ CREATE TABLE IF NOT EXISTS domains(
9999
CONSTRAINT domainsuffix UNIQUE (domain_suffix, tenant_id),
100100
PRIMARY KEY (name, domain_suffix, tenant_id)
101101
);
102+
CREATE TABLE IF NOT EXISTS proxiesconfigs(
103+
proxy_profile_name citext NOT NULL,
104+
access_info varchar(256),
105+
info_format integer,
106+
port integer,
107+
network_dns_suffix varchar(192),
108+
creation_date timestamp,
109+
tenant_id varchar(36) NOT NULL,
110+
PRIMARY KEY (proxy_profile_name, tenant_id)
111+
);
112+
CREATE TABLE IF NOT EXISTS profiles_proxiesconfigs(
113+
proxy_profile_name citext,
114+
profile_name citext,
115+
FOREIGN KEY (proxy_profile_name,tenant_id) REFERENCES proxiesconfigs(proxy_profile_name,tenant_id),
116+
FOREIGN KEY (profile_name,tenant_id) REFERENCES profiles(profile_name,tenant_id),
117+
priority integer,
118+
creation_date timestamp,
119+
created_by varchar(40),
120+
tenant_id varchar(36) NOT NULL,
121+
PRIMARY KEY (proxy_profile_name, profile_name, priority, tenant_id)
122+
);

src/data/postgres/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { WirelessProfilesTable } from './tables/wirelessProfiles.js'
1414
import { IEEE8021xProfilesTable } from './tables/ieee8021xProfiles.js'
1515
import { readFileSync } from 'fs'
1616
import { Environment } from '../../utils/Environment.js'
17+
import { ProxiesProfilesTable } from './tables/proxiesProfiles.js'
18+
import { ProfilesProxiesConfigsTable } from './tables/profileProxyConfigs.js'
1719

1820
export default class Db implements IDB {
1921
pool: InstanceType<typeof Pool>
@@ -23,6 +25,8 @@ export default class Db implements IDB {
2325
wirelessProfiles: WirelessProfilesTable
2426
profileWirelessConfigs: ProfilesWifiConfigsTable
2527
ieee8021xProfiles: IEEE8021xProfilesTable
28+
proxiesProfiles: ProxiesProfilesTable
29+
profileProxiesConfigs: ProfilesProxiesConfigsTable
2630

2731
log: Logger = new Logger('PostgresDb')
2832

@@ -79,6 +83,8 @@ export default class Db implements IDB {
7983
this.wirelessProfiles = new WirelessProfilesTable(this)
8084
this.profileWirelessConfigs = new ProfilesWifiConfigsTable(this)
8185
this.ieee8021xProfiles = new IEEE8021xProfilesTable(this)
86+
this.proxiesProfiles = new ProxiesProfilesTable(this)
87+
this.profileProxiesConfigs = new ProfilesProxiesConfigsTable(this)
8288
}
8389

8490
async query<T extends QueryResultRow>(text: string, params?: any): Promise<QueryResult<T>> {
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*********************************************************************
2+
* Copyright (c) Intel Corporation 2025
3+
* SPDX-License-Identifier: Apache-2.0
4+
**********************************************************************/
5+
6+
import PostgresDb from '../index.js'
7+
import { API_UNEXPECTED_EXCEPTION } from '../../../utils/constants.js'
8+
import { type ProfileProxyConfigs } from '../../../models/RCS.Config.js'
9+
import { ProfilesProxiesConfigsTable } from './profileProxyConfigs.js'
10+
import { jest } from '@jest/globals'
11+
import { type SpyInstance, spyOn } from 'jest-mock'
12+
13+
describe('profileproxyconfig tests', () => {
14+
let db: PostgresDb
15+
let profilesProxiesConfigsTable: ProfilesProxiesConfigsTable
16+
let querySpy: SpyInstance<any>
17+
const proxiesConfigs: ProfileProxyConfigs[] = [
18+
{ profileName: 'proxyConfig', priority: 1 } as any
19+
]
20+
const profileName = 'profileName'
21+
const tenantId = 'tenantId'
22+
23+
beforeEach(() => {
24+
db = new PostgresDb('')
25+
profilesProxiesConfigsTable = new ProfilesProxiesConfigsTable(db)
26+
querySpy = spyOn(profilesProxiesConfigsTable.db, 'query')
27+
})
28+
afterEach(() => {
29+
jest.clearAllMocks()
30+
})
31+
describe('Get', () => {
32+
test('should Get', async () => {
33+
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
34+
const result = await profilesProxiesConfigsTable.getProfileProxyConfigs(profileName)
35+
expect(result).toStrictEqual([{}])
36+
expect(querySpy).toBeCalledTimes(1)
37+
expect(querySpy).toBeCalledWith(
38+
`
39+
SELECT
40+
priority as "priority",
41+
proxy_profile_name as "profileName"
42+
FROM profiles_proxiesconfigs
43+
WHERE profile_name = $1 and tenant_id = $2
44+
ORDER BY priority`,
45+
[profileName, '']
46+
)
47+
})
48+
})
49+
describe('Delete', () => {
50+
test('should Delete', async () => {
51+
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
52+
const result = await profilesProxiesConfigsTable.deleteProfileProxyConfigs(profileName)
53+
expect(result).toBe(true)
54+
expect(querySpy).toBeCalledTimes(1)
55+
expect(querySpy).toBeCalledWith(
56+
`
57+
DELETE
58+
FROM profiles_proxiesconfigs
59+
WHERE profile_name = $1 and tenant_id = $2`,
60+
[profileName, '']
61+
)
62+
})
63+
test('should Delete with tenandId', async () => {
64+
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
65+
const result = await profilesProxiesConfigsTable.deleteProfileProxyConfigs(profileName, tenantId)
66+
expect(result).toBe(true)
67+
expect(querySpy).toBeCalledTimes(1)
68+
expect(querySpy).toBeCalledWith(
69+
`
70+
DELETE
71+
FROM profiles_proxiesconfigs
72+
WHERE profile_name = $1 and tenant_id = $2`,
73+
[profileName, tenantId]
74+
)
75+
})
76+
})
77+
describe('Insert', () => {
78+
test('should Insert', async () => {
79+
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
80+
const result = await profilesProxiesConfigsTable.createProfileProxyConfigs(proxiesConfigs, profileName)
81+
expect(result).toBe(true)
82+
expect(querySpy).toBeCalledTimes(1)
83+
expect(querySpy).toBeCalledWith(`
84+
INSERT INTO
85+
profiles_proxiesconfigs (proxy_profile_name, profile_name, priority, tenant_id)
86+
VALUES ('proxyConfig', 'profileName', '1', '')`)
87+
})
88+
test('should NOT insert when no proxyconfigs', async () => {
89+
await expect(profilesProxiesConfigsTable.createProfileProxyConfigs([], profileName)).rejects.toThrow(
90+
'Operation failed: profileName'
91+
)
92+
})
93+
test('should NOT insert when constraint violation', async () => {
94+
querySpy.mockRejectedValueOnce({ code: '23503', detail: 'error' })
95+
await expect(profilesProxiesConfigsTable.createProfileProxyConfigs(proxiesConfigs, profileName)).rejects.toThrow(
96+
'error'
97+
)
98+
})
99+
test('should NOT insert when unknown error', async () => {
100+
querySpy.mockRejectedValueOnce('unknown')
101+
await expect(profilesProxiesConfigsTable.createProfileProxyConfigs(proxiesConfigs, profileName)).rejects.toThrow(
102+
API_UNEXPECTED_EXCEPTION(profileName)
103+
)
104+
})
105+
})
106+
})
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*********************************************************************
2+
* Copyright (c) Intel Corporation 2025
3+
* SPDX-License-Identifier: Apache-2.0
4+
**********************************************************************/
5+
6+
import { type IProfilesProxiesConfigsTable } from '../../../interfaces/database/IProfileProxyConfigsDb.js'
7+
import { type ProfileProxyConfigs } from '../../../models/RCS.Config.js'
8+
import { API_UNEXPECTED_EXCEPTION } from '../../../utils/constants.js'
9+
import { RPSError } from '../../../utils/RPSError.js'
10+
import format from 'pg-format'
11+
import type PostgresDb from '../index.js'
12+
import { PostgresErr } from '../errors.js'
13+
14+
export class ProfilesProxiesConfigsTable implements IProfilesProxiesConfigsTable {
15+
db: PostgresDb
16+
constructor(db: PostgresDb) {
17+
this.db = db
18+
}
19+
20+
/**
21+
* @description Get AMT Profile associated proxy configs
22+
* @param {string} profileName
23+
* @returns {ProfileProxyConfigs[]} Return an array of proxy configs
24+
*/
25+
async getProfileProxyConfigs(profileName: string, tenantId = ''): Promise<ProfileProxyConfigs[]> {
26+
const results = await this.db.query<ProfileProxyConfigs>(
27+
`
28+
SELECT
29+
priority as "priority",
30+
proxy_profile_name as "profileName"
31+
FROM profiles_proxiesconfigs
32+
WHERE profile_name = $1 and tenant_id = $2
33+
ORDER BY priority`,
34+
[profileName, tenantId]
35+
)
36+
return results.rows
37+
}
38+
39+
/**
40+
* @description Insert proxy configs associated with AMT profile
41+
* @param {ProfileProxyConfigs[]} proxyConfigs
42+
* @param {string} profileName
43+
* @returns {ProfileProxyConfigs[]} Return an array of proxy configs
44+
*/
45+
async createProfileProxyConfigs(
46+
proxyConfigs: ProfileProxyConfigs[],
47+
profileName: string,
48+
tenantId = ''
49+
): Promise<boolean> {
50+
try {
51+
if (proxyConfigs.length < 1) {
52+
throw new RPSError('No proxyConfigs provided to insert')
53+
}
54+
// Preparing data for inserting multiple rows
55+
const configs = proxyConfigs.map((config) => [
56+
config.profileName,
57+
profileName,
58+
config.priority,
59+
tenantId
60+
])
61+
const proxyProfilesQueryResults = await this.db.query(
62+
format(
63+
`
64+
INSERT INTO
65+
profiles_proxiesconfigs (proxy_profile_name, profile_name, priority, tenant_id)
66+
VALUES %L`,
67+
configs
68+
)
69+
)
70+
71+
if (proxyProfilesQueryResults?.rowCount) {
72+
if (proxyProfilesQueryResults.rowCount > 0) {
73+
return true
74+
}
75+
}
76+
} catch (error) {
77+
if (error.code === PostgresErr.C23_FOREIGN_KEY_VIOLATION) {
78+
throw new RPSError(error.detail, 'Foreign key constraint violation')
79+
}
80+
throw new RPSError(API_UNEXPECTED_EXCEPTION(profileName))
81+
}
82+
return false
83+
}
84+
85+
/**
86+
* @description Delete proxy configs of an AMT Profile from DB by profile name
87+
* @param {string} profileName
88+
* @returns {boolean} Return true on successful deletion
89+
*/
90+
async deleteProfileProxyConfigs(profileName: string, tenantId = ''): Promise<boolean> {
91+
const deleteProfileWifiResults = await this.db.query(
92+
`
93+
DELETE
94+
FROM profiles_proxiesconfigs
95+
WHERE profile_name = $1 and tenant_id = $2`,
96+
[profileName, tenantId]
97+
)
98+
99+
if (deleteProfileWifiResults?.rowCount) {
100+
if (deleteProfileWifiResults.rowCount > 0) {
101+
return true
102+
}
103+
}
104+
105+
return false
106+
}
107+
}

0 commit comments

Comments
 (0)