diff --git a/docker/README.md b/docker/README.md index 458ce571b..472bb1309 100644 --- a/docker/README.md +++ b/docker/README.md @@ -31,7 +31,19 @@ docker buildx build -t mono-ui:0.1-pre-release -f ./docker/mono-ui-dockerfile . # .\init-volume.ps1 -baseDir "D:\" -configFile ".\config.toml" ``` -[2] Start whole mono engine stack + +[2] Start whole mono engine stack on local for testing +```bash +# create network +docker network create mono-network + +# run postgres +docker run --rm -it -d --name mono-pg --network mono-network -v /tmp/data/mono/pg-data:/var/lib/postgresql/data -p 5432:5432 mono-pg:0.1-pre-release +docker run --rm -it -d --name mono-engine --network mono-network -v /tmp/data/mono/mono-data:/opt/mega -p 8000:8000 mono-engine:0.1-pre-release +docker run --rm -it -d --name mono-ui --network mono-network -e MEGA_INTERNAL_HOST=http://mono-engine:8000 -e MEGA_HOST=http://localhost:8000 -e MOON_HOST=http://localhost:3000 -p 3000:3000 mono-ui:0.1-pre-release +``` + +[3] Start whole mono engine stack on server with domain ```bash # create network @@ -40,5 +52,5 @@ docker network create mono-network # run postgres docker run --rm -it -d --name mono-pg --network mono-network -v /mnt/data/mono/pg-data:/var/lib/postgresql/data -p 5432:5432 mono-pg:0.1-pre-release docker run --rm -it -d --name mono-engine --network mono-network -v /mnt/data/mono/mono-data:/opt/mega -p 8000:8000 -p 22:9000 mono-engine:0.1-pre-release -docker run --rm -it -d --name mono-ui --network mono-network -e MEGA_HOST=http://git.gitmono.com -e MOON_HOST=https://console.gitmono.com -p 3000:3000 mono-ui:0.1-pre-release +docker run --rm -it -d --name mono-ui --network mono-network -e MEGA_INTERNAL_HOST=http://mono-engine:8000 -e MEGA_HOST=http://git.gitmono.com -e MOON_HOST=https://console.gitmono.com -p 3000:3000 mono-ui:0.1-pre-release ``` \ No newline at end of file diff --git a/docker/mono-engine-dockerfile b/docker/mono-engine-dockerfile index 1dc461b40..f78f82351 100644 --- a/docker/mono-engine-dockerfile +++ b/docker/mono-engine-dockerfile @@ -52,7 +52,7 @@ RUN if [ "$BUILD_TYPE" = "release" ]; then \ # final image FROM debian:bookworm-slim -RUN apt-get update && apt-get install -y libssl-dev +RUN apt-get update && apt-get install -y libssl-dev ca-certificates ARG BUILD_TYPE=release diff --git a/docker/mono-ui-dockerfile b/docker/mono-ui-dockerfile index 27a32657d..37e9577b2 100644 --- a/docker/mono-ui-dockerfile +++ b/docker/mono-ui-dockerfile @@ -1,5 +1,5 @@ ## exmaple: https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile -FROM node:20-alpine AS base +FROM node:22-alpine AS base # Install dependencies only when needed FROM base AS deps diff --git a/docker/start-moon.sh b/docker/start-moon.sh index 744b072a7..91a13d5f3 100755 --- a/docker/start-moon.sh +++ b/docker/start-moon.sh @@ -1,11 +1,16 @@ #!/bin/bash -# user must set the NEXT_PUBLIC_API_URL +# user must set the MEGA_HOST,MEGA_INTERNAL_HOST and MOON_HOST if [ -z "$MEGA_HOST" ]; then echo "MEGA_HOST is not set" exit 1 fi +if [ -z "$MEGA_INTERNAL_HOST" ]; then + echo "MEGA_INTERNAL_HOST is not set" + exit 1 +fi + if [ -z "$MOON_HOST" ]; then echo "MOON_HOST is not set" exit 1 diff --git a/mono/src/api/oauth/mod.rs b/mono/src/api/oauth/mod.rs index 50b720eaf..7069b5c2d 100644 --- a/mono/src/api/oauth/mod.rs +++ b/mono/src/api/oauth/mod.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use axum::async_trait; use axum::response::Redirect; +use axum::routing::post; use axum::{ extract::{Path, Query, State}, http::StatusCode, @@ -15,6 +16,7 @@ use axum_extra::TypedHeader; use tokio::sync::Mutex; use uuid::Uuid; +use common::model::CommonResult; use common::enums::SupportOauthType; use common::errors::MegaError; use github::GithubOauthService; @@ -58,7 +60,7 @@ pub trait OauthHandler: Send + Sync { pub fn routers() -> Router { Router::new() .route("/:oauth_type/authorize", get(redirect_authorize)) - .route("/:oauth_type/callback", get(oauth_callback)) + .route("/:oauth_type/callback", post(oauth_callback)) .route("/:oauth_type/user", get(user)) } @@ -85,7 +87,7 @@ async fn oauth_callback( Path(oauth_type): Path, Query(query): Query, service_state: State, -) -> Result { +) -> Result>, (StatusCode, String)> { let oauth_type: SupportOauthType = match oauth_type.parse::() { Ok(value) => value, Err(err) => return Err((StatusCode::BAD_REQUEST, err)), @@ -96,7 +98,7 @@ async fn oauth_callback( let redirect_uri = match sessions.get(&query.state) { Some(uri) => uri.clone(), - None => return Err((StatusCode::BAD_REQUEST, "Invalid state".to_string())), + None => return Ok(Json(CommonResult::failed("Invalid state"))), }; let access_token = service_state .oauth_handler(oauth_type) @@ -104,9 +106,7 @@ async fn oauth_callback( .await .unwrap(); sessions.remove(&query.state); - - let callback_url = format!("{}?access_token={}", redirect_uri, access_token); - Ok(Redirect::temporary(&callback_url)) + Ok(Json(CommonResult::success(Some(access_token)))) } async fn user( diff --git a/moon/.env b/moon/.env index b66d5d51a..fe8d83a10 100644 --- a/moon/.env +++ b/moon/.env @@ -2,9 +2,10 @@ # Variables not prefixed with NEXT_PUBLIC_ are only available on the server side. -# add MEGA_HOST and MOON_HOST to your enviroment for development -# MEGA_HOST default to http://localhost:8000, MOON_HOST default to http://localhost:3000 +# add MEGA_HOST, MEGA_INTERNAL_HOST and MOON_HOST to your enviroment for development +# MEGA_HOST and MEGA_INTERNAL_HOST default to http://localhost:8000, MOON_HOST default to http://localhost:3000 MEGA_HOST=$MEGA_HOST +MEGA_INTERNAL_HOST=$MEGA_INTERNAL_HOST CALLBACK_URL=$MOON_HOST/auth/github/callback SECRET_KEY=$YOUR_SECRET_KEY #(not prefixed with NEXT_PUBLIC_ ) \ No newline at end of file diff --git a/moon/README.md b/moon/README.md index 0fb628d09..db3853f38 100644 --- a/moon/README.md +++ b/moon/README.md @@ -1 +1,16 @@ -## Moon Module \ No newline at end of file +## Moon Module + +--- + +### Environment Variables + +In the root directory of your project, three environment variables are required in the `.env` file: + +- **MEGA_HOST**: Used for redirecting to public backend routes during the OAuth process. +- **MOON_HOST**: Provides the callback URL to the authentication provider. +- **MEGA_INTERNAL_HOST**: Utilized for internal API requests. Given that the application uses SSR and Next.js Route Handlers, this variable allows you to specify a domain name within the container network. + +### Environment Handling + +- **Development Mode**: Next.js automatically reads the environment variables from the `.env` file. +- **Production Mode**: Environment variables must be passed via Docker commands when deploying the application. \ No newline at end of file diff --git a/moon/src/app/api/auth/github/callback/route.ts b/moon/src/app/api/auth/github/callback/route.ts new file mode 100644 index 000000000..9aaab7764 --- /dev/null +++ b/moon/src/app/api/auth/github/callback/route.ts @@ -0,0 +1,19 @@ + +// import { cookies } from "next/headers"; +import { type NextRequest } from 'next/server' + +export async function POST(request: NextRequest) { + const endpoint = process.env.MEGA_INTERNAL_HOST; + const searchParams = request.nextUrl.searchParams; + const code = searchParams.get("code"); + const state = searchParams.get("state"); + const res = await fetch(`${endpoint}/auth/github/callback?code=${code}&state=${state}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }) + const data = await res.json() + + return Response.json({ data }) +} \ No newline at end of file diff --git a/moon/src/app/api/auth/github/user/route.ts b/moon/src/app/api/auth/github/user/route.ts index fa97ac34a..70352cc4e 100644 --- a/moon/src/app/api/auth/github/user/route.ts +++ b/moon/src/app/api/auth/github/user/route.ts @@ -3,7 +3,7 @@ import { cookies } from "next/headers"; export async function GET(request: Request) { - const endpoint = process.env.MEGA_HOST; + const endpoint = process.env.MEGA_INTERNAL_HOST; const cookieStore = cookies(); const access_token = cookieStore.get('access_token'); diff --git a/moon/src/app/api/blob/route.ts b/moon/src/app/api/blob/route.ts index 8622d4b98..995710445 100644 --- a/moon/src/app/api/blob/route.ts +++ b/moon/src/app/api/blob/route.ts @@ -4,7 +4,7 @@ export const dynamic = 'force-dynamic' // defaults to auto export const revalidate = 0 export async function GET(request: NextRequest) { - const endpoint = process.env.MEGA_HOST; + const endpoint = process.env.MEGA_INTERNAL_HOST; const searchParams = request.nextUrl.searchParams const path = searchParams.get('path') diff --git a/moon/src/app/api/mr/[id]/detail/route.ts b/moon/src/app/api/mr/[id]/detail/route.ts index f4e98114a..f98d2df88 100644 --- a/moon/src/app/api/mr/[id]/detail/route.ts +++ b/moon/src/app/api/mr/[id]/detail/route.ts @@ -2,7 +2,7 @@ export const dynamic = 'force-dynamic' // defaults to auto export const revalidate = 0 export async function GET(request: Request, { params }: { params: { id: string } }) { - const endpoint = process.env.MEGA_HOST; + const endpoint = process.env.MEGA_INTERNAL_HOST; const res = await fetch(`${endpoint}/api/v1/mr/${params.id}/detail`, { }) const data = await res.json() diff --git a/moon/src/app/api/mr/[id]/files/route.ts b/moon/src/app/api/mr/[id]/files/route.ts index 07e07b9a0..a425b8c07 100644 --- a/moon/src/app/api/mr/[id]/files/route.ts +++ b/moon/src/app/api/mr/[id]/files/route.ts @@ -1,7 +1,7 @@ export const dynamic = 'force-dynamic' // defaults to auto export async function GET(request: Request, { params }: { params: { id: string } }) { - const endpoint = process.env.MEGA_HOST; + const endpoint = process.env.MEGA_INTERNAL_HOST; const res = await fetch(`${endpoint}/api/v1/mr/${params.id}/files`, { }) const data = await res.json() diff --git a/moon/src/app/api/mr/[id]/merge/route.ts b/moon/src/app/api/mr/[id]/merge/route.ts index 134ef50b7..dd477c226 100644 --- a/moon/src/app/api/mr/[id]/merge/route.ts +++ b/moon/src/app/api/mr/[id]/merge/route.ts @@ -2,7 +2,7 @@ export const dynamic = 'force-dynamic' // defaults to auto export async function POST(request: Request, { params }: { params: { id: string } }) { - const endpoint = process.env.MEGA_HOST; + const endpoint = process.env.MEGA_INTERNAL_HOST; const res = await fetch(`${endpoint}/api/v1/mr/${params.id}/merge`, { method: 'POST', }) diff --git a/moon/src/app/api/mr/list/route.ts b/moon/src/app/api/mr/list/route.ts index 6e2a45a6e..95352c34c 100644 --- a/moon/src/app/api/mr/list/route.ts +++ b/moon/src/app/api/mr/list/route.ts @@ -4,7 +4,7 @@ export const revalidate = 0 import { type NextRequest } from 'next/server' export async function GET(request: NextRequest) { - const endpoint = process.env.MEGA_HOST; + const endpoint = process.env.MEGA_INTERNAL_HOST; const searchParams = request.nextUrl.searchParams const status = searchParams.get('status') const res = await fetch(`${endpoint}/api/v1/mr/list?status=${status}`, { diff --git a/moon/src/app/api/tree/commit-info/route.ts b/moon/src/app/api/tree/commit-info/route.ts index 827b7440f..e85b70ab2 100644 --- a/moon/src/app/api/tree/commit-info/route.ts +++ b/moon/src/app/api/tree/commit-info/route.ts @@ -5,7 +5,7 @@ export const revalidate = 0 export async function GET(request: NextRequest) { - const endpoint = process.env.MEGA_HOST; + const endpoint = process.env.MEGA_INTERNAL_HOST; const searchParams = request.nextUrl.searchParams const path = searchParams.get('path') diff --git a/moon/src/app/api/tree/route.ts b/moon/src/app/api/tree/route.ts index 863433f05..266a2f6f3 100644 --- a/moon/src/app/api/tree/route.ts +++ b/moon/src/app/api/tree/route.ts @@ -3,7 +3,7 @@ export const revalidate = 0 export const dynamic = 'force-dynamic' // defaults to auto export async function GET(request: NextRequest) { - const endpoint = process.env.MEGA_HOST; + const endpoint = process.env.MEGA_INTERNAL_HOST; const searchParams = request.nextUrl.searchParams const path = searchParams.get('path') diff --git a/moon/src/app/auth/github/callback/page.tsx b/moon/src/app/auth/github/callback/page.tsx index a69a179ee..f0a282fa0 100644 --- a/moon/src/app/auth/github/callback/page.tsx +++ b/moon/src/app/auth/github/callback/page.tsx @@ -1,47 +1,47 @@ 'use client' import { handleLogin } from '@/app/actions'; -import { useEffect, useState } from 'react'; - -interface enviroment { - mega_host: string; - callback_url: string; -} +import { useCallback, useEffect } from 'react'; +import { message } from "antd"; export default function AuthPage({ searchParams }) { - const [data, setData] = useState(null); - const [loading, setLoading] = useState(true); + const [messageApi, contextHolder] = message.useMessage(); + + + const error = useCallback((err_msg) => { + messageApi.open({ + type: 'error', + content: err_msg, + }); + }, [messageApi]); + const code = searchParams.code; + const state = searchParams.state; useEffect(() => { async function fetchData() { try { - const res = await fetch(`/api/env`); + const res = await fetch(`/api/auth/github/callback?code=${code}&state=${state}`, { + method: 'POST', + }); if (!res.ok) { throw new Error('Failed to fetch data'); } const result = await res.json(); - setData(result); + let data = result.data; + if (data.req_result) { + handleLogin(data.data) + } else { + error(data.err_message) + } } catch (error) { console.error('Error fetching data:', error); - } finally { - setLoading(false); } } - - fetchData(); - }, []); - - if (loading) return
Loading...
; - if (!data) return
Env Route Error
; - - const access_token = searchParams.access_token || ""; - const code = searchParams.code || ""; - const state = searchParams.state || ""; - - if (code && state) { - const targetUrl = `${data.mega_host}/auth/github/callback?code=${code}&state=${state}`; - window.location.href = targetUrl; - } else if (access_token) { - handleLogin(access_token) - } + if (code && state) { + fetchData(); + } + }, [code, state, error]); + return <> + {contextHolder} + }