Skip to content

Commit

Permalink
Work on listing rfds
Browse files Browse the repository at this point in the history
  • Loading branch information
augustuswm committed Sep 17, 2023
1 parent 1e9bc0b commit 9793583
Show file tree
Hide file tree
Showing 22 changed files with 3,414 additions and 1,336 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ serde_urlencoded = "0.7.1"
similar = "2.2.1"
slog = "2.7.0"
slog-async = "2.7.0"
tabwriter = "1.3.0"
tap = "1.0.1"
thiserror = "1.0.38"
tokio = "1.25.0"
Expand Down
183 changes: 180 additions & 3 deletions rfd-api-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -812,8 +812,37 @@
}
}
},
"/rfd": {
"get": {
"summary": "List all available RFDs",
"operationId": "get_rfds",
"responses": {
"200": {
"description": "successful operation",
"content": {
"application/json": {
"schema": {
"title": "Array_of_ListRfd",
"type": "array",
"items": {
"$ref": "#/components/schemas/ListRfd"
}
}
}
}
},
"4XX": {
"$ref": "#/components/responses/Error"
},
"5XX": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/rfd/{number}": {
"get": {
"summary": "Get the latest representation of an RFD",
"operationId": "get_rfd",
"parameters": [
{
Expand Down Expand Up @@ -970,8 +999,11 @@
"GetAllRfds",
"GetAssignedRfds",
"GetAllDiscussions",
"GetAssignedDiscussions",
"CreateOAuthClient",
"GetOAuthClientAll"
"GetAssignedOAuthClients",
"UpdateAssignedOAuthClients",
"DeleteAssignedOAuthClients"
]
},
{
Expand Down Expand Up @@ -1043,6 +1075,19 @@
"type": "object",
"properties": {
"GetRfd": {
"type": "integer",
"format": "int32"
}
},
"required": [
"GetRfd"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"GetRfds": {
"type": "array",
"items": {
"type": "integer",
Expand All @@ -1052,7 +1097,37 @@
}
},
"required": [
"GetRfd"
"GetRfds"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"GetDiscussion": {
"type": "integer",
"format": "int32"
}
},
"required": [
"GetDiscussion"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"GetDiscussions": {
"type": "array",
"items": {
"type": "integer",
"format": "int32"
},
"uniqueItems": true
}
},
"required": [
"GetDiscussions"
],
"additionalProperties": false
},
Expand All @@ -1069,6 +1144,23 @@
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"GetOAuthClients": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"uniqueItems": true
}
},
"required": [
"GetOAuthClients"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
Expand All @@ -1082,6 +1174,23 @@
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"UpdateOAuthClients": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"uniqueItems": true
}
},
"required": [
"UpdateOAuthClients"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
Expand All @@ -1094,6 +1203,23 @@
"DeleteOAuthClient"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"DeleteOAuthClients": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"uniqueItems": true
}
},
"required": [
"DeleteOAuthClients"
],
"additionalProperties": false
}
]
},
Expand Down Expand Up @@ -1412,6 +1538,56 @@
"permissions"
]
},
"ListRfd": {
"type": "object",
"properties": {
"authors": {
"nullable": true,
"type": "string"
},
"commit": {
"type": "string"
},
"committed_at": {
"type": "string",
"format": "date-time"
},
"discussion": {
"nullable": true,
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
},
"link": {
"nullable": true,
"type": "string"
},
"rfd_number": {
"type": "integer",
"format": "int32"
},
"sha": {
"type": "string"
},
"state": {
"nullable": true,
"type": "string"
},
"title": {
"type": "string"
}
},
"required": [
"commit",
"committed_at",
"id",
"rfd_number",
"sha",
"title"
]
},
"OAuthAuthzCodeExchangeBody": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -1607,7 +1783,8 @@
"type": "array",
"items": {
"$ref": "#/components/schemas/ApiPermission"
}
},
"uniqueItems": true
}
}
},
Expand Down
15 changes: 14 additions & 1 deletion rfd-api/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,18 @@ pub struct GitHubOAuthConfig {

#[derive(Debug, Deserialize)]
pub struct GoogleOAuthConfig {
pub device: GoogleOAuthDeviceConfig,
pub web: GoogleOAuthWebConfig,
}

#[derive(Debug, Deserialize)]
pub struct GoogleOAuthDeviceConfig {
pub client_id: String,
pub client_secret: String,
}

#[derive(Debug, Deserialize)]
pub struct GoogleOAuthWebConfig {
pub client_id: String,
pub client_secret: String,
pub redirect_uri: String,
Expand All @@ -146,7 +158,8 @@ pub struct GoogleOAuthConfig {
impl AppConfig {
pub fn new() -> Result<Self, ConfigError> {
let config = Config::builder()
.add_source(File::with_name("config.toml"))
.add_source(File::with_name("config.toml").required(false))
.add_source(File::with_name("rfd-api/config.toml").required(false))
.add_source(Environment::default())
.build()?;

Expand Down
66 changes: 66 additions & 0 deletions rfd-api/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use hyper::{client::HttpConnector, Body, Client};
use hyper_tls::HttpsConnector;
use jsonwebtoken::jwk::JwkSet;
use oauth2::CsrfToken;
use partial_struct::partial;
use rfd_model::{
permissions::{Caller, Permissions},
schema_ext::LoginAttemptState,
Expand Down Expand Up @@ -144,6 +145,7 @@ pub enum LoginAttemptError {
Storage(#[from] StoreError),
}

#[partial(ListRfd)]
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
pub struct FullRfd {
pub id: Uuid,
Expand All @@ -153,10 +155,12 @@ pub struct FullRfd {
pub title: String,
pub state: Option<String>,
pub authors: Option<String>,
#[partial(ListRfd(skip))]
pub content: String,
pub sha: String,
pub commit: String,
pub committed_at: DateTime<Utc>,
#[partial(ListRfd(skip))]
pub pdfs: Vec<FullRfdPdfEntry>,
}

Expand Down Expand Up @@ -319,6 +323,56 @@ impl ApiContext {

// RFD Operations

pub async fn list_rfds(
&self,
caller: &Caller<ApiPermission>,
) -> Result<Vec<ListRfd>, StoreError> {
let mut filter = RfdFilter::default();

if !caller.can(&ApiPermission::GetAllRfds) {
let numbers = caller.permissions.iter().filter_map(|p| {
match p {
ApiPermission::GetRfd(number) => Some(*number),
_ => None
}
}).collect::<Vec<_>>();

filter = filter.rfd_number(Some(numbers));
}

let rfds = RfdStore::list(
&*self.storage,
filter,
&ListPagination::default().limit(1),
)
.await.tap_err(|err| tracing::error!(?err, "Failed to lookup RFDs"))?;

let rfd_revisions = RfdRevisionStore::list_unique_rfd(
&*self.storage,
RfdRevisionFilter::default()
.rfd(Some(rfds.iter().map(|rfd| rfd.id).collect())),
&ListPagination::default(),
)
.await.tap_err(|err| tracing::error!(?err, "Failed to lookup RFD revisions"))?;

let rfd_list = rfds.into_iter().zip(rfd_revisions).map(|(rfd, revision)| {
ListRfd {
id: rfd.id,
rfd_number: rfd.rfd_number,
link: rfd.link,
discussion: revision.discussion,
title: revision.title,
state: revision.state,
authors: revision.authors,
sha: revision.sha,
commit: revision.commit_sha,
committed_at: revision.committed_at,
}
}).collect::<Vec<_>>();

Ok(rfd_list)
}

pub async fn get_rfd(
&self,
rfd_number: i32,
Expand Down Expand Up @@ -888,6 +942,18 @@ pub(crate) mod tests {
.await
}

async fn list_unique_rfd(
&self,
filter: rfd_model::storage::RfdRevisionFilter,
pagination: &ListPagination,
) -> Result<Vec<rfd_model::RfdRevision>, rfd_model::storage::StoreError> {
self.rfd_revision_store
.as_ref()
.unwrap()
.list(filter, pagination)
.await
}

async fn upsert(
&self,
new_revision: NewRfdRevision,
Expand Down
Loading

0 comments on commit 9793583

Please sign in to comment.