Commit 2f8cd049 authored by Jukkrapong Ponharn's avatar Jukkrapong Ponharn

Refactor PolicyRequest class and enhance getPublicIP function; add HTTP method...

Refactor PolicyRequest class and enhance getPublicIP function; add HTTP method enum and improve configuration handling
parent be32d104
......@@ -9,6 +9,16 @@ export interface ResourceParam {
[key: string]: any;
}
/**
* HTTP Method Enum
*/
export enum HttpMethod {
GET = 'GET',
POST = 'POST',
PUT = 'PUT',
DELETE = 'DELETE',
}
/**
* Resource Structure
*/
......@@ -37,10 +47,8 @@ export interface Environment {
* Policy Request Configuration
*/
export interface PolicyConfig {
subject?: Subject;
resource?: Resource;
action?: string;
environment?: Environment;
}
/**
......@@ -53,36 +61,112 @@ export interface PolicyRequestData {
environment: Environment;
}
async function getPublicIP(): Promise<string> {
/**
* Get public IP address
* @returns Public IP address or null if failed
*/
async function getPublicIP(): Promise<string | null> {
try {
const response = await axios.get("https://api.ipify.org/?format=json");
const response = await axios.get('https://api.ipify.org/?format=json', {
timeout: 5000, // 5 second timeout
});
const ip = response.data?.ip;
if (!ip) {
throw new Error("IP address not found in response");
if (!ip || typeof ip !== 'string') {
throw new Error('IP address not found in response');
}
return ip;
} catch (error) {
// Do not throw here to avoid breaking callers that expect a string.
// Log the error and return empty string as a safe fallback.
console.error('getPublicIP error:', error);
return '';
console.error('Failed to get public IP:', error);
return null;
}
}
/**
* Policy Request Utility Functions
* Policy Request Instance Configuration
*/
export interface PolicyRequestInstanceConfig {
subject: Subject;
clientName: string;
ipVerify?: boolean;
}
/**
* Policy Request Class
*/
export class PolicyRequest {
private subject: Subject;
private clientName: string;
private ipVerify: boolean;
/**
* Create PolicyRequest instance
* @param config - Instance configuration with subject and clientName
*/
constructor(config: PolicyRequestInstanceConfig) {
this.subject = config.subject;
this.clientName = config.clientName;
this.ipVerify = config.ipVerify ?? false;
}
/**
* Get current subject
*/
getSubject(): Subject {
return { ...this.subject };
}
/**
* Get client name
*/
getClientName(): string {
return this.clientName;
}
/**
* Get IP Verify
*/
getIpVerify(): boolean {
return this.ipVerify;
}
/**
* Set ipVerify status
* @param ipVerify - IP verification flag
*/
setIpVerify(ipVerify: boolean): void {
this.ipVerify = ipVerify;
}
/**
* Update subject data
* @param subject - New subject data (merges with existing)
*/
updateSubject(subject: Subject): void {
this.subject = { ...this.subject, ...subject };
}
/**
* Create policy request and encode to Base64
* @param config - Policy configuration object
* @returns Base64 encoded string
*/
static create(config: PolicyConfig = {}): string {
async create(config: Omit<PolicyConfig, 'subject'> = {}): Promise<string> {
let environment: Environment = {
"resource": {
"type": "WEB",
"name": this.clientName,
"timestamp": new Date(),
}
}
if (this.ipVerify) {
environment["public_ip"] = await getPublicIP();
}
const data: PolicyRequestData = {
subject: config.subject || {},
subject: this.subject,
resource: {
type: config.resource?.type || 'API',
type: config.resource?.type || '',
name: config.resource?.name || '',
param: {
path: config.resource?.param?.path || '',
......@@ -91,7 +175,7 @@ export class PolicyRequest {
...config.resource,
},
action: config.action || '',
environment: config.environment || {},
environment: environment,
};
const jsonString = JSON.stringify(data);
......@@ -100,31 +184,17 @@ export class PolicyRequest {
/**
* Create policy request headers
* @param config - Policy configuration object
* @param url - API url
* @param method - HTTP method for call API
* @param headerKey - Custom header key name (default: 'X-Policy-Request')
* @returns Headers object
*/
static async createHeaders(
clientName: string,
async createHeaders(
url: string,
method: string,
subject: Subject = {},
ipVerify: Boolean = false,
method: HttpMethod,
headerKey: string = 'X-Policy-Request'
): Promise<Record<string, string>> {
let environment: any = {
"resource": {
"type": "WEB",
"name": clientName,
"timestamp": new Date(),
}
}
if (ipVerify) {
environment["public_ip"] = await getPublicIP();
}
const policyConfig = {
subject: subject,
resource: {
"type": "API",
"name": "",
......@@ -132,10 +202,9 @@ export class PolicyRequest {
"path": new URL(url).pathname
}
},
action: method,
environment: environment
action: method as string,
}
const encodedPolicy = PolicyRequest.create(policyConfig);
const encodedPolicy = await this.create(policyConfig);
return {
[headerKey]: encodedPolicy,
};
......@@ -190,35 +259,6 @@ export class PolicyRequest {
return true;
}
/**
* Create policy request with validation
* @param config - Policy configuration object
* @returns Base64 encoded string
* @throws Error if validation fails
*/
static createSafe(config: PolicyConfig = {}): string {
const data: PolicyRequestData = {
subject: config.subject || {},
resource: {
type: config.resource?.type || '',
name: config.resource?.name || '',
param: {
path: config.resource?.param?.path || '',
...config.resource?.param,
},
...config.resource,
},
action: config.action || '',
environment: config.environment || {},
};
if (!PolicyRequest.validate(data)) {
throw new Error('Invalid policy request data');
}
const jsonString = JSON.stringify(data);
return base64Encode(jsonString);
}
}
// Default export
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment