mirror of https://github.com/realaravinth/gitpad
feat: gist index view
parent
edca78906e
commit
2db966c04a
|
@ -51,6 +51,7 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
|||
cfg.service(get_comment);
|
||||
cfg.service(get_gist_comments);
|
||||
cfg.service(delete_comment);
|
||||
cfg.service(index);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
@ -244,10 +245,33 @@ async fn delete_comment(
|
|||
}
|
||||
}
|
||||
|
||||
#[my_codegen::get(
|
||||
path = "crate::V1_API_ROUTES.gist.gist_index",
|
||||
wrap = "super::get_auth_middleware()"
|
||||
)]
|
||||
async fn index(
|
||||
path: web::Path<PostCommentPath>,
|
||||
id: Identity,
|
||||
db: crate::DB,
|
||||
data: AppData,
|
||||
) -> ServiceResult<impl Responder> {
|
||||
let username = id.identity().unwrap();
|
||||
let gist = db.get_gist(&path.gist).await?;
|
||||
if gist.visibility == GistVisibility::Private && username != gist.owner {
|
||||
return Err(ServiceError::GistNotFound);
|
||||
}
|
||||
|
||||
let resp = data
|
||||
.gist_preview(db.as_ref(), &mut GistID::ID(&path.gist))
|
||||
.await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(resp))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::data::api::v1::gists::{ContentType, FileType};
|
||||
use crate::data::api::v1::gists::{ContentType, FileType, GistInfo};
|
||||
use crate::tests::*;
|
||||
use actix_web::ResponseError;
|
||||
|
||||
|
@ -359,11 +383,10 @@ mod tests {
|
|||
assert_eq!(&content, &req_escaped_file);
|
||||
}
|
||||
// 2. Unlisted gists
|
||||
let one_file = [files[0].clone()];
|
||||
let mut msg = CreateGistRequest {
|
||||
description: None,
|
||||
visibility: GistVisibility::Unlisted,
|
||||
files: one_file.to_vec(),
|
||||
files: files.to_vec(),
|
||||
};
|
||||
|
||||
let create_gist_resp = test::call_service(
|
||||
|
@ -378,7 +401,7 @@ mod tests {
|
|||
let unlisted = unlisted.id;
|
||||
|
||||
get_file_path.gist = unlisted.clone();
|
||||
for file in one_file.iter() {
|
||||
for file in files.iter() {
|
||||
// requesting user is owner
|
||||
get_file_path.file = file.filename.clone();
|
||||
let path = V1_API_ROUTES.gist.get_file_route(&get_file_path);
|
||||
|
@ -428,7 +451,7 @@ mod tests {
|
|||
let private = private.id;
|
||||
|
||||
get_file_path.gist = private.clone();
|
||||
for file in one_file.iter() {
|
||||
for file in files.iter() {
|
||||
get_file_path.file = file.filename.clone();
|
||||
let path = V1_API_ROUTES.gist.get_file_route(&get_file_path);
|
||||
println!("Trying to get file {path}");
|
||||
|
@ -783,5 +806,59 @@ mod tests {
|
|||
println!("delete comments; authenticated comment_owner == owner");
|
||||
let resp = delete_request!(&app, &del_comment_path, cookies.clone());
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
|
||||
/*
|
||||
*
|
||||
* ============================================
|
||||
* Gist index
|
||||
* ============================================
|
||||
*
|
||||
*/
|
||||
let mut gist_index = PostCommentPath {
|
||||
username: NAME.into(),
|
||||
gist: "non-existant".into(),
|
||||
};
|
||||
|
||||
// unauthenticated request
|
||||
let path = V1_API_ROUTES.gist.get_gist_index(&gist_index);
|
||||
let resp = get_request!(&app, &path);
|
||||
assert_eq!(resp.status(), StatusCode::FOUND);
|
||||
|
||||
// non-existant gist
|
||||
let path = V1_API_ROUTES.gist.get_gist_index(&gist_index);
|
||||
let resp = get_request!(&app, &path, cookies.clone());
|
||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
let err: ErrorToResponse = test::read_body_json(resp).await;
|
||||
assert_eq!(err.error, format!("{}", ServiceError::GistNotFound));
|
||||
|
||||
// get private gist with user that doesn't have access
|
||||
gist_index.gist = private.clone();
|
||||
let path = V1_API_ROUTES.gist.get_gist_index(&gist_index);
|
||||
let resp = get_request!(&app, &path, cookies2.clone());
|
||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
let err: ErrorToResponse = test::read_body_json(resp).await;
|
||||
assert_eq!(err.error, format!("{}", ServiceError::GistNotFound));
|
||||
|
||||
// get private gist with user=owner
|
||||
gist_index.gist = private.clone();
|
||||
let path = V1_API_ROUTES.gist.get_gist_index(&gist_index);
|
||||
let resp = get_request!(&app, &path, cookies.clone());
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
let preview: GistInfo = test::read_body_json(resp).await;
|
||||
assert_eq!(preview.owner, NAME);
|
||||
assert_eq!(preview.files.len(), files.len());
|
||||
for file in preview.files.iter() {
|
||||
let processed: Vec<FileInfo> = files
|
||||
.iter()
|
||||
.map(|f| FileInfo {
|
||||
filename: escape_spaces(&f.filename),
|
||||
content: f.content.clone(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
assert!(processed
|
||||
.iter()
|
||||
.any(|f| f.filename == file.filename && f.content == file.content));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,12 +79,15 @@ pub struct Gist {
|
|||
pub get_gist_comments: &'static str,
|
||||
/// delete comment
|
||||
pub delete_comment: &'static str,
|
||||
/// gist index page
|
||||
pub gist_index: &'static str,
|
||||
}
|
||||
|
||||
impl Gist {
|
||||
/// create new instance of Authentication route
|
||||
pub const fn new() -> Gist {
|
||||
let new = "/api/v1/gist/new";
|
||||
let gist_index = "/api/v1/gist/profile/{username}/{gist}";
|
||||
let get_file = "/api/v1/gist/profile/{username}/{gist}/contents/{file}";
|
||||
let post_comment = "/api/v1/gist/profile/{username}/{gist}/comments";
|
||||
let get_comment = "/api/v1/gist/profile/{username}/{gist}/comment/{comment_id}";
|
||||
|
@ -97,6 +100,7 @@ impl Gist {
|
|||
get_comment,
|
||||
get_gist_comments,
|
||||
delete_comment,
|
||||
gist_index,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,6 +120,13 @@ impl Gist {
|
|||
.replace("{gist}", &components.gist)
|
||||
}
|
||||
|
||||
/// get gist index route with placeholders replaced with values provided.
|
||||
pub fn get_gist_index(&self, components: &PostCommentPath) -> String {
|
||||
self.gist_index
|
||||
.replace("{username}", &components.username)
|
||||
.replace("{gist}", &components.gist)
|
||||
}
|
||||
|
||||
/// get post_comment route with placeholders replaced with values provided.
|
||||
pub fn get_gist_comments(&self, components: &PostCommentPath) -> String {
|
||||
self.get_post_comment_route(components)
|
||||
|
@ -228,6 +239,7 @@ mod tests {
|
|||
const COMMENT_ID: i64 = 5;
|
||||
let get_file = format!("/api/v1/gist/profile/{NAME}/{GIST}/contents/{FILE}");
|
||||
let post_comment = format!("/api/v1/gist/profile/{NAME}/{GIST}/comments");
|
||||
let gist_index = format!("/api/v1/gist/profile/{NAME}/{GIST}");
|
||||
let get_gist_comments = format!("/api/v1/gist/profile/{NAME}/{GIST}/comments");
|
||||
let get_comment = format!("/api/v1/gist/profile/{NAME}/{GIST}/comment/{COMMENT_ID}");
|
||||
let delete_comment = format!("/api/v1/gist/profile/{NAME}/{GIST}/comment/{COMMENT_ID}");
|
||||
|
@ -276,5 +288,7 @@ mod tests {
|
|||
delete_comment,
|
||||
ROUTES.gist.get_delete_comment_route(&delete_comment_path)
|
||||
);
|
||||
|
||||
assert_eq!(gist_index, ROUTES.gist.get_gist_index(&post_comment_path));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -294,7 +294,6 @@ impl Data {
|
|||
let tree = repo.find_tree(id).unwrap();
|
||||
let mut items = Vec::with_capacity(tree.len());
|
||||
for item in tree.iter() {
|
||||
println!("{:?}", item.name());
|
||||
if let Some(name) = item.name() {
|
||||
#[allow(clippy::needless_borrow)]
|
||||
let mode: GitFileMode = (&item).into();
|
||||
|
@ -346,6 +345,12 @@ impl Data {
|
|||
}
|
||||
}
|
||||
|
||||
/// fetches gist metadata from DB and retrieves contents of all the files stored
|
||||
/// in the repository
|
||||
// TODO
|
||||
// Data::gist_preview uses Data::read_file under the hood, which
|
||||
// currently reads subdirectories up to level 1 depth. Decision has
|
||||
// to be made regarding what to do with level 2 and below subdirectories.
|
||||
pub async fn gist_preview<T: GPDatabse>(
|
||||
&self,
|
||||
db: &T,
|
||||
|
@ -362,7 +367,6 @@ impl Data {
|
|||
let tree = head.peel_to_tree().unwrap();
|
||||
let mut files = Vec::with_capacity(5);
|
||||
for item in tree.iter() {
|
||||
println!("name from gist_preview: {:?}:", item.name());
|
||||
if let Some(name) = item.name() {
|
||||
let file = data.read_file(db, gist_id, name).await?;
|
||||
files.push(file);
|
||||
|
@ -505,7 +509,6 @@ pub mod tests {
|
|||
.await
|
||||
.unwrap();
|
||||
assert_eq!(preview.owner, NAME);
|
||||
println!("preview {:#?}", preview);
|
||||
assert_eq!(preview.files.len(), 4);
|
||||
for file in preview.files.iter() {
|
||||
if file.filename == escape_spaces(&files2[0].filename) {
|
||||
|
|
Loading…
Reference in New Issue