Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
radicle: pinned repositories configuration
Fintan Halpenny committed 2 years ago
commit 5b3d7b765258e4d2607b5f992f2a740cbac9ec5d
parent 92182a879b5250b3fee2678e24c857c4991b21cf
4 files changed +65 -26
modified radicle-httpd/src/api.rs
@@ -125,10 +125,20 @@ async fn root_handler() -> impl IntoResponse {
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct PaginationQuery {
+
    #[serde(default)]
+
    pub show: ProjectQuery,
    pub page: Option<usize>,
    pub per_page: Option<usize>,
}

+
#[derive(Serialize, Deserialize, Clone, Default)]
+
#[serde(rename_all = "camelCase")]
+
pub enum ProjectQuery {
+
    All,
+
    #[default]
+
    Pinned,
+
}
+

#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct RawQuery {
modified radicle-httpd/src/api/v1/delegates.rs
@@ -14,7 +14,7 @@ use radicle::storage::{ReadRepository, ReadStorage};
use crate::api::error::Error;
use crate::api::project::Info;
use crate::api::Context;
-
use crate::api::PaginationQuery;
+
use crate::api::{PaginationQuery, ProjectQuery};
use crate::axum_extra::{Path, Query};

pub fn router(ctx: Context) -> Router {
@@ -34,19 +34,28 @@ async fn delegates_projects_handler(
    Path(delegate): Path<Did>,
    Query(qs): Query<PaginationQuery>,
) -> impl IntoResponse {
-
    let PaginationQuery { page, per_page } = qs;
+
    let PaginationQuery {
+
        show,
+
        page,
+
        per_page,
+
    } = qs;
    let page = page.unwrap_or(0);
    let per_page = per_page.unwrap_or(10);
    let storage = &ctx.profile.storage;
    let db = &ctx.profile.database()?;
-
    let mut projects = storage
-
        .repositories()?
-
        .into_iter()
-
        .filter(|id| match &id.doc.visibility {
-
            Visibility::Private { .. } => addr.ip().is_loopback(),
-
            Visibility::Public => true,
-
        })
-
        .collect::<Vec<_>>();
+
    let pinned = &ctx.profile.config.web.pinned;
+

+
    let mut projects = match show {
+
        ProjectQuery::All => storage
+
            .repositories()?
+
            .into_iter()
+
            .filter(|repo| match &repo.doc.visibility {
+
                Visibility::Private { .. } => addr.ip().is_loopback(),
+
                Visibility::Public => true,
+
            })
+
            .collect::<Vec<_>>(),
+
        ProjectQuery::Pinned => storage.repositories_by_id(pinned.repositories.iter())?,
+
    };
    projects.sort_by_key(|p| p.rid);

    let infos = projects
@@ -116,11 +125,16 @@ mod routes {
            .layer(MockConnectInfo(SocketAddr::from(([127, 0, 0, 1], 8080))));
        let response = get(
            &app,
-
            "/delegates/did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/projects",
+
            "/delegates/did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/projects?show=all",
        )
        .await;

-
        assert_eq!(response.status(), StatusCode::OK);
+
        assert_eq!(
+
            response.status(),
+
            StatusCode::OK,
+
            "failed response: {:?}",
+
            response.json().await
+
        );
        assert_eq!(
            response.json().await,
            json!([
@@ -179,11 +193,16 @@ mod routes {
        ))));
        let response = get(
            &app,
-
            "/delegates/did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/projects",
+
            "/delegates/did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/projects?show=all",
        )
        .await;

-
        assert_eq!(response.status(), StatusCode::OK);
+
        assert_eq!(
+
            response.status(),
+
            StatusCode::OK,
+
            "failed response: {:?}",
+
            response.json().await
+
        );
        assert_eq!(
            response.json().await,
            json!([
modified radicle-httpd/src/api/v1/profile.rs
@@ -75,6 +75,7 @@ mod routes {
                "preferredSeeds": [
                  "z6MkrLMMsiPWUcNPHcRajuMi9mDfYckSoJyPwwnknocNYPm7@seed.radicle.garden:8776"
                ],
+
                "web": { "pinned": { "repositories": [] } },
                "cli": {
                  "hints": true
                },
modified radicle-httpd/src/api/v1/projects.rs
@@ -24,7 +24,7 @@ use radicle_surf::{diff, Glob, Oid, Repository};

use crate::api::error::Error;
use crate::api::project::Info;
-
use crate::api::{self, announce_refs, CobsQuery, Context, PaginationQuery};
+
use crate::api::{self, announce_refs, CobsQuery, Context, PaginationQuery, ProjectQuery};
use crate::axum_extra::{Path, Query};

const CACHE_1_HOUR: &str = "public, max-age=3600, must-revalidate";
@@ -79,19 +79,28 @@ async fn project_root_handler(
    State(ctx): State<Context>,
    Query(qs): Query<PaginationQuery>,
) -> impl IntoResponse {
-
    let PaginationQuery { page, per_page } = qs;
+
    let PaginationQuery {
+
        show,
+
        page,
+
        per_page,
+
    } = qs;
    let page = page.unwrap_or(0);
    let per_page = per_page.unwrap_or(10);
    let storage = &ctx.profile.storage;
    let db = &ctx.profile.database()?;
-
    let mut projects = storage
-
        .repositories()?
-
        .into_iter()
-
        .filter(|id| match &id.doc.visibility {
-
            Visibility::Private { .. } => addr.ip().is_loopback(),
-
            Visibility::Public => true,
-
        })
-
        .collect::<Vec<_>>();
+
    let pinned = &ctx.profile.config.web.pinned;
+

+
    let mut projects = match show {
+
        ProjectQuery::All => storage
+
            .repositories()?
+
            .into_iter()
+
            .filter(|repo| match &repo.doc.visibility {
+
                Visibility::Private { .. } => addr.ip().is_loopback(),
+
                Visibility::Public => true,
+
            })
+
            .collect::<Vec<_>>(),
+
        ProjectQuery::Pinned => storage.repositories_by_id(pinned.repositories.iter())?,
+
    };
    projects.sort_by_key(|p| p.rid);

    let infos = projects
@@ -976,7 +985,7 @@ mod routes {
        let seed = seed(tmp.path());
        let app = super::router(seed.clone())
            .layer(MockConnectInfo(SocketAddr::from(([127, 0, 0, 1], 8080))));
-
        let response = get(&app, "/projects").await;
+
        let response = get(&app, "/projects?show=all").await;

        assert_eq!(response.status(), StatusCode::OK);
        assert_eq!(
@@ -1035,7 +1044,7 @@ mod routes {
            [192, 168, 13, 37],
            8080,
        ))));
-
        let response = get(&app, "/projects").await;
+
        let response = get(&app, "/projects?show=all").await;

        assert_eq!(response.status(), StatusCode::OK);
        assert_eq!(