Skip to content

Commit d08fc2e

Browse files
berosasoBlanca Rosas
andauthored
refactor: add http proxy endpoints (#2277)
* feat: add http proxy endpoints for get all and post * fix: addressing PR comments * fix: changing primary key in db * fix: postman collection * fix: removing redundant code --------- Co-authored-by: Blanca Rosas <berosaso@berosaso-mobl1.amr.corp.intel.com>
1 parent e6cdcd3 commit d08fc2e

23 files changed

Lines changed: 3597 additions & 1254 deletions

data/init.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,23 @@ 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 proxyconfigs(
103+
access_info varchar(256) NOT NULL,
104+
info_format integer,
105+
port integer,
106+
network_dns_suffix varchar(192),
107+
creation_date timestamp,
108+
tenant_id varchar(36) NOT NULL,
109+
PRIMARY KEY (access_info, tenant_id)
110+
);
111+
CREATE TABLE IF NOT EXISTS profiles_proxyconfigs(
112+
access_info citext,
113+
profile_name citext,
114+
FOREIGN KEY (access_info,tenant_id) REFERENCES proxyconfigs(access_info,tenant_id),
115+
FOREIGN KEY (profile_name,tenant_id) REFERENCES profiles(profile_name,tenant_id),
116+
priority integer,
117+
creation_date timestamp,
118+
created_by varchar(40),
119+
tenant_id varchar(36) NOT NULL,
120+
PRIMARY KEY (access_info, profile_name, priority, tenant_id)
121+
);

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 { ProxyConfigsTable } from './tables/proxyConfigs.js'
18+
import { ProfileProxyConfigsTable } 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+
proxyConfigs: ProxyConfigsTable
29+
profileProxyConfigs: ProfileProxyConfigsTable
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.proxyConfigs = new ProxyConfigsTable(this)
87+
this.profileProxyConfigs = new ProfileProxyConfigsTable(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 { ProfileProxyConfigsTable } 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 profilesProxyConfigsTable: ProfileProxyConfigsTable
16+
let querySpy: SpyInstance<any>
17+
const proxyConfigs: ProfileProxyConfigs[] = [
18+
{ configName: 'proxyConfig', priority: 1 } as any
19+
]
20+
const configName = 'profileName'
21+
const tenantId = 'tenantId'
22+
23+
beforeEach(() => {
24+
db = new PostgresDb('')
25+
profilesProxyConfigsTable = new ProfileProxyConfigsTable(db)
26+
querySpy = spyOn(profilesProxyConfigsTable.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 profilesProxyConfigsTable.getProfileProxyConfigs(configName)
35+
expect(result).toStrictEqual([{}])
36+
expect(querySpy).toBeCalledTimes(1)
37+
expect(querySpy).toBeCalledWith(
38+
`
39+
SELECT
40+
priority as "priority",
41+
access_info as "configName"
42+
FROM profiles_proxyconfigs
43+
WHERE profile_name = $1 and tenant_id = $2
44+
ORDER BY priority`,
45+
[configName, '']
46+
)
47+
})
48+
})
49+
describe('Delete', () => {
50+
test('should Delete', async () => {
51+
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
52+
const result = await profilesProxyConfigsTable.deleteProfileProxyConfigs(configName)
53+
expect(result).toBe(true)
54+
expect(querySpy).toBeCalledTimes(1)
55+
expect(querySpy).toBeCalledWith(
56+
`
57+
DELETE
58+
FROM profiles_proxyconfigs
59+
WHERE profile_name = $1 and tenant_id = $2`,
60+
[configName, '']
61+
)
62+
})
63+
test('should Delete with tenandId', async () => {
64+
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
65+
const result = await profilesProxyConfigsTable.deleteProfileProxyConfigs(configName, tenantId)
66+
expect(result).toBe(true)
67+
expect(querySpy).toBeCalledTimes(1)
68+
expect(querySpy).toBeCalledWith(
69+
`
70+
DELETE
71+
FROM profiles_proxyconfigs
72+
WHERE profile_name = $1 and tenant_id = $2`,
73+
[configName, tenantId]
74+
)
75+
})
76+
})
77+
describe('Insert', () => {
78+
test('should Insert', async () => {
79+
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
80+
const result = await profilesProxyConfigsTable.createProfileProxyConfigs(proxyConfigs, configName)
81+
expect(result).toBe(true)
82+
expect(querySpy).toBeCalledTimes(1)
83+
expect(querySpy).toBeCalledWith(`
84+
INSERT INTO
85+
profiles_proxyconfigs (access_info, profile_name, priority, tenant_id)
86+
VALUES ('proxyConfig', 'profileName', '1', '')`)
87+
})
88+
test('should NOT insert when no proxyconfigs', async () => {
89+
await expect(profilesProxyConfigsTable.createProfileProxyConfigs([], configName)).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(profilesProxyConfigsTable.createProfileProxyConfigs(proxyConfigs, configName)).rejects.toThrow(
96+
'error'
97+
)
98+
})
99+
test('should NOT insert when unknown error', async () => {
100+
querySpy.mockRejectedValueOnce('unknown')
101+
await expect(profilesProxyConfigsTable.createProfileProxyConfigs(proxyConfigs, configName)).rejects.toThrow(
102+
API_UNEXPECTED_EXCEPTION(configName)
103+
)
104+
})
105+
})
106+
})
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*********************************************************************
2+
* Copyright (c) Intel Corporation 2025
3+
* SPDX-License-Identifier: Apache-2.0
4+
**********************************************************************/
5+
6+
import { type IProfileProxyConfigsTable } 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 ProfileProxyConfigsTable implements IProfileProxyConfigsTable {
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} configName
23+
* @returns {ProfileProxyConfigs[]} Return an array of proxy configs
24+
*/
25+
async getProfileProxyConfigs(configName: string, tenantId = ''): Promise<ProfileProxyConfigs[]> {
26+
const results = await this.db.query<ProfileProxyConfigs>(
27+
`
28+
SELECT
29+
priority as "priority",
30+
access_info as "configName"
31+
FROM profiles_proxyconfigs
32+
WHERE profile_name = $1 and tenant_id = $2
33+
ORDER BY priority`,
34+
[configName, 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} configName
43+
* @returns {ProfileProxyConfigs[]} Return an array of proxy configs
44+
*/
45+
async createProfileProxyConfigs(
46+
proxyConfigs: ProfileProxyConfigs[],
47+
configName: 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.configName,
57+
configName,
58+
config.priority,
59+
tenantId
60+
])
61+
const proxyProfilesQueryResults = await this.db.query(
62+
format(
63+
`
64+
INSERT INTO
65+
profiles_proxyconfigs (access_info, profile_name, priority, tenant_id)
66+
VALUES %L`,
67+
configs
68+
)
69+
)
70+
71+
if ((proxyProfilesQueryResults?.rowCount ?? 0) > 0) {
72+
return true
73+
}
74+
} catch (error) {
75+
if (error.code === PostgresErr.C23_FOREIGN_KEY_VIOLATION) {
76+
throw new RPSError(error.detail, 'Foreign key constraint violation')
77+
}
78+
throw new RPSError(API_UNEXPECTED_EXCEPTION(configName))
79+
}
80+
return false
81+
}
82+
83+
/**
84+
* @description Delete proxy configs of an AMT Profile from DB by profile name
85+
* @param {string} configName
86+
* @returns {boolean} Return true on successful deletion
87+
*/
88+
async deleteProfileProxyConfigs(configName: string, tenantId = ''): Promise<boolean> {
89+
const deleteProfileWifiResults = await this.db.query(
90+
`
91+
DELETE
92+
FROM profiles_proxyconfigs
93+
WHERE profile_name = $1 and tenant_id = $2`,
94+
[configName, tenantId]
95+
)
96+
97+
if ((deleteProfileWifiResults?.rowCount ?? 0) > 0) {
98+
return true
99+
}
100+
101+
return false
102+
}
103+
}

0 commit comments

Comments
 (0)