Skip to content

Commit 7c4a863

Browse files
Fir 28094 support both versions (#66)
1 parent 02af0ed commit 7c4a863

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+3334
-465
lines changed

package-lock.json

Lines changed: 41 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"eslint-plugin-prettier": "^4.0.0",
3333
"jest": "^27.5.1",
3434
"msw": "^0.45.0",
35+
"nock": "^13.4.0",
3536
"prettier": "^2.4.1",
3637
"standard-version": "^9.3.2",
3738
"ts-jest": "^27.0.7",

src/auth/index.ts

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { SERVICE_ACCOUNT_LOGIN } from "../common/api";
1+
import { SERVICE_ACCOUNT_LOGIN, USERNAME_PASSWORD_LOGIN } from "../common/api";
22
import { assignProtocol } from "../common/util";
33
import {
44
Context,
55
ConnectionOptions,
6-
ClientCredentialsAuth,
7-
AccessTokenAuth
6+
ServiceAccountAuth,
7+
UsernamePasswordAuth
88
} from "../types";
99

1010
type Login = {
@@ -21,7 +21,6 @@ export class Authenticator {
2121
options: ConnectionOptions;
2222

2323
accessToken?: string;
24-
refreshToken?: string;
2524

2625
constructor(context: Context, options: ConnectionOptions) {
2726
context.httpClient.authenticator = this;
@@ -38,12 +37,7 @@ export class Authenticator {
3837
return {};
3938
}
4039

41-
authenticateWithToken(auth: AccessTokenAuth) {
42-
const { accessToken } = auth;
43-
this.accessToken = accessToken;
44-
}
45-
46-
getAuthEndpoint(apiEndpoint: string) {
40+
private static getAuthEndpoint(apiEndpoint: string) {
4741
const myURL = new URL(assignProtocol(apiEndpoint));
4842
const hostStrings = myURL.hostname.split(".");
4943
// We expect an apiEndpoint to be of format api.<env>.firebolt.io
@@ -56,11 +50,32 @@ export class Authenticator {
5650
return myURL.toString();
5751
}
5852

59-
async authenticateServiceAccount(auth: ClientCredentialsAuth) {
53+
private async authenticateUsernamePassword(auth: UsernamePasswordAuth) {
54+
const { httpClient, apiEndpoint } = this.context;
55+
const { username, password } = auth;
56+
const url = `${apiEndpoint}/${USERNAME_PASSWORD_LOGIN}`;
57+
const body = JSON.stringify({
58+
username,
59+
password
60+
});
61+
62+
this.accessToken = undefined;
63+
64+
const { access_token } = await httpClient
65+
.request<Login>("POST", url, {
66+
body,
67+
retry: false
68+
})
69+
.ready();
70+
71+
this.accessToken = access_token;
72+
}
73+
74+
private async authenticateServiceAccount(auth: ServiceAccountAuth) {
6075
const { httpClient, apiEndpoint } = this.context;
6176
const { client_id, client_secret } = auth;
6277

63-
const authEndpoint = this.getAuthEndpoint(apiEndpoint);
78+
const authEndpoint = Authenticator.getAuthEndpoint(apiEndpoint);
6479
const params = new URLSearchParams({
6580
client_id,
6681
client_secret,
@@ -84,18 +99,30 @@ export class Authenticator {
8499
this.accessToken = access_token;
85100
}
86101

87-
async authenticate() {
102+
isUsernamePassword() {
88103
const options = this.options.auth || this.options;
104+
return !!(
105+
(options as UsernamePasswordAuth).username &&
106+
(options as UsernamePasswordAuth).password
107+
);
108+
}
89109

90-
if ((options as AccessTokenAuth).accessToken) {
91-
this.authenticateWithToken(options as AccessTokenAuth);
110+
isServiceAccount() {
111+
const options = this.options.auth || this.options;
112+
return !!(
113+
(options as ServiceAccountAuth).client_id &&
114+
(options as ServiceAccountAuth).client_secret
115+
);
116+
}
117+
118+
async authenticate() {
119+
const options = this.options.auth || this.options;
120+
if (this.isUsernamePassword()) {
121+
await this.authenticateUsernamePassword(options as UsernamePasswordAuth);
92122
return;
93123
}
94-
if (
95-
(options as ClientCredentialsAuth).client_id &&
96-
(options as ClientCredentialsAuth).client_secret
97-
) {
98-
await this.authenticateServiceAccount(options as ClientCredentialsAuth);
124+
if (this.isServiceAccount()) {
125+
await this.authenticateServiceAccount(options as ServiceAccountAuth);
99126
return;
100127
}
101128

src/common/api.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,62 @@ export const ACCOUNT_SYSTEM_ENGINE = (accountName: string) =>
55
`web/v3/account/${accountName}/engineUrl`;
66
export const ACCOUNT_ID_BY_NAME = (accountName: string) =>
77
`web/v3/account/${accountName}/resolve`;
8+
9+
// V1
10+
11+
export const USERNAME_PASSWORD_LOGIN = "auth/v1/login"; // legit:ignore-secrets
12+
13+
export const ACCOUNT = "iam/v2/account";
14+
export const ACCOUNT_BY_NAME = "iam/v2/accounts:getIdByName";
15+
16+
export const ACCOUNT_ENGINE = (accountId: string, engineId: string) =>
17+
`core/v1/accounts/${accountId}/engines/${engineId}`;
18+
19+
export const ACCOUNT_ENGINES = (accountId: string) =>
20+
`core/v1/accounts/${accountId}/engines`;
21+
22+
export const ACCOUNT_ENGINE_URL_BY_DATABASE_NAME = (accountId: string) =>
23+
ACCOUNT_ENGINES(accountId) + ":getURLByDatabaseName";
24+
25+
export const ACCOUNT_DATABASE = (accountId: string, databaseId: string) =>
26+
`core/v1/accounts/${accountId}/databases/${databaseId}`;
27+
28+
export const ACCOUNT_DATABASES = (accountId: string) =>
29+
`core/v1/accounts/${accountId}/databases`;
30+
31+
export const ACCOUNT_DATABASE_BINDING_URL = (
32+
accountId: string,
33+
databaseId: string,
34+
engineId: string
35+
) => ACCOUNT_DATABASE(accountId, databaseId) + `/bindings/${engineId}`;
36+
37+
export const ACCOUNT_ENGINE_START = (accountId: string, engineId: string) =>
38+
ACCOUNT_ENGINE(accountId, engineId) + ":start";
39+
export const ACCOUNT_ENGINE_RESTART = (accountId: string, engineId: string) =>
40+
ACCOUNT_ENGINE(accountId, engineId) + ":restart";
41+
export const ACCOUNT_ENGINE_STOP = (accountId: string, engineId: string) =>
42+
ACCOUNT_ENGINE(accountId, engineId) + ":stop";
43+
44+
export const REGIONS = "compute/v1/regions";
45+
export const ACCOUNT_INSTANCE_TYPES = (accountId: string) =>
46+
`aws/v2/accounts/${accountId}/instanceTypes`;
47+
48+
export const ACCOUNT_BINDINGS_URL = (accountId: string) =>
49+
`core/v1/accounts/${accountId}/bindings`;
50+
51+
export const ENGINES_BY_IDS_URL = "core/v1/engines:getByIds";
52+
53+
export type EdgeResult<T> = {
54+
cursor: string;
55+
node: T;
56+
};
57+
58+
export type ResultsPage<T> = {
59+
page: {
60+
page_size: number;
61+
total_size: number;
62+
has_previous_page: boolean;
63+
has_next_page: boolean;
64+
};
65+
edges: EdgeResult<T>[];
66+
};

0 commit comments

Comments
 (0)