feat: adiciona generics para o response type

This commit is contained in:
Leandro Costa 2023-03-27 20:49:33 -03:00
parent 13b8b2903d
commit 5c2137fb9d

View file

@ -1,164 +1,195 @@
import qs from 'querystring'; import qs from "querystring";
import https from 'https'; import https from "https";
import axios, { AxiosRequestConfig } from 'axios'; import axios, { AxiosRequestConfig } from "axios";
import { import {
AccessToken, ContentType, defaultAuthContentType, AccessToken,
defaultAuthHeaderName, ContentType,
defaultGrantType, defaultAuthContentType,
defaultTokenHeaderName, defaultAuthHeaderName,
ExecutarRequestParams, defaultGrantType,
LhispOauthClientConstructorParams, defaultTokenHeaderName,
ExecutarRequestParams,
LhispOauthClientConstructorParams,
} from "./lhisp-oauth-client.t"; } from "./lhisp-oauth-client.t";
export class LhispOauthClient { export class LhispOauthClient {
protected authUrl: string; protected authUrl: string;
protected apiUrl: string; protected apiUrl: string;
protected clientId: string; protected clientId: string;
protected clientSecret: string; protected clientSecret: string;
protected authHeaderName: string; protected authHeaderName: string;
protected tokenHeaderName: string; protected tokenHeaderName: string;
protected authContentType: ContentType; protected authContentType: ContentType;
protected certificado?: string; protected certificado?: string;
protected senhaCertificado?: string; protected senhaCertificado?: string;
protected authScope?: string; protected authScope?: string;
protected headers?: Headers; protected headers?: Headers;
protected grantType?: string; protected grantType?: string;
protected agent: https.Agent; protected agent: https.Agent;
protected accessToken?: AccessToken; protected accessToken?: AccessToken;
protected refreshToken?: AccessToken; protected refreshToken?: AccessToken;
protected sendAuthCredentialsOnRequestBody?: boolean; protected sendAuthCredentialsOnRequestBody?: boolean;
constructor(params: LhispOauthClientConstructorParams) { constructor(params: LhispOauthClientConstructorParams) {
if (params.certificado) { if (params.certificado) {
this.agent = new https.Agent({ this.agent = new https.Agent({
pfx: params.certificado, pfx: params.certificado,
passphrase: params.senhaCertificado, passphrase: params.senhaCertificado,
rejectUnauthorized: false, rejectUnauthorized: false,
}); });
} else { } else {
this.agent = new https.Agent({ this.agent = new https.Agent({
rejectUnauthorized: false rejectUnauthorized: false,
}); });
}
this.certificado = params.certificado;
this.headers = (params.headers ? params.headers : {}) as any as Headers;
this.apiUrl = params.apiUrl;
this.authUrl = params.authUrl;
this.authScope = params.authScope;
this.grantType = params.grantType || defaultGrantType;
this.authContentType = params.authContentType || defaultAuthContentType;
this.clientId = params.clientId;
this.clientSecret = params.clientSecret;
this.authHeaderName = params.authHeaderName || defaultAuthHeaderName;
this.tokenHeaderName = params.tokenHeaderName || defaultTokenHeaderName;
this.sendAuthCredentialsOnRequestBody = params.sendAuthCredentialsOnRequestBody;
} }
getAuthHeaderValue(): string { this.certificado = params.certificado;
return `Basic ${Buffer.from(`${this.clientId}:${this.clientSecret}`).toString("base64")}`; this.headers = (params.headers ? params.headers : {}) as any as Headers;
this.apiUrl = params.apiUrl;
this.authUrl = params.authUrl;
this.authScope = params.authScope;
this.grantType = params.grantType || defaultGrantType;
this.authContentType = params.authContentType || defaultAuthContentType;
this.clientId = params.clientId;
this.clientSecret = params.clientSecret;
this.authHeaderName = params.authHeaderName || defaultAuthHeaderName;
this.tokenHeaderName = params.tokenHeaderName || defaultTokenHeaderName;
this.sendAuthCredentialsOnRequestBody = params.sendAuthCredentialsOnRequestBody;
}
getAuthHeaderValue(): string {
return `Basic ${Buffer.from(`${this.clientId}:${this.clientSecret}`).toString("base64")}`;
}
parseData({ data, contentType = ContentType.APPLICATION_JSON }: { data: any; contentType: string }) {
if (!data || Object.keys(data).length === 0) return undefined;
switch (contentType) {
case ContentType.APPLICATION_JSON:
return JSON.stringify(data);
case ContentType.APPLICATION_X_WWW_FORM_URLENCODED:
return qs.stringify(data);
default:
throw new Error(`Content Type Inválido: [${contentType}]`);
}
}
isTokenValid(token: AccessToken) {
if (!token) return false;
if (!token.created_at) return false;
const timeDiff = (Date.now() - token.created_at) / 1000;
return timeDiff < token.expires_in - 10;
}
async getAccessToken(): Promise<AccessToken> {
if (this.accessToken && this.isTokenValid(this.accessToken)) {
return this.accessToken;
} }
parseData({ data, contentType = ContentType.APPLICATION_JSON }: { data: any, contentType: string }) { // TODO: Implementar Refresh Token.
if(!data || Object.keys(data).length===0) return undefined;
switch (contentType) { let authRequestOpt: AxiosRequestConfig = {
case ContentType.APPLICATION_JSON: return JSON.stringify(data); method: "POST",
case ContentType.APPLICATION_X_WWW_FORM_URLENCODED: return qs.stringify(data); url: this.authUrl,
default: httpsAgent: this.agent,
throw new Error(`Content Type Inválido: [${contentType}]`); headers: {
} [this.authHeaderName]: this.getAuthHeaderValue(),
"Content-Type": this.authContentType,
},
data: {},
};
if (this.grantType) authRequestOpt.data.grant_type = this.grantType;
if (this.authScope) authRequestOpt.data.scope = this.authScope;
if (this.sendAuthCredentialsOnRequestBody) {
if (this.clientId) authRequestOpt.data.client_id = this.clientId;
if (this.clientSecret) authRequestOpt.data.client_secret = this.clientSecret;
} }
isTokenValid(token: AccessToken){ authRequestOpt.data = this.parseData({
if(!token) return false; data: authRequestOpt.data,
if(!token.created_at) return false; contentType: this.authContentType,
const timeDiff = (Date.now() - token.created_at) / 1000; });
return timeDiff < token.expires_in - 10; const response = await axios.request(authRequestOpt);
return this.buildAccessToken(response.data);
}
buildAccessToken(data: Omit<AccessToken, "created_at">): AccessToken {
this.accessToken = {
...data,
created_at: Date.now(),
};
return this.accessToken;
}
getAuthToken() {
return `${this.accessToken?.token_type} ${this.accessToken?.access_token}`;
}
async executarRequest<ResponseType>({
method,
path,
data,
params,
contentType = ContentType.APPLICATION_JSON,
}: ExecutarRequestParams): Promise<ResponseType> {
await this.getAccessToken();
if (!this.accessToken?.token_type) {
console.log("## LHOAUTH2 NO TOKEN ?:", this.accessToken);
} }
async getAccessToken() : Promise<AccessToken> { let headers = {
if(this.accessToken && this.isTokenValid(this.accessToken)) { "Content-Type": contentType,
return this.accessToken; [this.tokenHeaderName]: this.getAuthToken(),
} // ...this.headers
};
// TODO: Implementar Refresh Token. const response = await axios.request<ResponseType>({
method,
url: `${this.apiUrl}${path}`,
httpsAgent: this.agent,
headers,
data,
params,
});
let authRequestOpt: AxiosRequestConfig = { return response.data;
method: 'POST', }
url: this.authUrl,
httpsAgent: this.agent,
headers: {
[this.authHeaderName]: this.getAuthHeaderValue(),
'Content-Type': this.authContentType,
},
data: {},
}
if(this.grantType) authRequestOpt.data.grant_type = this.grantType; async get<ResponseType>({ path, contentType = ContentType.APPLICATION_JSON, params }: ExecutarRequestParams) {
if(this.authScope) authRequestOpt.data.scope = this.authScope; return this.executarRequest<ResponseType>({
method: "GET",
path,
contentType,
params,
});
}
if(this.sendAuthCredentialsOnRequestBody) { async put<ResponseType>({ path, data, contentType = ContentType.APPLICATION_JSON }: ExecutarRequestParams) {
if(this.clientId) authRequestOpt.data.client_id = this.clientId; return this.executarRequest<ResponseType>({
if(this.clientSecret) authRequestOpt.data.client_secret = this.clientSecret; method: "PUT",
} path,
data,
contentType,
});
}
authRequestOpt.data = this.parseData({ data: authRequestOpt.data, contentType: this.authContentType }); async post<ResponseType>({ path, data, contentType = ContentType.APPLICATION_JSON }: ExecutarRequestParams) {
const response = await axios.request(authRequestOpt); return this.executarRequest<ResponseType>({
return this.buildAccessToken(response.data); method: "POST",
} path,
data,
contentType,
});
}
buildAccessToken(data: Omit<AccessToken,'created_at'>): AccessToken{ async delete<ResponseType>({ path, contentType = ContentType.APPLICATION_JSON }: ExecutarRequestParams) {
this.accessToken = { return this.executarRequest<ResponseType>({
...data, method: "DELETE",
created_at: Date.now() path,
}; contentType,
});
return this.accessToken; }
} }
getAuthToken(){
return `${this.accessToken?.token_type} ${this.accessToken?.access_token}`;
}
async executarRequest({ method, path, data, params, contentType = ContentType.APPLICATION_JSON } : ExecutarRequestParams) {
await this.getAccessToken();
if (!this.accessToken?.token_type) {
console.log("## LHOAUTH2 NO TOKEN ?:", this.accessToken);
}
let headers = {
'Content-Type': contentType,
[this.tokenHeaderName]: this.getAuthToken(),
// ...this.headers
};
const response = await axios.request({
method,
url: `${this.apiUrl}${path}`,
httpsAgent: this.agent,
headers,
data,
params
});
return response.data;
}
async get({ path, contentType = ContentType.APPLICATION_JSON, params }: ExecutarRequestParams) {
return this.executarRequest({ method: 'GET', path, contentType, params });
}
async put({ path, data, contentType = ContentType.APPLICATION_JSON }: ExecutarRequestParams) {
return this.executarRequest({ method: 'PUT', path, data, contentType });
}
async post({ path, data, contentType = ContentType.APPLICATION_JSON }: ExecutarRequestParams) {
return this.executarRequest({ method: 'POST', path, data, contentType });
}
async delete({ path, contentType = ContentType.APPLICATION_JSON }: ExecutarRequestParams) {
return this.executarRequest({ method: 'DELETE', path, contentType });
}
}