Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ serde = { workspace = true }
config = { workspace = true }
envsubst = "0.2.1"
rand = { workspace = true }
serde_json = { workspace = true }
2 changes: 0 additions & 2 deletions common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,
Expand All @@ -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![
Expand Down
19 changes: 19 additions & 0 deletions common/src/utils.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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")
}
5 changes: 1 addition & 4 deletions docker/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions jupiter/callisto/src/db_enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub enum ConvType {
MergeQueue,
Merged,
Closed,
Reopen,
}

impl Display for ConvType {
Expand All @@ -92,6 +93,7 @@ impl Display for ConvType {
ConvType::MergeQueue => "MergeQueue",
ConvType::Merged => "Merged",
ConvType::Closed => "Closed",
ConvType::Reopen => "Reopen",
};
write!(f, "{}", s)
}
Expand Down
9 changes: 9 additions & 0 deletions jupiter/src/storage/issue_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
54 changes: 38 additions & 16 deletions jupiter/src/storage/mr_storage.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -70,29 +69,52 @@ impl MrStorage {
Ok(model)
}

pub async fn get_open_mr_by_link(
&self,
link: &str,
) -> Result<Option<mega_mr::Model>, 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(())
}
Expand Down
5 changes: 1 addition & 4 deletions mega/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 1 addition & 4 deletions mono/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions mono/src/api/issue/issue_router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub fn routers() -> Router<MonoApiServiceState> {
.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))
Expand Down Expand Up @@ -85,6 +86,7 @@ async fn new_issue(
}

async fn close_issue(
_: LoginUser,
Path(link): Path<String>,
state: State<MonoApiServiceState>,
) -> Result<Json<CommonResult<String>>, ApiError> {
Expand All @@ -95,6 +97,18 @@ async fn close_issue(
Ok(Json(res))
}

async fn reopen_issue(
_: LoginUser,
Path(link): Path<String>,
state: State<MonoApiServiceState>,
) -> Result<Json<CommonResult<String>>, 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<String>,
Expand Down
105 changes: 87 additions & 18 deletions mono/src/api/mr/mr_router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -24,33 +25,100 @@ pub fn routers() -> Router<MonoApiServiceState> {
.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<String>,
state: State<MonoApiServiceState>,
) -> Result<Json<CommonResult<String>>, 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<String>,
state: State<MonoApiServiceState>,
) -> Result<Json<CommonResult<String>>, 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<String>,
state: State<MonoApiServiceState>,
) -> Result<Json<CommonResult<String>>, 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")))
}
Expand Down Expand Up @@ -117,6 +185,7 @@ async fn get_mr_files(
}

async fn save_comment(
user: LoginUser,
Path(link): Path<String>,
state: State<MonoApiServiceState>,
body: Bytes,
Expand All @@ -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)
Expand Down
3 changes: 0 additions & 3 deletions mono/src/server/https_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Loading