diff options
author | Colin Reeder <vpzomtrrfrt@gmail.com> | 2020-12-03 20:32:32 -0700 |
---|---|---|
committer | Colin Reeder <vpzomtrrfrt@gmail.com> | 2020-12-03 20:32:32 -0700 |
commit | 3419324fd722e1edaae572a396816fd63d6bcf82 (patch) | |
tree | 6f57b7cdff5d2ad9a0c2ad9d50d9b4f3f7452f5b | |
parent | 3856bd417db790342cce89ecf96de836f9b7d8ac (diff) |
Include more fields in community list (#128)
-rw-r--r-- | openapi/openapi.json | 53 | ||||
-rw-r--r-- | src/main.rs | 4 | ||||
-rw-r--r-- | src/routes/api/communities.rs | 61 |
3 files changed, 81 insertions, 37 deletions
diff --git a/openapi/openapi.json b/openapi/openapi.json index 5168fbc..2d9586b 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -100,6 +100,26 @@ } } }, + "CommunityInfo": { + "allOf": [{"$ref": "#/components/schemas/MinimalCommunityInfo"}], + "type": "object", + "required": ["description"], + "properties": { + "description": {"type": "string"}, + "you_are_moderator": {"type": "boolean"}, + "your_follow": { + "type": "object", + "nullable": true, + "required": ["accepted"], + "properties": { + "accepted": { + "type": "boolean", + "description": "Whether your follow request has been accepted by the community." + } + } + } + } + }, "SomePostInfo": { "type": "object", "required": ["id", "title", "created", "community", "score"], @@ -445,6 +465,15 @@ "/api/unstable/communities": { "get": { "summary": "List communities", + "parameters": [ + { + "name": "include_your", + "in": "query", + "required": false, + "schema": {"type": "boolean"}, + "description": "If true, will include `you_are_moderator` and `your_follow` in list. Requires login." + } + ], "responses": { "200": { "description": "", @@ -453,13 +482,14 @@ "schema": { "type": "array", "items": { - "$ref": "#/components/schemas/MinimalCommunityInfo" + "$ref": "#/components/schemas/CommunityInfo" } } } } } - } + }, + "security": [{"bearer": []}] }, "post": { "summary": "Create a community", @@ -525,24 +555,7 @@ "content": { "application/json": { "schema": { - "allOf": [{"$ref": "#/components/schemas/MinimalCommunityInfo"}], - "type": "object", - "required": ["description"], - "properties": { - "description": {"type": "string"}, - "you_are_moderator": {"type": "boolean"}, - "your_follow": { - "type": "object", - "nullable": true, - "required": ["accepted"], - "properties": { - "accepted": { - "type": "boolean", - "description": "Whether your follow request has been accepted by the community." - } - } - } - } + "$ref": "#/components/schemas/CommunityInfo" } } } diff --git a/src/main.rs b/src/main.rs index 18d2959..3a93424 100644 --- a/src/main.rs +++ b/src/main.rs @@ -87,6 +87,8 @@ impl Into<activitystreams::primitives::OneOrMany<activitystreams::base::AnyBase> } } +pub type ParamSlice<'a> = &'a [&'a (dyn tokio_postgres::types::ToSql + Sync)]; + #[derive(Serialize, Default)] pub struct Empty {} @@ -450,7 +452,7 @@ pub fn get_path_and_query(url: &url::Url) -> Result<String, url::ParseError> { pub async fn query_stream( db: &tokio_postgres::Client, statement: &(impl tokio_postgres::ToStatement + ?Sized), - params: &[&(dyn tokio_postgres::types::ToSql + Sync)], + params: ParamSlice<'_>, ) -> Result<tokio_postgres::RowStream, tokio_postgres::Error> { let params = params.iter().map(|s| *s as _); diff --git a/src/routes/api/communities.rs b/src/routes/api/communities.rs index 29bbcad..aa0d80f 100644 --- a/src/routes/api/communities.rs +++ b/src/routes/api/communities.rs @@ -10,7 +10,7 @@ use std::sync::Arc; #[derive(Serialize)] struct RespCommunityInfo<'a> { #[serde(flatten)] - base: &'a RespMinimalCommunityInfo<'a>, + base: RespMinimalCommunityInfo<'a>, description: &'a str, @@ -28,30 +28,59 @@ struct RespYourFollowInfo { async fn route_unstable_communities_list( _: (), ctx: Arc<crate::RouteContext>, - _req: hyper::Request<hyper::Body>, + req: hyper::Request<hyper::Body>, ) -> Result<hyper::Response<hyper::Body>, crate::Error> { - let db = ctx.db_pool.get().await?; + let query: MaybeIncludeYour = serde_urlencoded::from_str(req.uri().query().unwrap_or(""))?; - let rows = db - .query("SELECT id, local, ap_id, name FROM community", &[]) - .await?; + let db = ctx.db_pool.get().await?; + let rows = if query.include_your { + let user = crate::require_login(&req, &db).await?; + db.query( + "SELECT id, name, local, ap_id, description, (SELECT accepted FROM community_follow WHERE community=community.id AND follower=$1), EXISTS(SELECT 1 FROM community_moderator WHERE community=community.id AND person=$1) FROM community", + &[&user.raw()], + ).await? + } else { + db.query( + "SELECT id, name, local, ap_id, description FROM community", + &[], + ) + .await? + }; let output: Vec<_> = rows .iter() .map(|row| { let id = CommunityLocalID(row.get(0)); - let local = row.get(1); - let ap_id = row.get(2); - let name = row.get(3); + let name = row.get(1); + let local = row.get(2); + let ap_id = row.get(3); + let description = row.get(4); let host = crate::get_actor_host_or_unknown(local, ap_id, &ctx.local_hostname); - RespMinimalCommunityInfo { - id, - name, - local, - host, - remote_url: ap_id, + RespCommunityInfo { + base: RespMinimalCommunityInfo { + id, + name, + local, + host, + remote_url: ap_id, + }, + + description, + you_are_moderator: if query.include_your { + Some(row.get(6)) + } else { + None + }, + your_follow: if query.include_your { + Some(match row.get(5) { + Some(accepted) => Some(RespYourFollowInfo { accepted }), + None => None, + }) + } else { + None + }, } }) .collect(); @@ -173,7 +202,7 @@ async fn route_unstable_communities_get( let community_ap_id: Option<&str> = row.get(2); let info = RespCommunityInfo { - base: &RespMinimalCommunityInfo { + base: RespMinimalCommunityInfo { id: community_id, name: row.get(0), local: community_local, |