diff --git a/common/Cargo.toml b/common/Cargo.toml index fc52503e4..561b4b6be 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -20,3 +20,4 @@ serde = { workspace = true } config = { workspace = true } envsubst = "0.2.1" rand = { workspace = true } +serde_json = { workspace = true } diff --git a/common/src/config.rs b/common/src/config.rs index d5d541f36..71054f0cd 100644 --- a/common/src/config.rs +++ b/common/src/config.rs @@ -209,7 +209,6 @@ impl Default for StorageConfig { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct MonoConfig { pub import_dir: PathBuf, - pub disable_http_push: bool, pub enable_http_auth: bool, pub admin: String, pub root_dirs: Vec, @@ -219,7 +218,6 @@ impl Default for MonoConfig { fn default() -> Self { Self { import_dir: PathBuf::from("/third-part"), - disable_http_push: false, enable_http_auth: false, admin: String::from("admin"), root_dirs: vec![ diff --git a/common/src/utils.rs b/common/src/utils.rs index 1c9cd5a63..fc2453204 100644 --- a/common/src/utils.rs +++ b/common/src/utils.rs @@ -1,5 +1,6 @@ use idgenerator::IdInstance; use rand::{distributions::Alphanumeric, thread_rng, Rng}; +use serde_json::{json, Value}; pub const ZERO_ID: &str = match std::str::from_utf8(&[b'0'; 40]) { Ok(s) => s, @@ -21,3 +22,21 @@ pub fn generate_link() -> String { } pub const MEGA_BRANCH_NAME: &str = "refs/heads/main"; + +pub fn generate_rich_text(content: &str) -> String { + let json_str = r#" + { + "root": { + "children": [{ + "children": [{ "detail": 0, "format": 0, "mode": "normal", "style": "", "text": "", "type": "text", "version": 1 }], + "direction": "ltr", "format": "", "indent": 0, "type": "paragraph", "version": 1, "textFormat": 0, "textStyle": "" + }], "direction": "ltr", "format": "", "indent": 0, "type": "root", "version": 1 + } + }"#; + let mut data: Value = serde_json::from_str(json_str).expect("Invalid JSON"); + + if let Some(text_value) = data["root"]["children"][0]["children"][0].get_mut("text") { + *text_value = json!(content); + } + serde_json::to_string_pretty(&data).expect("Failed to serialize JSON") +} diff --git a/docker/config.toml b/docker/config.toml index 6e65a3be1..5166360e3 100644 --- a/docker/config.toml +++ b/docker/config.toml @@ -53,10 +53,7 @@ obs_endpoint = "https://obs.cn-east-3.myhuaweicloud.com" ## Mega treats files under this directory as import repo and other directories as monorepo import_dir = "/third-part" -# The current mono Git HTTP server does not support authentication, so we provided a disabled operations here -disable_http_push = false - -# Support http authtication, login in with github and generate token before push +# Support http authentication, login in with github and generate token before push enable_http_auth = false # Set System Admin in directory init, replace the admin's github username here diff --git a/jupiter/callisto/src/db_enums.rs b/jupiter/callisto/src/db_enums.rs index db287223c..d08d89ccf 100644 --- a/jupiter/callisto/src/db_enums.rs +++ b/jupiter/callisto/src/db_enums.rs @@ -77,6 +77,7 @@ pub enum ConvType { MergeQueue, Merged, Closed, + Reopen, } impl Display for ConvType { @@ -92,6 +93,7 @@ impl Display for ConvType { ConvType::MergeQueue => "MergeQueue", ConvType::Merged => "Merged", ConvType::Closed => "Closed", + ConvType::Reopen => "Reopen", }; write!(f, "{}", s) } diff --git a/jupiter/src/storage/issue_storage.rs b/jupiter/src/storage/issue_storage.rs index 29991318e..bf1bc1553 100644 --- a/jupiter/src/storage/issue_storage.rs +++ b/jupiter/src/storage/issue_storage.rs @@ -89,6 +89,15 @@ impl IssueStorage { Ok(()) } + pub async fn reopen_issue(&self, link: &str) -> Result<(), MegaError> { + if let Some(model) = self.get_issue(link).await.unwrap() { + let mut issue = model.into_active_model(); + issue.status = Set("open".to_owned()); + issue.update(self.get_connection()).await.unwrap(); + }; + Ok(()) + } + pub async fn get_issue_conversations( &self, link: &str, diff --git a/jupiter/src/storage/mr_storage.rs b/jupiter/src/storage/mr_storage.rs index dd615e734..c4f703cdc 100644 --- a/jupiter/src/storage/mr_storage.rs +++ b/jupiter/src/storage/mr_storage.rs @@ -1,9 +1,8 @@ use std::sync::Arc; -use sea_orm::ActiveValue::NotSet; use sea_orm::{ ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, IntoActiveModel, - PaginatorTrait, QueryFilter, QueryOrder, + PaginatorTrait, QueryFilter, QueryOrder, Set, }; use callisto::db_enums::{ConvType, MergeStatus}; @@ -70,29 +69,52 @@ impl MrStorage { Ok(model) } - pub async fn get_open_mr_by_link( - &self, - link: &str, - ) -> Result, MegaError> { - let model = mega_mr::Entity::find() - .filter(mega_mr::Column::Link.eq(link)) - .filter(mega_mr::Column::Status.eq(MergeStatus::Open)) - .one(self.get_connection()) - .await - .unwrap(); - Ok(model) - } - pub async fn save_mr(&self, mr: mega_mr::Model) -> Result<(), MegaError> { let a_model = mr.into_active_model(); a_model.insert(self.get_connection()).await.unwrap(); Ok(()) } + pub async fn close_mr( + &self, + model: mega_mr::Model, + user_id: i64, + username: &str, + ) -> Result<(), MegaError> { + self.update_mr(model.clone()).await.unwrap(); + self.add_mr_conversation( + &model.link, + user_id, + ConvType::Closed, + Some(format!("{} closed this", username)), + ) + .await + .unwrap(); + Ok(()) + } + + pub async fn reopen_mr( + &self, + model: mega_mr::Model, + user_id: i64, + username: &str, + ) -> Result<(), MegaError> { + self.update_mr(model.clone()).await.unwrap(); + self.add_mr_conversation( + &model.link, + user_id, + ConvType::Reopen, + Some(format!("{} reopen this", username)), + ) + .await + .unwrap(); + Ok(()) + } + pub async fn update_mr(&self, mr: mega_mr::Model) -> Result<(), MegaError> { let mut a_model = mr.into_active_model(); a_model = a_model.reset_all(); - a_model.created_at = NotSet; + a_model.updated_at = Set(chrono::Utc::now().naive_utc()); a_model.update(self.get_connection()).await.unwrap(); Ok(()) } diff --git a/mega/config.toml b/mega/config.toml index c41b04380..1fe5771fe 100644 --- a/mega/config.toml +++ b/mega/config.toml @@ -53,10 +53,7 @@ obs_endpoint = "https://obs.cn-east-3.myhuaweicloud.com" ## Mega treats files under this directory as import repo and other directories as monorepo import_dir = "/third-part" -# The current mono Git HTTP server does not support authentication, so we provided a disabled operations here -disable_http_push = false - -# Support http authtication, login in with github and generate token before push +# Support http authentication, login in with github and generate token before push enable_http_auth = false # Set System Admin in directory init, replace the admin's github username here diff --git a/mono/config.toml b/mono/config.toml index 316dc5fbb..37a50f38a 100644 --- a/mono/config.toml +++ b/mono/config.toml @@ -53,10 +53,7 @@ obs_endpoint = "https://obs.cn-east-3.myhuaweicloud.com" ## Mega treats files under this directory as import repo and other directories as monorepo import_dir = "/third-part" -# The current mono Git HTTP server does not support authentication, so we provided a disabled operations here -disable_http_push = false - -# Support http authtication, login in with github and generate token before push +# Support http authentication, login in with github and generate token before push enable_http_auth = false # Set System Admin in directory init, replace the admin's github username here diff --git a/mono/src/api/issue/issue_router.rs b/mono/src/api/issue/issue_router.rs index 705a02ab9..1ff546454 100644 --- a/mono/src/api/issue/issue_router.rs +++ b/mono/src/api/issue/issue_router.rs @@ -18,6 +18,7 @@ pub fn routers() -> Router { .route("/issue/list", post(fetch_issue_list)) .route("/issue/new", post(new_issue)) .route("/issue/:link/close", post(close_issue)) + .route("/issue/:link/reopen", post(reopen_issue)) .route("/issue/:link/detail", get(issue_detail)) .route("/issue/:link/comment", post(save_comment)) .route("/issue/comment/:id/delete", post(delete_comment)) @@ -85,6 +86,7 @@ async fn new_issue( } async fn close_issue( + _: LoginUser, Path(link): Path, state: State, ) -> Result>, ApiError> { @@ -95,6 +97,18 @@ async fn close_issue( Ok(Json(res)) } +async fn reopen_issue( + _: LoginUser, + Path(link): Path, + state: State, +) -> Result>, ApiError> { + let res = match state.issue_stg().reopen_issue(&link).await { + Ok(_) => CommonResult::success(None), + Err(err) => CommonResult::failed(&err.to_string()), + }; + Ok(Json(res)) +} + async fn save_comment( user: LoginUser, Path(link): Path, diff --git a/mono/src/api/mr/mr_router.rs b/mono/src/api/mr/mr_router.rs index 9d77bdca5..40156ecc2 100644 --- a/mono/src/api/mr/mr_router.rs +++ b/mono/src/api/mr/mr_router.rs @@ -9,6 +9,7 @@ use axum::{ use bytes::Bytes; use callisto::db_enums::{ConvType, MergeStatus}; +use ceres::protocol::mr::MergeRequest; use common::model::{CommonPage, CommonResult, PageParams}; use saturn::ActionEnum; use taurus::event::api_request::{ApiRequestEvent, ApiType}; @@ -24,33 +25,100 @@ pub fn routers() -> Router { .route("/mr/list", post(fetch_mr_list)) .route("/mr/:link/detail", get(mr_detail)) .route("/mr/:link/merge", post(merge)) + .route("/mr/:link/close", post(close_mr)) + .route("/mr/:link/reopen", post(reopen_mr)) .route("/mr/:link/files", get(get_mr_files)) .route("/mr/:link/comment", post(save_comment)) .route("/mr/comment/:conv_id/delete", post(delete_comment)) } +async fn reopen_mr( + user: LoginUser, + Path(link): Path, + state: State, +) -> Result>, ApiError> { + if let Some(model) = state.mr_stg().get_mr(&link).await.unwrap() { + if model.status == MergeStatus::Closed { + util::check_permissions( + &user.name, + &model.path, + ActionEnum::EditMergeRequest, + state.clone(), + ) + .await + .unwrap(); + let mut mr: MergeRequest = model.into(); + mr.status = MergeStatus::Open; + let res = match state + .mr_stg() + .reopen_mr(mr.into(), user.user_id, &user.name) + .await + { + Ok(_) => CommonResult::success(None), + Err(err) => CommonResult::failed(&err.to_string()), + }; + return Ok(Json(res)); + } + } + Ok(Json(CommonResult::failed("not found"))) +} + +async fn close_mr( + user: LoginUser, + Path(link): Path, + state: State, +) -> Result>, ApiError> { + if let Some(model) = state.mr_stg().get_mr(&link).await.unwrap() { + if model.status == MergeStatus::Open { + util::check_permissions( + &user.name, + &model.path, + ActionEnum::EditMergeRequest, + state.clone(), + ) + .await + .unwrap(); + let mut mr: MergeRequest = model.into(); + mr.status = MergeStatus::Closed; + let res = match state + .mr_stg() + .close_mr(mr.into(), user.user_id, &user.name) + .await + { + Ok(_) => CommonResult::success(None), + Err(err) => CommonResult::failed(&err.to_string()), + }; + return Ok(Json(res)); + } + } + Ok(Json(CommonResult::failed("not found"))) +} + async fn merge( user: LoginUser, Path(link): Path, state: State, ) -> Result>, ApiError> { - if let Some(model) = state.mr_stg().get_open_mr_by_link(&link).await.unwrap() { - let path = model.path.clone(); - let _ = util::check_permissions( - &user.name, - &path, - ActionEnum::ApproveMergeRequest, - state.clone(), - ) - .await; - ApiRequestEvent::notify(ApiType::MergeRequest, &state.0.context.config); - let res = state.monorepo().merge_mr(&mut model.into()).await; - let res = match res { - Ok(_) => CommonResult::success(None), - Err(err) => CommonResult::failed(&err.to_string()), - }; - ApiRequestEvent::notify(ApiType::MergeDone, &state.0.context.config); - return Ok(Json(res)); + if let Some(model) = state.mr_stg().get_mr(&link).await.unwrap() { + if model.status == MergeStatus::Open { + let path = model.path.clone(); + util::check_permissions( + &user.name, + &path, + ActionEnum::ApproveMergeRequest, + state.clone(), + ) + .await + .unwrap(); + ApiRequestEvent::notify(ApiType::MergeRequest, &state.0.context.config); + let res = state.monorepo().merge_mr(&mut model.into()).await; + let res = match res { + Ok(_) => CommonResult::success(None), + Err(err) => CommonResult::failed(&err.to_string()), + }; + ApiRequestEvent::notify(ApiType::MergeDone, &state.0.context.config); + return Ok(Json(res)); + } } Ok(Json(CommonResult::failed("not found"))) } @@ -117,6 +185,7 @@ async fn get_mr_files( } async fn save_comment( + user: LoginUser, Path(link): Path, state: State, body: Bytes, @@ -127,7 +196,7 @@ async fn save_comment( let res = if let Some(model) = state.mr_stg().get_mr(&link).await.unwrap() { state .mr_stg() - .add_mr_conversation(&model.link, 0, ConvType::Comment, Some(json_string)) + .add_mr_conversation(&model.link, user.user_id, ConvType::Comment, Some(json_string)) .await .unwrap(); CommonResult::success(None) diff --git a/mono/src/server/https_server.rs b/mono/src/server/https_server.rs index d391ed6a6..d14503a01 100644 --- a/mono/src/server/https_server.rs +++ b/mono/src/server/https_server.rs @@ -212,9 +212,6 @@ pub async fn post_method_router( pack_protocol.service_type = Some(ServiceType::UploadPack); crate::git_protocol::http::git_upload_pack(req, pack_protocol).await } else if REGEX_GIT_RECEIVE_PACK.is_match(uri.path()) { - if state.context.config.monorepo.disable_http_push { - return Err(ProtocolError::Disabled); - } let mut pack_protocol = SmartProtocol::new( remove_git_suffix(uri.clone(), "/git-receive-pack"), state.context.clone(), diff --git a/moon/src/app/(dashboard)/issue/[id]/page.tsx b/moon/src/app/(dashboard)/issue/[id]/page.tsx index 0e5ab6419..3d5387295 100644 --- a/moon/src/app/(dashboard)/issue/[id]/page.tsx +++ b/moon/src/app/(dashboard)/issue/[id]/page.tsx @@ -70,6 +70,7 @@ export default function IssueDetailPage({ params }: { params: Params }) { } async function close_issue() { + set_to_loading(3); const res = await fetch(`/api/issue/${id}/close`, { method: 'POST', }); @@ -80,6 +81,18 @@ export default function IssueDetailPage({ params }: { params: Params }) { } }; + async function reopen_issue() { + set_to_loading(3); + const res = await fetch(`/api/issue/${id}/reopen`, { + method: 'POST', + }); + if (res) { + router.push( + "/issue" + ); + } + }; + async function save_comment(comment) { set_to_loading(3); const res = await fetch(`/api/issue/${id}/comment`, { @@ -125,6 +138,11 @@ export default function IssueDetailPage({ params }: { params: Params }) { } + {info && info.status === "closed" && + + + + } } ]; diff --git a/moon/src/app/(dashboard)/issue/page.tsx b/moon/src/app/(dashboard)/issue/page.tsx index 51a6e70d9..54c1c8ba9 100644 --- a/moon/src/app/(dashboard)/issue/page.tsx +++ b/moon/src/app/(dashboard)/issue/page.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react'; import React from 'react'; import { Flex, List, PaginationProps, Tag, Button, Tabs, Space, TabsProps, Segmented } from 'antd/lib'; import { format, formatDistance, fromUnixTime } from 'date-fns' -import { IssuesCloseOutlined, ExclamationCircleOutlined } from '@ant-design/icons'; +import { CheckCircleOutlined, ExclamationCircleOutlined } from '@ant-design/icons'; import Link from 'next/link'; @@ -56,9 +56,18 @@ export default function IssuePage() { const getStatusTag = (status: string) => { switch (status) { case 'open': - return open; + return open; case 'closed': - return closed; + return closed; + } + }; + + const getStatusIcon = (status: string) => { + switch (status) { + case 'open': + return ; + case 'closed': + return ; } }; @@ -111,7 +120,8 @@ export default function IssuePage() { + // + getStatusIcon(item.status) } title={{item.title} {getStatusTag(item.status)}} description={getDescription(item)} diff --git a/moon/src/app/(dashboard)/mr/[id]/page.tsx b/moon/src/app/(dashboard)/mr/[id]/page.tsx index 943710a3e..757d96015 100644 --- a/moon/src/app/(dashboard)/mr/[id]/page.tsx +++ b/moon/src/app/(dashboard)/mr/[id]/page.tsx @@ -1,11 +1,12 @@ 'use client' import { useEffect, useState } from "react"; import { Card, Button, List, Tabs, TabsProps, Space, Timeline, Flex } from 'antd/lib'; -import { CommentOutlined, MergeOutlined, CloseCircleOutlined } from '@ant-design/icons'; +import { CommentOutlined, MergeOutlined, CloseCircleOutlined, PullRequestOutlined } from '@ant-design/icons'; import { formatDistance, fromUnixTime } from 'date-fns'; import RichEditor from "@/components/rich-editor/RichEditor"; import MRComment from "@/components/MRComment"; import * as React from 'react' +import { useRouter } from "next/navigation"; interface MRDetail { status: string, @@ -36,7 +37,7 @@ export default function MRDetailPage({ params }: { params: Params }) { ); const [filedata, setFileData] = useState([]); const [loadings, setLoadings] = useState([]); - + const router = useRouter(); const checkLogin = async () => { const res = await fetch(`/api/auth`); @@ -89,9 +90,39 @@ export default function MRDetailPage({ params }: { params: Params }) { }); if (res) { cancel_loading(1); + router.push( + "/mr" + ); + } + }; + + async function close_mr() { + set_to_loading(3); + const res = await fetch(`/api/mr/${id}/close`, { + method: 'POST', + }); + if (res) { + cancel_loading(3); + router.push( + "/mr" + ); } }; + async function reopen_mr() { + set_to_loading(3); + const res = await fetch(`/api/mr/${id}/reopen`, { + method: 'POST', + }); + if (res) { + cancel_loading(3); + router.push( + "/mr" + ); + } + }; + + async function save_comment(comment) { set_to_loading(3); const res = await fetch(`/api/mr/${id}/comment`, { @@ -111,7 +142,8 @@ export default function MRDetailPage({ params }: { params: Params }) { switch (conv.conv_type) { case "Comment": icon = ; children = ; break case "Merged": icon = ; children = "Merged via the queue into main " + formatDistance(fromUnixTime(conv.created_at), new Date(), { addSuffix: true }); break; - case "Closed": icon = ; children = conv.comment; + case "Closed": icon = ; children = conv.comment; break; + case "Reopen": icon = ; children = conv.comment; break; }; const element = { @@ -131,8 +163,14 @@ export default function MRDetailPage({ params }: { params: Params }) {

Add a comment

- - + + {mrDetail && mrDetail.status === "open" && + + } + {mrDetail && mrDetail.status === "closed" && + + } + }, @@ -141,7 +179,6 @@ export default function MRDetailPage({ params }: { params: Params }) { label: 'Files Changed', children: Change File List} bordered dataSource={filedata} diff --git a/moon/src/app/(dashboard)/mr/page.tsx b/moon/src/app/(dashboard)/mr/page.tsx index 5a61bc6c7..dbfb76a68 100644 --- a/moon/src/app/(dashboard)/mr/page.tsx +++ b/moon/src/app/(dashboard)/mr/page.tsx @@ -1,10 +1,11 @@ 'use client' import { useEffect, useState } from 'react'; import React from 'react'; -import { List, PaginationProps, Tag } from 'antd/lib'; +import { List, PaginationProps, Tag, Tabs, TabsProps } from 'antd/lib'; import { format, formatDistance, fromUnixTime } from 'date-fns' -import { MergeOutlined } from '@ant-design/icons'; +import { MergeOutlined, PullRequestOutlined, CloseCircleOutlined } from '@ant-design/icons'; import Link from 'next/link'; +import { Heading } from '@/components/catalyst/heading' interface MrInfoItem { @@ -20,6 +21,7 @@ export default function MergeRequestPage() { const [mrList, setMrList] = useState([]); const [numTotal, setNumTotal] = useState(0); const [pageSize, setPageSize] = useState(10); + const [status, setStatus] = useState("open") const fetchData = async (page: number, per_page: number) => { try { @@ -34,7 +36,7 @@ export default function MergeRequestPage() { per_page: per_page }, additional: { - status: "" + status: status } }), }); @@ -50,7 +52,7 @@ export default function MergeRequestPage() { useEffect(() => { fetchData(1, pageSize); - }, [pageSize]); + }, [pageSize, status]); const getStatusTag = (status: string) => { switch (status) { @@ -63,6 +65,17 @@ export default function MergeRequestPage() { } }; + const getStatusIcon = (status: string) => { + switch (status) { + case 'open': + return ; + case 'closed': + return ; + case 'merged': + return ; + } + }; + const getDescription = (item: MrInfoItem) => { switch (item.status) { case 'open': @@ -82,22 +95,50 @@ export default function MergeRequestPage() { fetchData(current, pageSize); }; + const tabsChange = (activeKey: string) => { + if (activeKey === '1') { + setStatus("open"); + } else { + setStatus("closed"); + } + } + + const tab_items: TabsProps['items'] = [ + { + key: '1', + label: 'Open', + }, + { + key: '2', + label: 'Closed', + } + ]; + + + return ( - ( - - - } - title={{`MR ${item.link} open by Mega automacticlly${item.title}`}{getStatusTag(item.status)}} - description={getDescription(item)} - /> - - )} - /> + <> + Merge Request +
+ + + ( + + {`MR ${item.link} open by Mega automacticlly${item.title}`}{getStatusTag(item.status)}} + description={getDescription(item)} + /> + + )} + /> + + ) } \ No newline at end of file diff --git a/moon/src/app/(dashboard)/tree/[...path]/page.tsx b/moon/src/app/(dashboard)/tree/[...path]/page.tsx index 5a51a3efc..45453d0aa 100644 --- a/moon/src/app/(dashboard)/tree/[...path]/page.tsx +++ b/moon/src/app/(dashboard)/tree/[...path]/page.tsx @@ -62,7 +62,7 @@ export default function Page({ params }: { params: Params }) { return ( - + { cloneBtn && diff --git a/moon/src/app/api/auth/route.ts b/moon/src/app/api/auth/route.ts index 9bd549a0b..ffd659eed 100644 --- a/moon/src/app/api/auth/route.ts +++ b/moon/src/app/api/auth/route.ts @@ -2,8 +2,7 @@ import { isLoginIn } from '@/app/lib/dal'; export async function GET(request: Request) { - const login = isLoginIn(); - + const login = await isLoginIn(); if (!login) { return new Response(null, { status: 401 }) } diff --git a/moon/src/app/api/issue/[id]/close/route.ts b/moon/src/app/api/issue/[id]/close/route.ts index 119799368..4a6ca5812 100644 --- a/moon/src/app/api/issue/[id]/close/route.ts +++ b/moon/src/app/api/issue/[id]/close/route.ts @@ -6,6 +6,9 @@ export async function POST(request: Request, props: { params: Params }) { const endpoint = process.env.MEGA_INTERNAL_HOST; const res = await fetch(`${endpoint}/api/v1/issue/${params.id}/close`, { method: 'POST', + headers: { + 'Cookie': request.headers.get('cookie') || '', + }, }) const data = await res.json() diff --git a/moon/src/app/api/issue/[id]/reopen/route.ts b/moon/src/app/api/issue/[id]/reopen/route.ts new file mode 100644 index 000000000..dc4beb9a0 --- /dev/null +++ b/moon/src/app/api/issue/[id]/reopen/route.ts @@ -0,0 +1,16 @@ +type Params = Promise<{ id: string }> + +export async function POST(request: Request, props: { params: Params }) { + const params = await props.params + + const endpoint = process.env.MEGA_INTERNAL_HOST; + const res = await fetch(`${endpoint}/api/v1/issue/${params.id}/reopen`, { + method: 'POST', + headers: { + 'Cookie': request.headers.get('cookie') || '', + }, + }) + const data = await res.json() + + return Response.json({ data }) +} \ No newline at end of file diff --git a/moon/src/app/api/mr/[id]/close/route.ts b/moon/src/app/api/mr/[id]/close/route.ts new file mode 100644 index 000000000..a6b5f0f9f --- /dev/null +++ b/moon/src/app/api/mr/[id]/close/route.ts @@ -0,0 +1,28 @@ +import { verifySession } from "@/app/lib/dal"; + +export const dynamic = 'force-dynamic' // defaults to auto + +type Params = Promise<{ id: string }> + +export async function POST(request: Request, props: { params: Params }) { + const params = await props.params; + + const session = await verifySession() + + // Check if the user is authenticated + if (!session) { + // User is not authenticated + return new Response(null, { status: 401 }) + } + + const endpoint = process.env.MEGA_INTERNAL_HOST; + const res = await fetch(`${endpoint}/api/v1/mr/${params.id}/close`, { + method: 'POST', + headers: { + 'Cookie': request.headers.get('cookie') || '', + }, + }) + const data = await res.json() + + return Response.json({ data }) +} \ No newline at end of file diff --git a/moon/src/app/api/mr/[id]/comment/route.ts b/moon/src/app/api/mr/[id]/comment/route.ts index 37896097f..7997bc5fb 100644 --- a/moon/src/app/api/mr/[id]/comment/route.ts +++ b/moon/src/app/api/mr/[id]/comment/route.ts @@ -2,7 +2,7 @@ import { verifySession } from "@/app/lib/dal"; type Params = Promise<{ id: string }> -export async function POST(request: Request, props: { params: Params }) { +export async function POST(request: Request, props: { params: Params }) { const params = await props.params const session = await verifySession() @@ -10,8 +10,8 @@ export async function POST(request: Request, props: { params: Params }) { // Check if the user is authenticated if (!session) { - // User is not authenticated - return new Response(null, { status: 401 }) + // User is not authenticated + return new Response(null, { status: 401 }) } const endpoint = process.env.MEGA_INTERNAL_HOST; @@ -19,6 +19,7 @@ export async function POST(request: Request, props: { params: Params }) { method: 'POST', headers: { 'Content-Type': 'application/json', + 'Cookie': request.headers.get('cookie') || '', }, body: JSON.stringify(jsonData), }) diff --git a/moon/src/app/api/mr/[id]/reopen/route.ts b/moon/src/app/api/mr/[id]/reopen/route.ts new file mode 100644 index 000000000..48b1dc611 --- /dev/null +++ b/moon/src/app/api/mr/[id]/reopen/route.ts @@ -0,0 +1,28 @@ +import { verifySession } from "@/app/lib/dal"; + +export const dynamic = 'force-dynamic' // defaults to auto + +type Params = Promise<{ id: string }> + +export async function POST(request: Request, props: { params: Params }) { + const params = await props.params; + + const session = await verifySession() + + // Check if the user is authenticated + if (!session) { + // User is not authenticated + return new Response(null, { status: 401 }) + } + + const endpoint = process.env.MEGA_INTERNAL_HOST; + const res = await fetch(`${endpoint}/api/v1/mr/${params.id}/reopen`, { + method: 'POST', + headers: { + 'Cookie': request.headers.get('cookie') || '', + }, + }) + const data = await res.json() + + return Response.json({ data }) +} \ No newline at end of file diff --git a/moon/src/app/lib/dal.ts b/moon/src/app/lib/dal.ts index 580ba5086..70a4489ac 100644 --- a/moon/src/app/lib/dal.ts +++ b/moon/src/app/lib/dal.ts @@ -5,7 +5,8 @@ import { cache } from 'react' import { redirect } from 'next/navigation' export const verifySession = cache(async () => { - const session = (await cookies()).get('SESSION')?.value + const cookieStore = await cookies() + const session = cookieStore.get('SESSION')?.value if (!session) { redirect('/login') } @@ -13,6 +14,7 @@ export const verifySession = cache(async () => { }) export const isLoginIn = async () => { - const session = (await cookies()).get('SESSION')?.value + const cookieStore = await cookies() + const session = cookieStore.get('SESSION')?.value return session != null } diff --git a/saturn/src/lib.rs b/saturn/src/lib.rs index c01b2ac95..ecc8ed949 100644 --- a/saturn/src/lib.rs +++ b/saturn/src/lib.rs @@ -30,16 +30,16 @@ pub enum ActionEnum { impl Display for ActionEnum { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { - ActionEnum::CreateMergeRequest => "Comment", - ActionEnum::EditIssue => "Deploy", - ActionEnum::EditMergeRequest => "Commit", - ActionEnum::AssignIssue => "ForcePush", + ActionEnum::CreateMergeRequest => "createMergeRequest", + ActionEnum::EditIssue => "editIssue", + ActionEnum::EditMergeRequest => "editMergeRequest", + ActionEnum::AssignIssue => "assignIssue", ActionEnum::ApproveMergeRequest => "approveMergeRequest", - ActionEnum::AddMaintainer => "Review", - ActionEnum::AddAdmin => "Approve", - ActionEnum::DeleteRepo => "MergeQueue", - ActionEnum::DeleteIssue => "Merged", - ActionEnum::DeleteMergeRequest => "Merged", + ActionEnum::AddMaintainer => "addMaintainer", + ActionEnum::AddAdmin => "addAdmin", + ActionEnum::DeleteRepo => "deleteRepo", + ActionEnum::DeleteIssue => "deleteIssue", + ActionEnum::DeleteMergeRequest => "deleteMergeRequest", }; write!(f, "{}", s) } diff --git a/sql/postgres/pg_20241029__init.sql b/sql/postgres/pg_20241029__init.sql index da11cb846..d8b5bc915 100644 --- a/sql/postgres/pg_20241029__init.sql +++ b/sql/postgres/pg_20241029__init.sql @@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS "mega_mr" ( ); CREATE INDEX "idx_mr_path" ON "mega_mr" ("path"); -CREATE TABLE IF NOT EXISTS "mega_conversion" ( +CREATE TABLE IF NOT EXISTS "mega_conversation" ( "id" BIGINT PRIMARY KEY, "link" VARCHAR(20) NOT NULL, "user_id" BIGINT NOT NULL, @@ -62,7 +62,7 @@ CREATE TABLE IF NOT EXISTS "mega_conversion" ( "created_at" TIMESTAMP NOT NULL, "updated_at" TIMESTAMP NOT NULL ); -CREATE INDEX "idx_conversation" ON "mega_conversion" ("link"); +CREATE INDEX "idx_conversation" ON "mega_conversation" ("link"); CREATE TABLE IF NOT EXISTS "mega_issue" ( diff --git a/sql/sqlite/sqlite_20241029_init.sql b/sql/sqlite/sqlite_20241029_init.sql index 866c0db87..c8793ea08 100644 --- a/sql/sqlite/sqlite_20241029_init.sql +++ b/sql/sqlite/sqlite_20241029_init.sql @@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS "mega_mr" ( ); CREATE INDEX "idx_mr_path" ON "mega_mr" ("path"); -CREATE TABLE IF NOT EXISTS "mega_conversion" ( +CREATE TABLE IF NOT EXISTS "mega_conversation" ( "id" INTEGER PRIMARY KEY, "link" INTEGER NOT NULL, "user_id" INTEGER NOT NULL, @@ -62,7 +62,7 @@ CREATE TABLE IF NOT EXISTS "mega_conversion" ( "created_at" TEXT NOT NULL, "updated_at" TEXT NOT NULL ); -CREATE INDEX "idx_conversation" ON "mega_conversion" ("link"); +CREATE INDEX "idx_conversation" ON "mega_conversation" ("link"); CREATE TABLE IF NOT EXISTS "mega_issue" ( "id" INTEGER PRIMARY KEY,