Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions data/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,23 @@ CREATE TABLE IF NOT EXISTS domains(
CONSTRAINT domainsuffix UNIQUE (domain_suffix, tenant_id),
PRIMARY KEY (name, domain_suffix, tenant_id)
);
CREATE TABLE IF NOT EXISTS proxyconfigs(
access_info varchar(256) NOT NULL,
info_format integer,
port integer,
network_dns_suffix varchar(192),
creation_date timestamp,
tenant_id varchar(36) NOT NULL,
PRIMARY KEY (access_info, tenant_id)
);
CREATE TABLE IF NOT EXISTS profiles_proxyconfigs(
access_info citext,
profile_name citext,
FOREIGN KEY (access_info,tenant_id) REFERENCES proxyconfigs(access_info,tenant_id),
FOREIGN KEY (profile_name,tenant_id) REFERENCES profiles(profile_name,tenant_id),
priority integer,
creation_date timestamp,
created_by varchar(40),
tenant_id varchar(36) NOT NULL,
PRIMARY KEY (access_info, profile_name, priority, tenant_id)
);
6 changes: 6 additions & 0 deletions src/data/postgres/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { WirelessProfilesTable } from './tables/wirelessProfiles.js'
import { IEEE8021xProfilesTable } from './tables/ieee8021xProfiles.js'
import { readFileSync } from 'fs'
import { Environment } from '../../utils/Environment.js'
import { ProxyConfigsTable } from './tables/proxyConfigs.js'
import { ProfileProxyConfigsTable } from './tables/profileProxyConfigs.js'

export default class Db implements IDB {
pool: InstanceType<typeof Pool>
Expand All @@ -23,6 +25,8 @@ export default class Db implements IDB {
wirelessProfiles: WirelessProfilesTable
profileWirelessConfigs: ProfilesWifiConfigsTable
ieee8021xProfiles: IEEE8021xProfilesTable
proxyConfigs: ProxyConfigsTable
profileProxyConfigs: ProfileProxyConfigsTable

log: Logger = new Logger('PostgresDb')

Expand Down Expand Up @@ -79,6 +83,8 @@ export default class Db implements IDB {
this.wirelessProfiles = new WirelessProfilesTable(this)
this.profileWirelessConfigs = new ProfilesWifiConfigsTable(this)
this.ieee8021xProfiles = new IEEE8021xProfilesTable(this)
this.proxyConfigs = new ProxyConfigsTable(this)
this.profileProxyConfigs = new ProfileProxyConfigsTable(this)
}

async query<T extends QueryResultRow>(text: string, params?: any): Promise<QueryResult<T>> {
Expand Down
106 changes: 106 additions & 0 deletions src/data/postgres/tables/profileProxyConfigs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*********************************************************************
* Copyright (c) Intel Corporation 2025
* SPDX-License-Identifier: Apache-2.0
**********************************************************************/

import PostgresDb from '../index.js'
import { API_UNEXPECTED_EXCEPTION } from '../../../utils/constants.js'
import { type ProfileProxyConfigs } from '../../../models/RCS.Config.js'
import { ProfileProxyConfigsTable } from './profileProxyConfigs.js'
import { jest } from '@jest/globals'
import { type SpyInstance, spyOn } from 'jest-mock'

describe('profileproxyconfig tests', () => {
let db: PostgresDb
let profilesProxyConfigsTable: ProfileProxyConfigsTable
let querySpy: SpyInstance<any>
const proxyConfigs: ProfileProxyConfigs[] = [
{ configName: 'proxyConfig', priority: 1 } as any
]
const configName = 'profileName'
const tenantId = 'tenantId'

beforeEach(() => {
db = new PostgresDb('')
profilesProxyConfigsTable = new ProfileProxyConfigsTable(db)
querySpy = spyOn(profilesProxyConfigsTable.db, 'query')
})
afterEach(() => {
jest.clearAllMocks()
})
describe('Get', () => {
test('should Get', async () => {
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
const result = await profilesProxyConfigsTable.getProfileProxyConfigs(configName)
expect(result).toStrictEqual([{}])
expect(querySpy).toBeCalledTimes(1)
expect(querySpy).toBeCalledWith(
`
SELECT
priority as "priority",
access_info as "configName"
FROM profiles_proxyconfigs
WHERE profile_name = $1 and tenant_id = $2
ORDER BY priority`,
[configName, '']
)
})
})
describe('Delete', () => {
test('should Delete', async () => {
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
const result = await profilesProxyConfigsTable.deleteProfileProxyConfigs(configName)
expect(result).toBe(true)
expect(querySpy).toBeCalledTimes(1)
expect(querySpy).toBeCalledWith(
`
DELETE
FROM profiles_proxyconfigs
WHERE profile_name = $1 and tenant_id = $2`,
[configName, '']
)
})
test('should Delete with tenandId', async () => {
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
const result = await profilesProxyConfigsTable.deleteProfileProxyConfigs(configName, tenantId)
expect(result).toBe(true)
expect(querySpy).toBeCalledTimes(1)
expect(querySpy).toBeCalledWith(
`
DELETE
FROM profiles_proxyconfigs
WHERE profile_name = $1 and tenant_id = $2`,
[configName, tenantId]
)
})
})
describe('Insert', () => {
test('should Insert', async () => {
querySpy.mockResolvedValueOnce({ rows: [{}], rowCount: 1 })
const result = await profilesProxyConfigsTable.createProfileProxyConfigs(proxyConfigs, configName)
expect(result).toBe(true)
expect(querySpy).toBeCalledTimes(1)
expect(querySpy).toBeCalledWith(`
INSERT INTO
profiles_proxyconfigs (access_info, profile_name, priority, tenant_id)
VALUES ('proxyConfig', 'profileName', '1', '')`)
})
test('should NOT insert when no proxyconfigs', async () => {
await expect(profilesProxyConfigsTable.createProfileProxyConfigs([], configName)).rejects.toThrow(
'Operation failed: profileName'
)
})
test('should NOT insert when constraint violation', async () => {
querySpy.mockRejectedValueOnce({ code: '23503', detail: 'error' })
await expect(profilesProxyConfigsTable.createProfileProxyConfigs(proxyConfigs, configName)).rejects.toThrow(
'error'
)
})
test('should NOT insert when unknown error', async () => {
querySpy.mockRejectedValueOnce('unknown')
await expect(profilesProxyConfigsTable.createProfileProxyConfigs(proxyConfigs, configName)).rejects.toThrow(
API_UNEXPECTED_EXCEPTION(configName)
)
})
})
})
103 changes: 103 additions & 0 deletions src/data/postgres/tables/profileProxyConfigs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*********************************************************************
* Copyright (c) Intel Corporation 2025
* SPDX-License-Identifier: Apache-2.0
**********************************************************************/

import { type IProfileProxyConfigsTable } from '../../../interfaces/database/IProfileProxyConfigsDb.js'
import { type ProfileProxyConfigs } from '../../../models/RCS.Config.js'
import { API_UNEXPECTED_EXCEPTION } from '../../../utils/constants.js'
import { RPSError } from '../../../utils/RPSError.js'
import format from 'pg-format'
import type PostgresDb from '../index.js'
import { PostgresErr } from '../errors.js'

export class ProfileProxyConfigsTable implements IProfileProxyConfigsTable {
db: PostgresDb
constructor(db: PostgresDb) {
this.db = db
}

/**
* @description Get AMT Profile associated proxy configs
* @param {string} configName
* @returns {ProfileProxyConfigs[]} Return an array of proxy configs
*/
async getProfileProxyConfigs(configName: string, tenantId = ''): Promise<ProfileProxyConfigs[]> {
const results = await this.db.query<ProfileProxyConfigs>(
`
SELECT
priority as "priority",
access_info as "configName"
FROM profiles_proxyconfigs
WHERE profile_name = $1 and tenant_id = $2
ORDER BY priority`,
[configName, tenantId]
)
return results.rows
}

/**
* @description Insert proxy configs associated with AMT profile
* @param {ProfileProxyConfigs[]} proxyConfigs
* @param {string} configName
* @returns {ProfileProxyConfigs[]} Return an array of proxy configs
*/
async createProfileProxyConfigs(
proxyConfigs: ProfileProxyConfigs[],
configName: string,
tenantId = ''
): Promise<boolean> {
try {
if (proxyConfigs.length < 1) {
throw new RPSError('No proxyConfigs provided to insert')
}
// Preparing data for inserting multiple rows
const configs = proxyConfigs.map((config) => [
config.configName,
configName,
config.priority,
tenantId
])
const proxyProfilesQueryResults = await this.db.query(
format(
`
INSERT INTO
profiles_proxyconfigs (access_info, profile_name, priority, tenant_id)
VALUES %L`,
configs
)
)

if ((proxyProfilesQueryResults?.rowCount ?? 0) > 0) {
return true
}
} catch (error) {
if (error.code === PostgresErr.C23_FOREIGN_KEY_VIOLATION) {
throw new RPSError(error.detail, 'Foreign key constraint violation')
}
throw new RPSError(API_UNEXPECTED_EXCEPTION(configName))
}
return false
}

/**
* @description Delete proxy configs of an AMT Profile from DB by profile name
* @param {string} configName
* @returns {boolean} Return true on successful deletion
*/
async deleteProfileProxyConfigs(configName: string, tenantId = ''): Promise<boolean> {
const deleteProfileWifiResults = await this.db.query(
`
DELETE
FROM profiles_proxyconfigs
WHERE profile_name = $1 and tenant_id = $2`,
[configName, tenantId]
)

if ((deleteProfileWifiResults?.rowCount ?? 0) > 0) {
return true
}

return false
}
}
Loading
Loading