Merged in development (pull request #3)

Development
This commit is contained in:
Leandro Costa 2023-06-15 17:38:35 +00:00
commit 34ac3a28da
6 changed files with 4654 additions and 824 deletions

3
.prettierrc.json Normal file
View file

@ -0,0 +1,3 @@
{
"printWidth": 120
}

4
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,4 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
}

3786
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{ {
"name": "lhisp-oauth-client", "name": "lhisp-oauth-client",
"version": "1.0.6", "version": "1.0.7",
"main": "src/index", "main": "src/index",
"types": "src/index.d.ts", "types": "src/index.d.ts",
"repository": "git@bitbucket.org:leandro_costa/lhisp-oauth-client.git", "repository": "git@bitbucket.org:leandro_costa/lhisp-oauth-client.git",
@ -12,13 +12,13 @@
"test:watch": "jest --watchAll" "test:watch": "jest --watchAll"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.4.0", "@types/jest": "^29.5.2",
"@types/node": "^18.11.18", "@types/node": "^20.3.1",
"jest": "^29.4.1", "jest": "^29.5.0",
"ts-jest": "^29.0.5", "ts-jest": "^29.1.0",
"typescript": "^4.9.4" "typescript": "^5.1.3"
}, },
"dependencies": { "dependencies": {
"axios": "^1.2.5" "axios": "^1.4.0"
} }
} }

View file

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

1350
yarn.lock

File diff suppressed because it is too large Load diff