@lightdash/common 0.1832.0 → 0.1834.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/auth.d.ts +3 -1
- package/dist/cjs/types/auth.d.ts.map +1 -1
- package/dist/cjs/types/auth.js +2 -0
- package/dist/cjs/types/auth.js.map +1 -1
- package/dist/cjs/types/errors.d.ts +5 -0
- package/dist/cjs/types/errors.d.ts.map +1 -1
- package/dist/cjs/types/errors.js +12 -1
- package/dist/cjs/types/errors.js.map +1 -1
- package/dist/cjs/types/oauth.d.ts +104 -0
- package/dist/cjs/types/oauth.d.ts.map +1 -0
- package/dist/cjs/types/oauth.js +3 -0
- package/dist/cjs/types/oauth.js.map +1 -0
- package/dist/cjs/utils/oauth.d.ts +44 -0
- package/dist/cjs/utils/oauth.d.ts.map +1 -0
- package/dist/cjs/utils/oauth.js +193 -0
- package/dist/cjs/utils/oauth.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/auth.d.ts +3 -1
- package/dist/esm/types/auth.d.ts.map +1 -1
- package/dist/esm/types/auth.js +2 -0
- package/dist/esm/types/auth.js.map +1 -1
- package/dist/esm/types/errors.d.ts +5 -0
- package/dist/esm/types/errors.d.ts.map +1 -1
- package/dist/esm/types/errors.js +10 -0
- package/dist/esm/types/errors.js.map +1 -1
- package/dist/esm/types/oauth.d.ts +104 -0
- package/dist/esm/types/oauth.d.ts.map +1 -0
- package/dist/esm/types/oauth.js +2 -0
- package/dist/esm/types/oauth.js.map +1 -0
- package/dist/esm/utils/oauth.d.ts +44 -0
- package/dist/esm/utils/oauth.d.ts.map +1 -0
- package/dist/esm/utils/oauth.js +186 -0
- package/dist/esm/utils/oauth.js.map +1 -0
- package/dist/tsconfig.types.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types/auth.d.ts +3 -1
- package/dist/types/types/auth.d.ts.map +1 -1
- package/dist/types/types/errors.d.ts +5 -0
- package/dist/types/types/errors.d.ts.map +1 -1
- package/dist/types/types/oauth.d.ts +104 -0
- package/dist/types/types/oauth.d.ts.map +1 -0
- package/dist/types/utils/oauth.d.ts +44 -0
- package/dist/types/utils/oauth.d.ts.map +1 -0
- package/package.json +3 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export interface OAuthClient {
|
|
2
|
+
clientUuid: string;
|
|
3
|
+
clientId: string;
|
|
4
|
+
clientSecret: string | undefined;
|
|
5
|
+
clientName: string;
|
|
6
|
+
redirectUris: string[];
|
|
7
|
+
grants: string[];
|
|
8
|
+
scopes: string[] | null;
|
|
9
|
+
createdAt: Date;
|
|
10
|
+
createdByUserUuid: string | null;
|
|
11
|
+
expiresAt: Date | null;
|
|
12
|
+
}
|
|
13
|
+
export interface OAuthAuthorizationCode {
|
|
14
|
+
authorizationCodeUuid: string;
|
|
15
|
+
authorizationCode: string;
|
|
16
|
+
expiresAt: Date;
|
|
17
|
+
redirectUri: string;
|
|
18
|
+
scopes: string[];
|
|
19
|
+
userUuid: string;
|
|
20
|
+
organizationUuid: string;
|
|
21
|
+
createdAt: Date;
|
|
22
|
+
usedAt: Date | null;
|
|
23
|
+
codeChallenge: string | null;
|
|
24
|
+
codeChallengeMethod: 'S256' | 'plain' | null;
|
|
25
|
+
}
|
|
26
|
+
export interface OAuthAccessToken {
|
|
27
|
+
accessTokenUuid: string;
|
|
28
|
+
accessToken: string;
|
|
29
|
+
expiresAt: Date;
|
|
30
|
+
scopes: string[];
|
|
31
|
+
userUuid: string;
|
|
32
|
+
organizationUuid: string;
|
|
33
|
+
createdAt: Date;
|
|
34
|
+
lastUsedAt: Date | null;
|
|
35
|
+
revokedAt: Date | null;
|
|
36
|
+
authorizationCodeUuid: string | null;
|
|
37
|
+
}
|
|
38
|
+
export interface OAuthRefreshToken {
|
|
39
|
+
refreshTokenUuid: string;
|
|
40
|
+
refreshToken: string;
|
|
41
|
+
expiresAt: Date;
|
|
42
|
+
scopes: string[];
|
|
43
|
+
userUuid: string;
|
|
44
|
+
organizationUuid: string;
|
|
45
|
+
createdAt: Date;
|
|
46
|
+
lastUsedAt: Date | null;
|
|
47
|
+
revokedAt: Date | null;
|
|
48
|
+
accessTokenUuid: string;
|
|
49
|
+
}
|
|
50
|
+
export interface OAuthTokenRequest {
|
|
51
|
+
grant_type: 'authorization_code' | 'refresh_token' | 'client_credentials';
|
|
52
|
+
code?: string;
|
|
53
|
+
refresh_token?: string;
|
|
54
|
+
redirect_uri?: string;
|
|
55
|
+
client_id: string;
|
|
56
|
+
client_secret: string;
|
|
57
|
+
scope?: string;
|
|
58
|
+
code_verifier?: string;
|
|
59
|
+
}
|
|
60
|
+
export interface OAuthAuthorizationRequest {
|
|
61
|
+
response_type: 'code';
|
|
62
|
+
client_id: string;
|
|
63
|
+
redirect_uri: string;
|
|
64
|
+
scope?: string;
|
|
65
|
+
state?: string;
|
|
66
|
+
code_challenge?: string;
|
|
67
|
+
code_challenge_method?: 'S256' | 'plain';
|
|
68
|
+
}
|
|
69
|
+
export interface OAuthTokenResponse {
|
|
70
|
+
access_token: string;
|
|
71
|
+
token_type: 'Bearer';
|
|
72
|
+
expires_in: number;
|
|
73
|
+
refresh_token?: string;
|
|
74
|
+
scope?: string;
|
|
75
|
+
}
|
|
76
|
+
export interface OAuthIntrospectRequest {
|
|
77
|
+
token: string;
|
|
78
|
+
token_type_hint?: 'access_token' | 'refresh_token';
|
|
79
|
+
client_id?: string;
|
|
80
|
+
client_secret?: string;
|
|
81
|
+
}
|
|
82
|
+
export interface OAuthIntrospectResponse {
|
|
83
|
+
active: boolean;
|
|
84
|
+
scope?: string;
|
|
85
|
+
client_id?: string;
|
|
86
|
+
username?: string;
|
|
87
|
+
token_type?: string;
|
|
88
|
+
exp?: number;
|
|
89
|
+
iat?: number;
|
|
90
|
+
nbf?: number;
|
|
91
|
+
sub?: string;
|
|
92
|
+
aud?: string;
|
|
93
|
+
iss?: string;
|
|
94
|
+
jti?: string;
|
|
95
|
+
}
|
|
96
|
+
export interface OAuthRevokeRequest {
|
|
97
|
+
token: string;
|
|
98
|
+
token_type_hint?: 'access_token' | 'refresh_token';
|
|
99
|
+
}
|
|
100
|
+
export type UserWithOrganizationUuid = {
|
|
101
|
+
userId: number;
|
|
102
|
+
organizationUuid: string;
|
|
103
|
+
};
|
|
104
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../src/types/oauth.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACnC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,mBAAmB,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,gBAAgB;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB;IAC9B,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAC9B,UAAU,EAAE,oBAAoB,GAAG,eAAe,GAAG,oBAAoB,CAAC;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,yBAAyB;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5C;AAED,MAAM,WAAW,kBAAkB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,QAAQ,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,cAAc,GAAG,eAAe,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,cAAc,GAAG,eAAe,CAAC;CACtD;AAED,MAAM,MAAM,wBAAwB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;CAC5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/types/oauth.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare const oauthPageStyles = "\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Open Sans', 'Helvetica Neue', sans-serif;\n background-color: #f8fafc;\n margin: 0;\n padding: 0;\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n line-height: 1.4;\n }\n .container {\n background: white;\n border-radius: 4px;\n border: 1px solid #e9ecef;\n box-shadow: 0px 1px 2px 0px rgba(10, 13, 18, 0.05);\n padding: 24px;\n max-width: 400px;\n width: 90%;\n text-align: center;\n }\n h1 {\n color: #111418;\n margin: 0 0 16px 0;\n font-size: 20px;\n font-weight: 600;\n text-align: center;\n }\n p {\n color: #6c757d;\n margin: 0 0 12px 0;\n line-height: 1.4;\n font-size: 14px;\n }\n .success h1 {\n color: #10b981;\n }\n .error h1 {\n color: #ef4444;\n }\n .icon {\n width: 32px;\n height: 32px;\n margin: 0 auto 16px auto;\n display: block;\n }\n .success .icon {\n color: #10b981;\n }\n .error .icon {\n color: #ef4444;\n }\n .stack {\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n";
|
|
2
|
+
declare const OAUTH_ICONS: {
|
|
3
|
+
readonly success: "<circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/><path d=\"M9 12l2 2 4-4\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>";
|
|
4
|
+
readonly error: "<circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/><path d=\"M15 9l-6 6M9 9l6 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>";
|
|
5
|
+
readonly sessionExpired: "<circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/><path d=\"M12 6v6l4 2\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>";
|
|
6
|
+
};
|
|
7
|
+
export type OAuthResponseStatus = 'success' | 'error';
|
|
8
|
+
export type OAuthIconType = keyof typeof OAUTH_ICONS;
|
|
9
|
+
export interface OAuthHiddenInput {
|
|
10
|
+
name: string;
|
|
11
|
+
value: string;
|
|
12
|
+
}
|
|
13
|
+
export interface OAuthUser {
|
|
14
|
+
firstName: string;
|
|
15
|
+
lastName: string;
|
|
16
|
+
organizationName: string;
|
|
17
|
+
}
|
|
18
|
+
export interface OAuthAuthorizeParams {
|
|
19
|
+
action: string;
|
|
20
|
+
client_id: string;
|
|
21
|
+
scope: string;
|
|
22
|
+
user: OAuthUser;
|
|
23
|
+
hiddenInputs: OAuthHiddenInput[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generates an OAuth response HTML page using Handlebars templating
|
|
27
|
+
* This prevents XSS issues by auto-escaping content while still allowing safe HTML in icons and styles
|
|
28
|
+
*/
|
|
29
|
+
export declare const generateOAuthResponseHtml: (status: OAuthResponseStatus, title: string, messages: string[], iconType?: OAuthIconType) => string;
|
|
30
|
+
/**
|
|
31
|
+
* Generates a success OAuth response
|
|
32
|
+
*/
|
|
33
|
+
export declare const generateOAuthSuccessResponse: (title?: string, messages?: string[]) => string;
|
|
34
|
+
/**
|
|
35
|
+
* Generates an error OAuth response
|
|
36
|
+
*/
|
|
37
|
+
export declare const generateOAuthErrorResponse: (title: string, messages: string[], iconType?: OAuthIconType) => string;
|
|
38
|
+
/**
|
|
39
|
+
* Generates an OAuth authorization page HTML using Handlebars templating
|
|
40
|
+
* This prevents XSS issues by auto-escaping all user content
|
|
41
|
+
*/
|
|
42
|
+
export declare const generateOAuthAuthorizePage: (params: OAuthAuthorizeParams) => string;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../src/utils/oauth.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,u5CA2D3B,CAAC;AA0FF,QAAA,MAAM,WAAW;;;;CAMP,CAAC;AAMX,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,CAAC;AACtD,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,WAAW,CAAC;AAGrD,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,YAAY,EAAE,gBAAgB,EAAE,CAAC;CACpC;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,WAC1B,mBAAmB,SACpB,MAAM,YACH,MAAM,EAAE,aACR,aAAa,KACxB,MAOG,CAAC;AAEP;;GAEG;AACH,eAAO,MAAM,4BAA4B,WAC9B,MAAM,aACH,MAAM,EAAE,KAInB,MAA0E,CAAC;AAE9E;;GAEG;AACH,eAAO,MAAM,0BAA0B,UAC5B,MAAM,YACH,MAAM,EAAE,aACR,aAAa,KACxB,MAME,CAAC;AAEN;;;GAGG;AACH,eAAO,MAAM,0BAA0B,WAC3B,oBAAoB,KAC7B,MAIG,CAAC"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { compile } from 'handlebars';
|
|
2
|
+
export const oauthPageStyles = `
|
|
3
|
+
body {
|
|
4
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
5
|
+
background-color: #f8fafc;
|
|
6
|
+
margin: 0;
|
|
7
|
+
padding: 0;
|
|
8
|
+
min-height: 100vh;
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
justify-content: center;
|
|
12
|
+
font-size: 14px;
|
|
13
|
+
line-height: 1.4;
|
|
14
|
+
}
|
|
15
|
+
.container {
|
|
16
|
+
background: white;
|
|
17
|
+
border-radius: 4px;
|
|
18
|
+
border: 1px solid #e9ecef;
|
|
19
|
+
box-shadow: 0px 1px 2px 0px rgba(10, 13, 18, 0.05);
|
|
20
|
+
padding: 24px;
|
|
21
|
+
max-width: 400px;
|
|
22
|
+
width: 90%;
|
|
23
|
+
text-align: center;
|
|
24
|
+
}
|
|
25
|
+
h1 {
|
|
26
|
+
color: #111418;
|
|
27
|
+
margin: 0 0 16px 0;
|
|
28
|
+
font-size: 20px;
|
|
29
|
+
font-weight: 600;
|
|
30
|
+
text-align: center;
|
|
31
|
+
}
|
|
32
|
+
p {
|
|
33
|
+
color: #6c757d;
|
|
34
|
+
margin: 0 0 12px 0;
|
|
35
|
+
line-height: 1.4;
|
|
36
|
+
font-size: 14px;
|
|
37
|
+
}
|
|
38
|
+
.success h1 {
|
|
39
|
+
color: #10b981;
|
|
40
|
+
}
|
|
41
|
+
.error h1 {
|
|
42
|
+
color: #ef4444;
|
|
43
|
+
}
|
|
44
|
+
.icon {
|
|
45
|
+
width: 32px;
|
|
46
|
+
height: 32px;
|
|
47
|
+
margin: 0 auto 16px auto;
|
|
48
|
+
display: block;
|
|
49
|
+
}
|
|
50
|
+
.success .icon {
|
|
51
|
+
color: #10b981;
|
|
52
|
+
}
|
|
53
|
+
.error .icon {
|
|
54
|
+
color: #ef4444;
|
|
55
|
+
}
|
|
56
|
+
.stack {
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
gap: 16px;
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
// OAuth response HTML template
|
|
63
|
+
const OAUTH_RESPONSE_TEMPLATE = `
|
|
64
|
+
<html>
|
|
65
|
+
<head>
|
|
66
|
+
<style>{{{styles}}}</style>
|
|
67
|
+
</head>
|
|
68
|
+
<body>
|
|
69
|
+
<div class="stack">
|
|
70
|
+
<div class="container {{status}}">
|
|
71
|
+
<svg class="icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
72
|
+
{{{icon}}}
|
|
73
|
+
</svg>
|
|
74
|
+
<h1>{{title}}</h1>
|
|
75
|
+
{{#each messages}}
|
|
76
|
+
<p>{{this}}</p>
|
|
77
|
+
{{/each}}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</body>
|
|
81
|
+
</html>
|
|
82
|
+
`;
|
|
83
|
+
// OAuth authorization page template
|
|
84
|
+
const OAUTH_AUTHORIZE_TEMPLATE = `
|
|
85
|
+
<html>
|
|
86
|
+
<head>
|
|
87
|
+
<title>Authorize Application</title>
|
|
88
|
+
<style>
|
|
89
|
+
{{{styles}}}
|
|
90
|
+
.container, .container p, .container strong, .container form { text-align: center; }
|
|
91
|
+
.container p { margin-left: auto; margin-right: auto; }
|
|
92
|
+
.oauth-desc { margin-bottom: 18px; color: #374151; font-size: 12px; }
|
|
93
|
+
.oauth-btn-row { display: flex; justify-content: center; gap: 12px; margin-top: 18px; }
|
|
94
|
+
.oauth-btn {
|
|
95
|
+
padding: 8px 24px;
|
|
96
|
+
border: none;
|
|
97
|
+
border-radius: 4px;
|
|
98
|
+
font-weight: 600;
|
|
99
|
+
font-size: 15px;
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
transition: background 0.15s;
|
|
102
|
+
}
|
|
103
|
+
.oauth-btn.approve {
|
|
104
|
+
background: #00B26F;
|
|
105
|
+
color: #fff;
|
|
106
|
+
}
|
|
107
|
+
.oauth-btn.approve:hover {
|
|
108
|
+
background: #00975E;
|
|
109
|
+
}
|
|
110
|
+
.oauth-btn.deny {
|
|
111
|
+
background: #E03131;
|
|
112
|
+
color: #fff;
|
|
113
|
+
}
|
|
114
|
+
.oauth-btn.deny:hover {
|
|
115
|
+
background: #B32525;
|
|
116
|
+
}
|
|
117
|
+
</style>
|
|
118
|
+
</head>
|
|
119
|
+
<body>
|
|
120
|
+
<div class="stack">
|
|
121
|
+
<form class="container" method="POST" action="{{action}}">
|
|
122
|
+
<h1>Authorize Application</h1>
|
|
123
|
+
<p class="oauth-desc">
|
|
124
|
+
You are about to grant access to your Lightdash account using OAuth.<br/>
|
|
125
|
+
This is a secure way to let trusted applications access your account without sharing your password.<br/>
|
|
126
|
+
Approving will allow the client below to perform actions on your behalf, according to the requested permissions.
|
|
127
|
+
</p>
|
|
128
|
+
<p>Client: <b>{{client_id}}</b></p>
|
|
129
|
+
<p>Scope: <b>{{scope}}</b></p>
|
|
130
|
+
|
|
131
|
+
{{#each hiddenInputs}}
|
|
132
|
+
<input type="hidden" name="{{name}}" value="{{value}}" />
|
|
133
|
+
{{/each}}
|
|
134
|
+
|
|
135
|
+
<p>Authenticate as user: <b>{{user.firstName}} {{user.lastName}}</b></p>
|
|
136
|
+
<p>on organization: <b>{{user.organizationName}}</b></p>
|
|
137
|
+
|
|
138
|
+
<div class="oauth-btn-row">
|
|
139
|
+
<button type="submit" name="approve" value="true" class="oauth-btn approve">Approve</button>
|
|
140
|
+
<button type="submit" name="approve" value="false" class="oauth-btn deny">Deny</button>
|
|
141
|
+
</div>
|
|
142
|
+
</form>
|
|
143
|
+
</div>
|
|
144
|
+
</body>
|
|
145
|
+
</html>
|
|
146
|
+
`;
|
|
147
|
+
// SVG icons for different response types
|
|
148
|
+
const OAUTH_ICONS = {
|
|
149
|
+
success: '<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/><path d="M9 12l2 2 4-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
150
|
+
error: '<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/><path d="M15 9l-6 6M9 9l6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
151
|
+
sessionExpired: '<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/><path d="M12 6v6l4 2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
152
|
+
};
|
|
153
|
+
// Compile the templates once with proper type safety
|
|
154
|
+
const compiledResponseTemplate = compile(OAUTH_RESPONSE_TEMPLATE);
|
|
155
|
+
const compiledAuthorizeTemplate = compile(OAUTH_AUTHORIZE_TEMPLATE);
|
|
156
|
+
/**
|
|
157
|
+
* Generates an OAuth response HTML page using Handlebars templating
|
|
158
|
+
* This prevents XSS issues by auto-escaping content while still allowing safe HTML in icons and styles
|
|
159
|
+
*/
|
|
160
|
+
export const generateOAuthResponseHtml = (status, title, messages, iconType = status === 'success' ? 'success' : 'error') => compiledResponseTemplate({
|
|
161
|
+
styles: oauthPageStyles,
|
|
162
|
+
status,
|
|
163
|
+
title,
|
|
164
|
+
messages,
|
|
165
|
+
icon: OAUTH_ICONS[iconType],
|
|
166
|
+
});
|
|
167
|
+
/**
|
|
168
|
+
* Generates a success OAuth response
|
|
169
|
+
*/
|
|
170
|
+
export const generateOAuthSuccessResponse = (title = 'Authentication Successful!', messages = [
|
|
171
|
+
'You have been successfully authenticated with Lightdash.',
|
|
172
|
+
'You can close this window and return to the CLI.',
|
|
173
|
+
]) => generateOAuthResponseHtml('success', title, messages, 'success');
|
|
174
|
+
/**
|
|
175
|
+
* Generates an error OAuth response
|
|
176
|
+
*/
|
|
177
|
+
export const generateOAuthErrorResponse = (title, messages, iconType = 'error') => generateOAuthResponseHtml('error', title, [...messages, 'You can close this window and try again.'], iconType);
|
|
178
|
+
/**
|
|
179
|
+
* Generates an OAuth authorization page HTML using Handlebars templating
|
|
180
|
+
* This prevents XSS issues by auto-escaping all user content
|
|
181
|
+
*/
|
|
182
|
+
export const generateOAuthAuthorizePage = (params) => compiledAuthorizeTemplate({
|
|
183
|
+
styles: oauthPageStyles,
|
|
184
|
+
...params,
|
|
185
|
+
});
|
|
186
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/utils/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2D9B,CAAC;AAEF,+BAA+B;AAC/B,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;CAmB/B,CAAC;AAEF,oCAAoC;AACpC,MAAM,wBAAwB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8DhC,CAAC;AAEF,yCAAyC;AACzC,MAAM,WAAW,GAAG;IAChB,OAAO,EACH,wLAAwL;IAC5L,KAAK,EAAE,6LAA6L;IACpM,cAAc,EACV,sLAAsL;CACpL,CAAC;AAEX,qDAAqD;AACrD,MAAM,wBAAwB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAClE,MAAM,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;AAyBpE;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACrC,MAA2B,EAC3B,KAAa,EACb,QAAkB,EAClB,WAA0B,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAC9D,EAAE,CACR,wBAAwB,CAAC;IACrB,MAAM,EAAE,eAAe;IACvB,MAAM;IACN,KAAK;IACL,QAAQ;IACR,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC;CAC9B,CAAC,CAAC;AAEP;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CACxC,QAAgB,4BAA4B,EAC5C,WAAqB;IACjB,0DAA0D;IAC1D,kDAAkD;CACrD,EACK,EAAE,CAAC,yBAAyB,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;AAE9E;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACtC,KAAa,EACb,QAAkB,EAClB,WAA0B,OAAO,EAC3B,EAAE,CACR,yBAAyB,CACrB,OAAO,EACP,KAAK,EACL,CAAC,GAAG,QAAQ,EAAE,0CAA0C,CAAC,EACzD,QAAQ,CACX,CAAC;AAEN;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACtC,MAA4B,EACtB,EAAE,CACR,yBAAyB,CAAC;IACtB,MAAM,EAAE,eAAe;IACvB,GAAG,MAAM;CACZ,CAAC,CAAC"}
|