@arch-cadre/auth-google 0.0.1
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/actions/auth.cjs +37 -0
- package/dist/actions/auth.d.ts +1 -0
- package/dist/actions/auth.mjs +39 -0
- package/dist/actions/settings.cjs +25 -0
- package/dist/actions/settings.d.ts +9 -0
- package/dist/actions/settings.mjs +20 -0
- package/dist/index.cjs +33 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +29 -0
- package/dist/intl.d.ts +9 -0
- package/dist/navigation.cjs +17 -0
- package/dist/navigation.d.ts +2 -0
- package/dist/navigation.mjs +13 -0
- package/dist/routes.cjs +73 -0
- package/dist/routes.d.ts +3 -0
- package/dist/routes.mjs +80 -0
- package/dist/ui/google-button.cjs +31 -0
- package/dist/ui/google-button.d.ts +2 -0
- package/dist/ui/google-button.mjs +34 -0
- package/dist/ui/settings-page.cjs +93 -0
- package/dist/ui/settings-page.d.ts +2 -0
- package/dist/ui/settings-page.mjs +78 -0
- package/locales/en/global.json +14 -0
- package/manifest.json +11 -0
- package/package.json +53 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use server";
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.loginWithGoogle = loginWithGoogle;
|
|
8
|
+
var _arctic = require("arctic");
|
|
9
|
+
var _headers = require("next/headers");
|
|
10
|
+
var _navigation = require("next/navigation");
|
|
11
|
+
var _settings = require("./settings.cjs");
|
|
12
|
+
async function loginWithGoogle() {
|
|
13
|
+
const config = await (0, _settings.getGoogleConfig)();
|
|
14
|
+
if (!config.clientId || !config.clientSecret) {
|
|
15
|
+
throw new Error("Google Auth is not configured. Please visit settings.");
|
|
16
|
+
}
|
|
17
|
+
const google = new _arctic.Google(config.clientId, config.clientSecret, config.redirectUri);
|
|
18
|
+
const state = (0, _arctic.generateState)();
|
|
19
|
+
const codeVerifier = (0, _arctic.generateCodeVerifier)();
|
|
20
|
+
const url = google.createAuthorizationURL(state, codeVerifier, ["openid", "profile", "email"]);
|
|
21
|
+
const cookieStore = await (0, _headers.cookies)();
|
|
22
|
+
cookieStore.set("google_oauth_state", state, {
|
|
23
|
+
path: "/",
|
|
24
|
+
secure: process.env.NODE_ENV === "production",
|
|
25
|
+
httpOnly: true,
|
|
26
|
+
maxAge: 60 * 10,
|
|
27
|
+
sameSite: "lax"
|
|
28
|
+
});
|
|
29
|
+
cookieStore.set("google_code_verifier", codeVerifier, {
|
|
30
|
+
path: "/",
|
|
31
|
+
secure: process.env.NODE_ENV === "production",
|
|
32
|
+
httpOnly: true,
|
|
33
|
+
maxAge: 60 * 10,
|
|
34
|
+
sameSite: "lax"
|
|
35
|
+
});
|
|
36
|
+
return (0, _navigation.redirect)(url.toString());
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function loginWithGoogle(): Promise<never>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { Google, generateCodeVerifier, generateState } from "arctic";
|
|
3
|
+
import { cookies } from "next/headers";
|
|
4
|
+
import { redirect } from "next/navigation";
|
|
5
|
+
import { getGoogleConfig } from "./settings.mjs";
|
|
6
|
+
export async function loginWithGoogle() {
|
|
7
|
+
const config = await getGoogleConfig();
|
|
8
|
+
if (!config.clientId || !config.clientSecret) {
|
|
9
|
+
throw new Error("Google Auth is not configured. Please visit settings.");
|
|
10
|
+
}
|
|
11
|
+
const google = new Google(
|
|
12
|
+
config.clientId,
|
|
13
|
+
config.clientSecret,
|
|
14
|
+
config.redirectUri
|
|
15
|
+
);
|
|
16
|
+
const state = generateState();
|
|
17
|
+
const codeVerifier = generateCodeVerifier();
|
|
18
|
+
const url = google.createAuthorizationURL(state, codeVerifier, [
|
|
19
|
+
"openid",
|
|
20
|
+
"profile",
|
|
21
|
+
"email"
|
|
22
|
+
]);
|
|
23
|
+
const cookieStore = await cookies();
|
|
24
|
+
cookieStore.set("google_oauth_state", state, {
|
|
25
|
+
path: "/",
|
|
26
|
+
secure: process.env.NODE_ENV === "production",
|
|
27
|
+
httpOnly: true,
|
|
28
|
+
maxAge: 60 * 10,
|
|
29
|
+
sameSite: "lax"
|
|
30
|
+
});
|
|
31
|
+
cookieStore.set("google_code_verifier", codeVerifier, {
|
|
32
|
+
path: "/",
|
|
33
|
+
secure: process.env.NODE_ENV === "production",
|
|
34
|
+
httpOnly: true,
|
|
35
|
+
maxAge: 60 * 10,
|
|
36
|
+
sameSite: "lax"
|
|
37
|
+
});
|
|
38
|
+
return redirect(url.toString());
|
|
39
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use server";
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.getGoogleConfig = getGoogleConfig;
|
|
8
|
+
exports.updateGoogleConfig = updateGoogleConfig;
|
|
9
|
+
var _server = require("@arch-cadre/modules/server");
|
|
10
|
+
var _cache = require("next/cache");
|
|
11
|
+
async function getGoogleConfig() {
|
|
12
|
+
const config = await (0, _server.getModuleConfig)("google-auth");
|
|
13
|
+
return config ?? {
|
|
14
|
+
clientId: "",
|
|
15
|
+
clientSecret: "",
|
|
16
|
+
redirectUri: "http://localhost:3000/api/auth/google/callback"
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
async function updateGoogleConfig(config) {
|
|
20
|
+
await (0, _server.updateModuleConfig)("google-auth", config);
|
|
21
|
+
(0, _cache.revalidatePath)(`${(0, _server.getKryoPathPrefix)()}/google-auth/settings`);
|
|
22
|
+
return {
|
|
23
|
+
success: true
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface GoogleAuthConfig {
|
|
2
|
+
clientId: string;
|
|
3
|
+
clientSecret: string;
|
|
4
|
+
redirectUri: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function getGoogleConfig(): Promise<any>;
|
|
7
|
+
export declare function updateGoogleConfig(config: GoogleAuthConfig): Promise<{
|
|
8
|
+
success: boolean;
|
|
9
|
+
}>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import {
|
|
3
|
+
getKryoPathPrefix,
|
|
4
|
+
getModuleConfig,
|
|
5
|
+
updateModuleConfig
|
|
6
|
+
} from "@arch-cadre/modules/server";
|
|
7
|
+
import { revalidatePath } from "next/cache";
|
|
8
|
+
export async function getGoogleConfig() {
|
|
9
|
+
const config = await getModuleConfig("google-auth");
|
|
10
|
+
return config ?? {
|
|
11
|
+
clientId: "",
|
|
12
|
+
clientSecret: "",
|
|
13
|
+
redirectUri: "http://localhost:3000/api/auth/google/callback"
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export async function updateGoogleConfig(config) {
|
|
17
|
+
await updateModuleConfig("google-auth", config);
|
|
18
|
+
revalidatePath(`${getKryoPathPrefix()}/google-auth/settings`);
|
|
19
|
+
return { success: true };
|
|
20
|
+
}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
var _manifest = _interopRequireDefault(require("../manifest.json"));
|
|
8
|
+
var _navigation = require("./navigation.cjs");
|
|
9
|
+
var _routes = require("./routes.cjs");
|
|
10
|
+
var _googleButton = require("./ui/google-button.cjs");
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
const googleAuthModule = {
|
|
13
|
+
manifest: _manifest.default,
|
|
14
|
+
routes: {
|
|
15
|
+
private: _routes.privateRoutes,
|
|
16
|
+
api: _routes.apiRoutes
|
|
17
|
+
},
|
|
18
|
+
extensions: [{
|
|
19
|
+
id: "google-login-signin",
|
|
20
|
+
targetModule: "auth",
|
|
21
|
+
point: "signin:extra-buttons",
|
|
22
|
+
component: _googleButton.GoogleLoginButton,
|
|
23
|
+
priority: 10
|
|
24
|
+
}, {
|
|
25
|
+
id: "google-login-signup",
|
|
26
|
+
targetModule: "auth",
|
|
27
|
+
point: "signup:extra-buttons",
|
|
28
|
+
component: _googleButton.GoogleLoginButton,
|
|
29
|
+
priority: 10
|
|
30
|
+
}],
|
|
31
|
+
navigation: _navigation.navigation
|
|
32
|
+
};
|
|
33
|
+
module.exports = googleAuthModule;
|
package/dist/index.d.ts
ADDED
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import manifest from "../manifest.json";
|
|
2
|
+
import { navigation } from "./navigation.mjs";
|
|
3
|
+
import { apiRoutes, privateRoutes } from "./routes.mjs";
|
|
4
|
+
import { GoogleLoginButton } from "./ui/google-button.mjs";
|
|
5
|
+
const googleAuthModule = {
|
|
6
|
+
manifest,
|
|
7
|
+
routes: {
|
|
8
|
+
private: privateRoutes,
|
|
9
|
+
api: apiRoutes
|
|
10
|
+
},
|
|
11
|
+
extensions: [
|
|
12
|
+
{
|
|
13
|
+
id: "google-login-signin",
|
|
14
|
+
targetModule: "auth",
|
|
15
|
+
point: "signin:extra-buttons",
|
|
16
|
+
component: GoogleLoginButton,
|
|
17
|
+
priority: 10
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "google-login-signup",
|
|
21
|
+
targetModule: "auth",
|
|
22
|
+
point: "signup:extra-buttons",
|
|
23
|
+
component: GoogleLoginButton,
|
|
24
|
+
priority: 10
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
navigation
|
|
28
|
+
};
|
|
29
|
+
export default googleAuthModule;
|
package/dist/intl.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.navigation = void 0;
|
|
7
|
+
var _intl = require("@arch-cadre/intl");
|
|
8
|
+
const navigation = exports.navigation = {
|
|
9
|
+
admin: {
|
|
10
|
+
[(0, _intl.i18n)("Security")]: [{
|
|
11
|
+
id: "google-auth-settings",
|
|
12
|
+
title: (0, _intl.i18n)("Google Auth"),
|
|
13
|
+
url: "/google-auth/settings",
|
|
14
|
+
icon: "solar:lock-keyhole-bold-duotone"
|
|
15
|
+
}]
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { i18n } from "@arch-cadre/intl";
|
|
2
|
+
export const navigation = {
|
|
3
|
+
admin: {
|
|
4
|
+
[i18n("Security")]: [
|
|
5
|
+
{
|
|
6
|
+
id: "google-auth-settings",
|
|
7
|
+
title: i18n("Google Auth"),
|
|
8
|
+
url: "/google-auth/settings",
|
|
9
|
+
icon: "solar:lock-keyhole-bold-duotone"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
};
|
package/dist/routes.cjs
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.privateRoutes = exports.apiRoutes = void 0;
|
|
7
|
+
var _core = require("@arch-cadre/core");
|
|
8
|
+
var _server = require("@arch-cadre/core/server");
|
|
9
|
+
var _arctic = require("arctic");
|
|
10
|
+
var _dynamic = _interopRequireDefault(require("next/dynamic"));
|
|
11
|
+
var _headers = require("next/headers");
|
|
12
|
+
var _settings = require("./actions/settings.cjs");
|
|
13
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
+
const GoogleAuthSettingsPage = (0, _dynamic.default)(() => Promise.resolve().then(() => require("./ui/settings-page.cjs")));
|
|
15
|
+
async function getGoogleClient() {
|
|
16
|
+
const config = await (0, _settings.getGoogleConfig)();
|
|
17
|
+
return new _arctic.Google(config.clientId, config.clientSecret, config.redirectUri);
|
|
18
|
+
}
|
|
19
|
+
const privateRoutes = exports.privateRoutes = [{
|
|
20
|
+
path: "/google-auth/settings",
|
|
21
|
+
// Będzie widoczne pod /module/google-auth/settings
|
|
22
|
+
component: GoogleAuthSettingsPage,
|
|
23
|
+
auth: true
|
|
24
|
+
}];
|
|
25
|
+
const apiRoutes = exports.apiRoutes = [{
|
|
26
|
+
path: "/api/auth/google/callback",
|
|
27
|
+
handler: async request => {
|
|
28
|
+
const google = await getGoogleClient();
|
|
29
|
+
const url = new URL(request.url);
|
|
30
|
+
const code = url.searchParams.get("code");
|
|
31
|
+
const state = url.searchParams.get("state");
|
|
32
|
+
const cookieStore = await (0, _headers.cookies)();
|
|
33
|
+
const storedState = cookieStore.get("google_oauth_state")?.value;
|
|
34
|
+
const codeVerifier = cookieStore.get("google_code_verifier")?.value;
|
|
35
|
+
if (!code || !state || !storedState || !codeVerifier || state !== storedState) {
|
|
36
|
+
return new Response("Invalid state or code", {
|
|
37
|
+
status: 400
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const tokens = await google.validateAuthorizationCode(code, codeVerifier);
|
|
42
|
+
const idToken = tokens.idToken();
|
|
43
|
+
const claims = (0, _arctic.decodeIdToken)(idToken);
|
|
44
|
+
let user = await (0, _server.getUserFromEmail)(claims.email);
|
|
45
|
+
if (!user) {
|
|
46
|
+
user = await (0, _server.createOAuthUser)(claims.email, claims.name, claims.picture);
|
|
47
|
+
}
|
|
48
|
+
const sessionToken = await (0, _server.generateSessionToken)();
|
|
49
|
+
const session = await (0, _server.createSession)(sessionToken, user.id, {});
|
|
50
|
+
await (0, _server.setSessionTokenCookie)(sessionToken, session.expiresAt);
|
|
51
|
+
const fullUser = await (0, _server.performFullUserAugmentation)(user);
|
|
52
|
+
await _core.eventBus.publish("auth:login", {
|
|
53
|
+
email: user.email,
|
|
54
|
+
userId: user.id
|
|
55
|
+
});
|
|
56
|
+
await _core.eventBus.publish("auth:session-created", {
|
|
57
|
+
session,
|
|
58
|
+
user: fullUser
|
|
59
|
+
});
|
|
60
|
+
return new Response(null, {
|
|
61
|
+
status: 302,
|
|
62
|
+
headers: {
|
|
63
|
+
Location: "/"
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error("[GoogleAuth] Error during callback:", error);
|
|
68
|
+
return new Response("Authentication failed", {
|
|
69
|
+
status: 500
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}];
|
package/dist/routes.d.ts
ADDED
package/dist/routes.mjs
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { eventBus } from "@arch-cadre/core";
|
|
2
|
+
import {
|
|
3
|
+
createOAuthUser,
|
|
4
|
+
createSession,
|
|
5
|
+
generateSessionToken,
|
|
6
|
+
getUserFromEmail,
|
|
7
|
+
performFullUserAugmentation,
|
|
8
|
+
setSessionTokenCookie
|
|
9
|
+
} from "@arch-cadre/core/server";
|
|
10
|
+
import { decodeIdToken, Google } from "arctic";
|
|
11
|
+
import dynamic from "next/dynamic";
|
|
12
|
+
import { cookies } from "next/headers";
|
|
13
|
+
import { getGoogleConfig } from "./actions/settings.mjs";
|
|
14
|
+
const GoogleAuthSettingsPage = dynamic(() => import("./ui/settings-page.mjs"));
|
|
15
|
+
async function getGoogleClient() {
|
|
16
|
+
const config = await getGoogleConfig();
|
|
17
|
+
return new Google(config.clientId, config.clientSecret, config.redirectUri);
|
|
18
|
+
}
|
|
19
|
+
export const privateRoutes = [
|
|
20
|
+
{
|
|
21
|
+
path: "/google-auth/settings",
|
|
22
|
+
// Będzie widoczne pod /module/google-auth/settings
|
|
23
|
+
component: GoogleAuthSettingsPage,
|
|
24
|
+
auth: true
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
export const apiRoutes = [
|
|
28
|
+
{
|
|
29
|
+
path: "/api/auth/google/callback",
|
|
30
|
+
handler: async (request) => {
|
|
31
|
+
const google = await getGoogleClient();
|
|
32
|
+
const url = new URL(request.url);
|
|
33
|
+
const code = url.searchParams.get("code");
|
|
34
|
+
const state = url.searchParams.get("state");
|
|
35
|
+
const cookieStore = await cookies();
|
|
36
|
+
const storedState = cookieStore.get("google_oauth_state")?.value;
|
|
37
|
+
const codeVerifier = cookieStore.get("google_code_verifier")?.value;
|
|
38
|
+
if (!code || !state || !storedState || !codeVerifier || state !== storedState) {
|
|
39
|
+
return new Response("Invalid state or code", { status: 400 });
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const tokens = await google.validateAuthorizationCode(
|
|
43
|
+
code,
|
|
44
|
+
codeVerifier
|
|
45
|
+
);
|
|
46
|
+
const idToken = tokens.idToken();
|
|
47
|
+
const claims = decodeIdToken(idToken);
|
|
48
|
+
let user = await getUserFromEmail(claims.email);
|
|
49
|
+
if (!user) {
|
|
50
|
+
user = await createOAuthUser(
|
|
51
|
+
claims.email,
|
|
52
|
+
claims.name,
|
|
53
|
+
claims.picture
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
const sessionToken = await generateSessionToken();
|
|
57
|
+
const session = await createSession(sessionToken, user.id, {});
|
|
58
|
+
await setSessionTokenCookie(sessionToken, session.expiresAt);
|
|
59
|
+
const fullUser = await performFullUserAugmentation(user);
|
|
60
|
+
await eventBus.publish("auth:login", {
|
|
61
|
+
email: user.email,
|
|
62
|
+
userId: user.id
|
|
63
|
+
});
|
|
64
|
+
await eventBus.publish("auth:session-created", {
|
|
65
|
+
session,
|
|
66
|
+
user: fullUser
|
|
67
|
+
});
|
|
68
|
+
return new Response(null, {
|
|
69
|
+
status: 302,
|
|
70
|
+
headers: {
|
|
71
|
+
Location: "/"
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error("[GoogleAuth] Error during callback:", error);
|
|
76
|
+
return new Response("Authentication failed", { status: 500 });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.GoogleLoginButton = GoogleLoginButton;
|
|
8
|
+
var _intl = require("@arch-cadre/intl");
|
|
9
|
+
var _ui = require("@arch-cadre/ui");
|
|
10
|
+
var React = _interopRequireWildcard(require("react"));
|
|
11
|
+
var _auth = require("../actions/auth.cjs");
|
|
12
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
13
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
14
|
+
function GoogleLoginButton() {
|
|
15
|
+
const {
|
|
16
|
+
t
|
|
17
|
+
} = (0, _intl.useTranslation)();
|
|
18
|
+
return /* @__PURE__ */React.createElement(_ui.Button, {
|
|
19
|
+
type: "button",
|
|
20
|
+
variant: "outline",
|
|
21
|
+
className: "w-full gap-2",
|
|
22
|
+
onClick: () => (0, _auth.loginWithGoogle)()
|
|
23
|
+
}, /* @__PURE__ */React.createElement("svg", {
|
|
24
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
25
|
+
viewBox: "0 0 24 24",
|
|
26
|
+
className: "size-4"
|
|
27
|
+
}, /* @__PURE__ */React.createElement("title", null, t("Continue with Google")), /* @__PURE__ */React.createElement("path", {
|
|
28
|
+
d: "M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z",
|
|
29
|
+
fill: "currentColor"
|
|
30
|
+
})), t("Continue with Google"));
|
|
31
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useTranslation } from "@arch-cadre/intl";
|
|
3
|
+
import { Button } from "@arch-cadre/ui";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { loginWithGoogle } from "../actions/auth.mjs";
|
|
6
|
+
export function GoogleLoginButton() {
|
|
7
|
+
const { t } = useTranslation();
|
|
8
|
+
return /* @__PURE__ */ React.createElement(
|
|
9
|
+
Button,
|
|
10
|
+
{
|
|
11
|
+
type: "button",
|
|
12
|
+
variant: "outline",
|
|
13
|
+
className: "w-full gap-2",
|
|
14
|
+
onClick: () => loginWithGoogle()
|
|
15
|
+
},
|
|
16
|
+
/* @__PURE__ */ React.createElement(
|
|
17
|
+
"svg",
|
|
18
|
+
{
|
|
19
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
20
|
+
viewBox: "0 0 24 24",
|
|
21
|
+
className: "size-4"
|
|
22
|
+
},
|
|
23
|
+
/* @__PURE__ */ React.createElement("title", null, t("Continue with Google")),
|
|
24
|
+
/* @__PURE__ */ React.createElement(
|
|
25
|
+
"path",
|
|
26
|
+
{
|
|
27
|
+
d: "M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z",
|
|
28
|
+
fill: "currentColor"
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
),
|
|
32
|
+
t("Continue with Google")
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
module.exports = GoogleAuthSettingsPage;
|
|
8
|
+
var _intl = require("@arch-cadre/intl");
|
|
9
|
+
var _button = require("@arch-cadre/ui/components/button");
|
|
10
|
+
var _card = require("@arch-cadre/ui/components/card");
|
|
11
|
+
var _input = require("@arch-cadre/ui/components/input");
|
|
12
|
+
var _label = require("@arch-cadre/ui/components/label");
|
|
13
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
14
|
+
var React = _react;
|
|
15
|
+
var _sonner = require("sonner");
|
|
16
|
+
var _settings = require("../actions/settings.cjs");
|
|
17
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
18
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
19
|
+
function GoogleAuthSettingsPage() {
|
|
20
|
+
const {
|
|
21
|
+
t
|
|
22
|
+
} = (0, _intl.useTranslation)();
|
|
23
|
+
const [config, setConfig] = (0, _react.useState)({
|
|
24
|
+
clientId: "",
|
|
25
|
+
clientSecret: "",
|
|
26
|
+
redirectUri: ""
|
|
27
|
+
});
|
|
28
|
+
const [loading, setLoading] = (0, _react.useState)(true);
|
|
29
|
+
(0, _react.useEffect)(() => {
|
|
30
|
+
(0, _settings.getGoogleConfig)().then(data => {
|
|
31
|
+
setConfig(data);
|
|
32
|
+
setLoading(false);
|
|
33
|
+
});
|
|
34
|
+
}, []);
|
|
35
|
+
const handleSave = async e => {
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
try {
|
|
38
|
+
await (0, _settings.updateGoogleConfig)(config);
|
|
39
|
+
_sonner.toast.success(t("Settings saved successfully"));
|
|
40
|
+
} catch {
|
|
41
|
+
_sonner.toast.error(t("Failed to save settings. Please check your configuration and try again."));
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
if (loading) return /* @__PURE__ */React.createElement("div", null, t("Google Auth"));
|
|
45
|
+
return /* @__PURE__ */React.createElement("div", {
|
|
46
|
+
className: "container mx-auto py-10 max-w-2xl"
|
|
47
|
+
}, /* @__PURE__ */React.createElement(_card.Card, null, /* @__PURE__ */React.createElement(_card.CardHeader, null, /* @__PURE__ */React.createElement("div", null, t("Google Auth")), /* @__PURE__ */React.createElement("div", null, t("")), /* @__PURE__ */React.createElement(_card.CardTitle, null, t("Google Authentication Settings")), /* @__PURE__ */React.createElement(_card.CardDescription, null, t("Configure your Google OAuth2 credentials. You can find these in the Google Cloud Console."))), /* @__PURE__ */React.createElement(_card.CardContent, null, /* @__PURE__ */React.createElement("form", {
|
|
48
|
+
onSubmit: handleSave,
|
|
49
|
+
className: "space-y-4"
|
|
50
|
+
}, /* @__PURE__ */React.createElement("div", {
|
|
51
|
+
className: "space-y-2"
|
|
52
|
+
}, /* @__PURE__ */React.createElement(_label.Label, {
|
|
53
|
+
htmlFor: "clientId"
|
|
54
|
+
}, t("Client ID")), /* @__PURE__ */React.createElement(_input.Input, {
|
|
55
|
+
id: "clientId",
|
|
56
|
+
value: config.clientId,
|
|
57
|
+
onChange: e => setConfig({
|
|
58
|
+
...config,
|
|
59
|
+
clientId: e.target.value
|
|
60
|
+
}),
|
|
61
|
+
placeholder: "xxx.apps.googleusercontent.com"
|
|
62
|
+
})), /* @__PURE__ */React.createElement("div", {
|
|
63
|
+
className: "space-y-2"
|
|
64
|
+
}, /* @__PURE__ */React.createElement(_label.Label, {
|
|
65
|
+
htmlFor: "clientSecret"
|
|
66
|
+
}, t("Client Secret")), /* @__PURE__ */React.createElement(_input.Input, {
|
|
67
|
+
id: "clientSecret",
|
|
68
|
+
type: "password",
|
|
69
|
+
value: config.clientSecret,
|
|
70
|
+
onChange: e => setConfig({
|
|
71
|
+
...config,
|
|
72
|
+
clientSecret: e.target.value
|
|
73
|
+
}),
|
|
74
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
75
|
+
})), /* @__PURE__ */React.createElement("div", {
|
|
76
|
+
className: "space-y-2"
|
|
77
|
+
}, /* @__PURE__ */React.createElement(_label.Label, {
|
|
78
|
+
htmlFor: "redirectUri"
|
|
79
|
+
}, t("Redirect URI")), /* @__PURE__ */React.createElement(_input.Input, {
|
|
80
|
+
id: "redirectUri",
|
|
81
|
+
value: config.redirectUri,
|
|
82
|
+
onChange: e => setConfig({
|
|
83
|
+
...config,
|
|
84
|
+
redirectUri: e.target.value
|
|
85
|
+
}),
|
|
86
|
+
placeholder: "http://localhost:3000/api/auth/google/callback"
|
|
87
|
+
}), /* @__PURE__ */React.createElement("p", {
|
|
88
|
+
className: "text-[10px] text-muted-foreground italic"
|
|
89
|
+
}, t("Must match exactly with Google Cloud Console configuration."))), /* @__PURE__ */React.createElement(_button.Button, {
|
|
90
|
+
type: "submit",
|
|
91
|
+
className: "w-full"
|
|
92
|
+
}, t("Save Configuration"))))));
|
|
93
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useTranslation } from "@arch-cadre/intl";
|
|
3
|
+
import { Button } from "@arch-cadre/ui/components/button";
|
|
4
|
+
import {
|
|
5
|
+
Card,
|
|
6
|
+
CardContent,
|
|
7
|
+
CardDescription,
|
|
8
|
+
CardHeader,
|
|
9
|
+
CardTitle
|
|
10
|
+
} from "@arch-cadre/ui/components/card";
|
|
11
|
+
import { Input } from "@arch-cadre/ui/components/input";
|
|
12
|
+
import { Label } from "@arch-cadre/ui/components/label";
|
|
13
|
+
import * as React from "react";
|
|
14
|
+
import { useEffect, useState } from "react";
|
|
15
|
+
import { toast } from "sonner";
|
|
16
|
+
import {
|
|
17
|
+
getGoogleConfig,
|
|
18
|
+
updateGoogleConfig
|
|
19
|
+
} from "../actions/settings.mjs";
|
|
20
|
+
export default function GoogleAuthSettingsPage() {
|
|
21
|
+
const { t } = useTranslation();
|
|
22
|
+
const [config, setConfig] = useState({
|
|
23
|
+
clientId: "",
|
|
24
|
+
clientSecret: "",
|
|
25
|
+
redirectUri: ""
|
|
26
|
+
});
|
|
27
|
+
const [loading, setLoading] = useState(true);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
getGoogleConfig().then((data) => {
|
|
30
|
+
setConfig(data);
|
|
31
|
+
setLoading(false);
|
|
32
|
+
});
|
|
33
|
+
}, []);
|
|
34
|
+
const handleSave = async (e) => {
|
|
35
|
+
e.preventDefault();
|
|
36
|
+
try {
|
|
37
|
+
await updateGoogleConfig(config);
|
|
38
|
+
toast.success(t("Settings saved successfully"));
|
|
39
|
+
} catch {
|
|
40
|
+
toast.error(
|
|
41
|
+
t(
|
|
42
|
+
"Failed to save settings. Please check your configuration and try again."
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
if (loading) return /* @__PURE__ */ React.createElement("div", null, t("Google Auth"));
|
|
48
|
+
return /* @__PURE__ */ React.createElement("div", { className: "container mx-auto py-10 max-w-2xl" }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardHeader, null, /* @__PURE__ */ React.createElement("div", null, t("Google Auth")), /* @__PURE__ */ React.createElement("div", null, t("")), /* @__PURE__ */ React.createElement(CardTitle, null, t("Google Authentication Settings")), /* @__PURE__ */ React.createElement(CardDescription, null, t(
|
|
49
|
+
"Configure your Google OAuth2 credentials. You can find these in the Google Cloud Console."
|
|
50
|
+
))), /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement("form", { onSubmit: handleSave, className: "space-y-4" }, /* @__PURE__ */ React.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React.createElement(Label, { htmlFor: "clientId" }, t("Client ID")), /* @__PURE__ */ React.createElement(
|
|
51
|
+
Input,
|
|
52
|
+
{
|
|
53
|
+
id: "clientId",
|
|
54
|
+
value: config.clientId,
|
|
55
|
+
onChange: (e) => setConfig({ ...config, clientId: e.target.value }),
|
|
56
|
+
placeholder: "xxx.apps.googleusercontent.com"
|
|
57
|
+
}
|
|
58
|
+
)), /* @__PURE__ */ React.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React.createElement(Label, { htmlFor: "clientSecret" }, t("Client Secret")), /* @__PURE__ */ React.createElement(
|
|
59
|
+
Input,
|
|
60
|
+
{
|
|
61
|
+
id: "clientSecret",
|
|
62
|
+
type: "password",
|
|
63
|
+
value: config.clientSecret,
|
|
64
|
+
onChange: (e) => setConfig({ ...config, clientSecret: e.target.value }),
|
|
65
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
66
|
+
}
|
|
67
|
+
)), /* @__PURE__ */ React.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React.createElement(Label, { htmlFor: "redirectUri" }, t("Redirect URI")), /* @__PURE__ */ React.createElement(
|
|
68
|
+
Input,
|
|
69
|
+
{
|
|
70
|
+
id: "redirectUri",
|
|
71
|
+
value: config.redirectUri,
|
|
72
|
+
onChange: (e) => setConfig({ ...config, redirectUri: e.target.value }),
|
|
73
|
+
placeholder: "http://localhost:3000/api/auth/google/callback"
|
|
74
|
+
}
|
|
75
|
+
), /* @__PURE__ */ React.createElement("p", { className: "text-[10px] text-muted-foreground italic" }, t(
|
|
76
|
+
"Must match exactly with Google Cloud Console configuration."
|
|
77
|
+
))), /* @__PURE__ */ React.createElement(Button, { type: "submit", className: "w-full" }, t("Save Configuration"))))));
|
|
78
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Settings saved successfully": "Settings saved successfully",
|
|
3
|
+
"Failed to save settings. Please check your configuration and try again.": "Failed to save settings. Please check your configuration and try again.",
|
|
4
|
+
"Google Auth": "Google Auth",
|
|
5
|
+
"Google Authentication Settings": "Google Authentication Settings",
|
|
6
|
+
"Configure your Google OAuth2 credentials. You can find these in the Google Cloud Console.": "Configure your Google OAuth2 credentials. You can find these in the Google Cloud Console.",
|
|
7
|
+
"Client ID": "Client ID",
|
|
8
|
+
"Client Secret": "Client Secret",
|
|
9
|
+
"Redirect URI": "Redirect URI",
|
|
10
|
+
"Must match exactly with Google Cloud Console configuration.": "Must match exactly with Google Cloud Console configuration.",
|
|
11
|
+
"Save Configuration": "Save Configuration",
|
|
12
|
+
"Continue with Google": "Continue with Google",
|
|
13
|
+
"Security": "Security"
|
|
14
|
+
}
|
package/manifest.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "google-auth",
|
|
3
|
+
"name": "Google Authentication",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"description": "Allows users to sign in using their Google account.",
|
|
6
|
+
"enabled": false,
|
|
7
|
+
"system": false,
|
|
8
|
+
"dependencies": ["auth"],
|
|
9
|
+
"extends": ["auth"],
|
|
10
|
+
"isNpm": true
|
|
11
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arch-cadre/auth-google",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Google Auth module for Kryo framework",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
"./package.json": "./package.json",
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.cjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"locales",
|
|
17
|
+
"manifest.json"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"release": "npm publish --access public --no-git-checks",
|
|
21
|
+
"clean": "rm -rf ./dist",
|
|
22
|
+
"switch:dev": "node scripts/switchToSrc.js",
|
|
23
|
+
"switch:prod": "node scripts/switchToDist.js",
|
|
24
|
+
"dev": "unbuild --stub",
|
|
25
|
+
"build": "unbuild"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@arch-cadre/modules": "^0.0.15",
|
|
29
|
+
"@hookform/resolvers": "^3.10.0",
|
|
30
|
+
"@arch-cadre/ui": "^0.0.15",
|
|
31
|
+
"arctic": "^3.7.0",
|
|
32
|
+
"lucide-react": "^0.475.0",
|
|
33
|
+
"react-hook-form": "^7.54.2",
|
|
34
|
+
"sonner": "^2.0.7",
|
|
35
|
+
"zod": "^3.24.1"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@arch-cadre/core": "^0.0.15",
|
|
39
|
+
"@arch-cadre/intl": "^0.0.15",
|
|
40
|
+
"@types/react": "^19",
|
|
41
|
+
"next": "16.1.1",
|
|
42
|
+
"react": "^19.0.0",
|
|
43
|
+
"typescript": "^5.3.3",
|
|
44
|
+
"unbuild": "^3.6.1"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@arch-cadre/core": "^0.0.15",
|
|
48
|
+
"@arch-cadre/ui": "^0.0.15",
|
|
49
|
+
"next": ">=13.0.0",
|
|
50
|
+
"react": "^19.0.0"
|
|
51
|
+
},
|
|
52
|
+
"main": "./dist/index.mjs"
|
|
53
|
+
}
|