163 lines
4.6 KiB
Rust
163 lines
4.6 KiB
Rust
use model::{
|
|
repos::{repo::RepoModel, repo_history_name::RepoHistoryNameModel},
|
|
users::user::UserModel,
|
|
workspace::{
|
|
wk_history_name::WkHistoryNameModel, wk_member::WkMemberModel,
|
|
workspace::WorkspaceModel,
|
|
},
|
|
};
|
|
use uuid::Uuid;
|
|
|
|
use crate::{
|
|
AppGitState,
|
|
errors::{GitError, GitResult},
|
|
};
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct DbRepoStatus {
|
|
pub repo: RepoModel,
|
|
pub wk: WorkspaceModel,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub enum MemberRole {
|
|
Owner,
|
|
Admin,
|
|
Member,
|
|
}
|
|
|
|
impl MemberRole {
|
|
pub fn can_write(self) -> bool {
|
|
matches!(self, Self::Owner | Self::Admin)
|
|
}
|
|
}
|
|
|
|
impl AppGitState {
|
|
pub async fn repo(
|
|
&self,
|
|
wk_name: String,
|
|
repo_name: String,
|
|
) -> GitResult<DbRepoStatus> {
|
|
let wk = self.resolve_wk(&wk_name).await?;
|
|
let repo = self.resolve_repo(wk.id, &repo_name).await?;
|
|
|
|
Ok(DbRepoStatus { repo, wk })
|
|
}
|
|
|
|
pub async fn member_check(
|
|
&self,
|
|
status: &DbRepoStatus,
|
|
user: &UserModel,
|
|
) -> GitResult<Option<MemberRole>> {
|
|
self.member_check_by_user_id(status, user.id).await
|
|
}
|
|
|
|
pub async fn member_check_by_user_id(
|
|
&self,
|
|
status: &DbRepoStatus,
|
|
user_id: Uuid,
|
|
) -> GitResult<Option<MemberRole>> {
|
|
let member = db::sqlx::query_as::<_, WkMemberModel>(
|
|
"SELECT wk, \"user\", owner, admin, join_at, leave_at \
|
|
FROM wk_member \
|
|
WHERE wk = $1 AND \"user\" = $2 AND leave_at IS NULL",
|
|
)
|
|
.bind(status.wk.id)
|
|
.bind(user_id)
|
|
.fetch_optional(self.db.reader())
|
|
.await?;
|
|
|
|
Ok(member.map(|member| {
|
|
if member.owner {
|
|
MemberRole::Owner
|
|
} else if member.admin {
|
|
MemberRole::Admin
|
|
} else {
|
|
MemberRole::Member
|
|
}
|
|
}))
|
|
}
|
|
|
|
async fn resolve_wk(&self, name: &str) -> GitResult<WorkspaceModel> {
|
|
if let Some(wk) = db::sqlx::query_as::<_, WorkspaceModel>(
|
|
"SELECT id, name, description, avatar_url, created_at \
|
|
FROM workspace \
|
|
WHERE name = $1",
|
|
)
|
|
.bind(&name)
|
|
.fetch_optional(self.db.reader())
|
|
.await?
|
|
{
|
|
return Ok(wk);
|
|
}
|
|
|
|
let Some(history) = db::sqlx::query_as::<_, WkHistoryNameModel>(
|
|
"SELECT id, wk, name, changed_by, created_at \
|
|
FROM wk_history_name \
|
|
WHERE name = $1 \
|
|
ORDER BY created_at DESC \
|
|
LIMIT 1",
|
|
)
|
|
.bind(&name)
|
|
.fetch_optional(self.db.reader())
|
|
.await?
|
|
else {
|
|
return Err(GitError::RepoNotFound);
|
|
};
|
|
|
|
db::sqlx::query_as::<_, WorkspaceModel>(
|
|
"SELECT id, name, description, avatar_url, created_at \
|
|
FROM workspace \
|
|
WHERE id = $1",
|
|
)
|
|
.bind(history.wk)
|
|
.fetch_optional(self.db.reader())
|
|
.await?
|
|
.ok_or(GitError::RepoNotFound)
|
|
}
|
|
|
|
async fn resolve_repo(&self, wk: Uuid, name: &str) -> GitResult<RepoModel> {
|
|
if let Some(repo) = db::sqlx::query_as::<_, RepoModel>(
|
|
"SELECT id, wk, name, description, default_branch, visibility, size_bytes, \
|
|
is_archived, is_template, is_mirror, created_by, created_at, updated_at, deleted_at \
|
|
FROM repo \
|
|
WHERE wk = $1 AND name = $2 AND deleted_at IS NULL",
|
|
)
|
|
.bind(wk)
|
|
.bind(&name)
|
|
.fetch_optional(self.db.reader())
|
|
.await?
|
|
{
|
|
return Ok(repo);
|
|
}
|
|
|
|
let Some(history) = db::sqlx::query_as::<_, RepoHistoryNameModel>(
|
|
"SELECT h.id, h.repo, h.name, h.changed_by, h.created_at \
|
|
FROM repo_history_name h \
|
|
INNER JOIN repo r ON h.repo = r.id \
|
|
WHERE h.name = $1 AND r.wk = $2 AND r.deleted_at IS NULL \
|
|
ORDER BY h.created_at DESC \
|
|
LIMIT 1",
|
|
)
|
|
.bind(&name)
|
|
.bind(wk)
|
|
.fetch_optional(self.db.reader())
|
|
.await?
|
|
else {
|
|
return Err(GitError::RepoNotFound);
|
|
};
|
|
|
|
db::sqlx::query_as::<_, RepoModel>(
|
|
"SELECT id, wk, name, description, default_branch, visibility, size_bytes, \
|
|
is_archived, is_template, is_mirror, created_by, created_at, updated_at, deleted_at \
|
|
FROM repo \
|
|
WHERE id = $1 AND wk = $2 AND deleted_at IS NULL",
|
|
)
|
|
.bind(history.repo)
|
|
.bind(wk)
|
|
.fetch_optional(self.db.reader())
|
|
.await?
|
|
.ok_or(GitError::RepoNotFound)
|
|
}
|
|
}
|