2ae9196
ZhenYi
feat(lib/git): add HTTP handler tree with routes and errors across analysis, archives, blobs, branches, commits, conflicts, content, diffs, hooks, lfs, logs, maintenance, packs, patches, pipelines, refs, remotes, repos, signatures, submodules, tags, trees
2ae9196
use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::Arc;
use russh::server::{Auth, Handler, Msg, Session};
use russh::{Channel, ChannelId};
use tokio::sync::OwnedSemaphorePermit;
use uuid::Uuid;
use models::users::user;
use crate::ssh::handler::git_op::GitOperation;
use crate::ssh::service::GitSshService;
pub mod git_op;
mod auth;
mod channel;
mod command;
#[derive(Default)]
pub struct ChannelState {
pub buffer: Vec<u8>,
pub git_op: Option<GitOperation>,
pub repo_id: Option<Uuid>,
pub space_id: Option<Uuid>,
pub actor_id: Option<Uuid>,
pub buffer_overflow: bool,
}
pub struct GitSshHandler {
pub service: Arc<GitSshService>,
pub client_addr: Option<SocketAddr>,
pub session_permit: Option<OwnedSemaphorePermit>,
pub operator: Option<user::Model>,
pub channels: HashMap<ChannelId, ChannelState>,
pub over_capacity: bool,
}
impl GitSshHandler {
pub fn new(
service: Arc<GitSshService>,
client_addr: Option<SocketAddr>,
session_permit: Option<OwnedSemaphorePermit>,
) -> Self {
let over_capacity = session_permit.is_none();
Self {
service,
client_addr,
session_permit,
operator: None,
channels: HashMap::new(),
over_capacity,
}
}
pub fn config(&self) -> &config::git::GitSshConfig {
&self.service.config
}
}
impl Handler for GitSshHandler {
type Error = russh::Error;
async fn auth_none(&mut self, _user: &str) -> Result<Auth, Self::Error> {
Ok(Auth::reject())
}
async fn auth_password(&mut self, _user: &str, _password: &str) -> Result<Auth, Self::Error> {
Ok(Auth::reject())
}
async fn auth_publickey_offered(
&mut self,
user: &str,
public_key: &russh::keys::PublicKey,
) -> Result<Auth, Self::Error> {
self.auth_publickey_offered_impl(user, public_key).await
}
async fn auth_publickey(
&mut self,
user: &str,
public_key: &russh::keys::PublicKey,
) -> Result<Auth, Self::Error> {
self.auth_publickey_impl(user, public_key).await
}
async fn auth_openssh_certificate(
&mut self,
_user: &str,
_certificate: &russh::keys::Certificate,
) -> Result<Auth, Self::Error> {
Ok(Auth::reject())
}
async fn authentication_banner(&mut self) -> Result<Option<String>, Self::Error> {
Ok(self.config().banner.clone())
}
async fn channel_open_session(
&mut self,
_channel: Channel<Msg>,
reply: russh::server::ChannelOpenHandle,
_session: &mut Session,
) -> Result<(), Self::Error> {
reply.accept().await;
Ok(())
}
async fn channel_close(
&mut self,
channel: ChannelId,
_session: &mut Session,
) -> Result<(), Self::Error> {
self.channel_close_impl(channel).await;
Ok(())
}
async fn channel_eof(
&mut self,
channel: ChannelId,
session: &mut Session,
) -> Result<(), Self::Error> {
self.channel_eof_impl(channel, session).await
}
async fn data(
&mut self,
channel: ChannelId,
data: &[u8],
session: &mut Session,
) -> Result<(), Self::Error> {
self.data_impl(channel, data, session).await
}
async fn exec_request(
&mut self,
channel: ChannelId,
data: &[u8],
session: &mut Session,
) -> Result<(), Self::Error> {
self.exec_request_impl(channel, data, session).await
}
async fn pty_request(
&mut self,
_channel: ChannelId,
_term: &str,
_col_width: u32,
_row_height: u32,
_pix_width: u32,
_pix_height: u32,
_modes: &[(russh::Pty, u32)],
session: &mut Session,
) -> Result<(), Self::Error> {
let _ = session.flush();
Ok(())
}
async fn shell_request(
&mut self,
channel: ChannelId,
session: &mut Session,
) -> Result<(), Self::Error> {
self.shell_request_impl(channel, session).await
}
async fn subsystem_request(
&mut self,
_channel: ChannelId,
_name: &str,
session: &mut Session,
) -> Result<(), Self::Error> {
let _ = session.flush();
Ok(())
}
async fn env_request(
&mut self,
_channel: ChannelId,
_variable_name: &str,
_variable_value: &str,
session: &mut Session,
) -> Result<(), Self::Error> {
let _ = session.flush();
Ok(())
}
async fn window_change_request(
&mut self,
_channel: ChannelId,
_col_width: u32,
_row_height: u32,
_pix_width: u32,
_pix_height: u32,
session: &mut Session,
) -> Result<(), Self::Error> {
let _ = session.flush();
Ok(())
}
}