Web API, Web UI #86

Merged
projectmoon merged 37 commits from web-api into master 2021-07-15 15:04:54 +00:00
8 changed files with 126 additions and 17 deletions
Showing only changes of commit 05157507aa - Show all commits

8
api/Rocket.toml Normal file
View File

@ -0,0 +1,8 @@
[default]
address = "0.0.0.0"
port = 10000
keep_alive = 5
read_timeout = 5
write_timeout = 5
log = "normal"
limits = { forms = 32768 }

View File

@ -39,7 +39,6 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
log::info!("Setting up gRPC connection"); log::info!("Setting up gRPC connection");
let client = tenebrous_rpc::create_client("http://localhost:9090", "abc123").await?; let client = tenebrous_rpc::create_client("http://localhost:9090", "abc123").await?;
log::info!("Listening on 127.0.0.1:8080");
let context = Context { let context = Context {
dicebot_client: client, dicebot_client: client,
}; };

View File

@ -1,21 +1,30 @@
use juniper::{ use juniper::{
graphql_object, EmptyMutation, EmptySubscription, FieldResult, GraphQLInputObject, graphql_object, EmptyMutation, EmptySubscription, FieldResult, GraphQLObject, RootNode,
GraphQLObject, RootNode,
}; };
use rocket::{response::content, Rocket, State};
use std::env;
use tenebrous_rpc::protos::dicebot::dicebot_client::DicebotClient;
use tenebrous_rpc::protos::dicebot::GetVariableRequest; use tenebrous_rpc::protos::dicebot::GetVariableRequest;
use tenebrous_rpc::protos::dicebot::{dicebot_client::DicebotClient, UserIdRequest};
use tonic::{transport::Channel as TonicChannel, Request as TonicRequest}; use tonic::{transport::Channel as TonicChannel, Request as TonicRequest};
//api stuff /// Hide generic type behind alias.
#[derive(GraphQLInputObject)] pub type DicebotGrpcClient = DicebotClient<TonicChannel>;
struct UserVariableArgument {
/// Single room for a user.
#[derive(GraphQLObject)]
#[graphql(description = "A matrix room.")]
struct Room {
room_id: String, room_id: String,
user_id: String, display_name: String,
variable_name: String,
} }
/// List of rooms a user is in.
#[derive(GraphQLObject)]
#[graphql(description = "List of rooms a user is in.")]
struct UserRoomList {
user_id: String,
rooms: Vec<Room>,
}
/// A single user variable in a room.
#[derive(GraphQLObject)] #[derive(GraphQLObject)]
#[graphql(description = "User variable in a room.")] #[graphql(description = "User variable in a room.")]
struct UserVariable { struct UserVariable {
@ -25,10 +34,11 @@ struct UserVariable {
value: i32, value: i32,
} }
//graphql shit /// Context passed to every GraphQL function that holds stuff we need
/// (GRPC client).
#[derive(Clone)] #[derive(Clone)]
pub struct Context { pub struct Context {
pub dicebot_client: DicebotClient<TonicChannel>, pub dicebot_client: DicebotGrpcClient,
} }
// To make our context usable by Juniper, we have to implement a marker trait. // To make our context usable by Juniper, we have to implement a marker trait.
@ -74,6 +84,31 @@ impl Query {
value: response.value, value: response.value,
}) })
} }
async fn user_rooms(context: &Context, user_id: String) -> FieldResult<UserRoomList> {
let request = TonicRequest::new(UserIdRequest {
user_id: user_id.clone(),
});
let response = context
.dicebot_client
.clone()
.rooms_for_user(request)
.await?
.into_inner();
Ok(UserRoomList {
user_id,
rooms: response
.rooms
.into_iter()
.map(|grpc_room| Room {
room_id: grpc_room.room_id,
display_name: grpc_room.display_name,
})
.collect(),
})
}
} }
pub type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>; pub type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;

View File

@ -0,0 +1,9 @@
query RoomsForUser($userId: String!) {
userRooms(userId: $userId) {
userId
rooms {
roomId
displayName
}
}
}

View File

@ -9,6 +9,19 @@ type UserVariable {
type Query { type Query {
apiVersion: String! apiVersion: String!
variable(roomId: String!, userId: String!, variable: String!): UserVariable! variable(roomId: String!, userId: String!, variable: String!): UserVariable!
userRooms(userId: String!): UserRoomList!
}
"List of rooms a user is in."
type UserRoomList {
userId: String!
rooms: [Room!]!
}
"A matrix room."
type Room {
roomId: String!
displayName: String!
} }
schema { schema {

View File

@ -9,6 +9,19 @@ type UserVariable {
type Query { type Query {
apiVersion: String! apiVersion: String!
variable(roomId: String!, userId: String!, variable: String!): UserVariable! variable(roomId: String!, userId: String!, variable: String!): UserVariable!
userRooms(userId: String!): UserRoomList!
}
"List of rooms a user is in."
type UserRoomList {
userId: String!
rooms: [Room!]!
}
"A matrix room."
type Room {
roomId: String!
displayName: String!
} }
schema { schema {

View File

@ -10,6 +10,14 @@ use graphql_client::GraphQLQuery;
)] )]
struct GetUserVariable; struct GetUserVariable;
#[derive(GraphQLQuery)]
#[graphql(
schema_path = "graphql/schema.graphql",
query_path = "graphql/queries/rooms_for_user.graphql",
response_derives = "Debug"
)]
struct RoomsForUser;
pub async fn get_user_variable( pub async fn get_user_variable(
room_id: &str, room_id: &str,
user_id: &str, user_id: &str,
@ -28,3 +36,21 @@ pub async fn get_user_variable(
let value = response.data.map(|d| d.variable.value).unwrap(); let value = response.data.map(|d| d.variable.value).unwrap();
Ok(value) Ok(value)
} }
pub async fn rooms_for_user(
user_id: &str,
) -> Result<Vec<rooms_for_user::RoomsForUserUserRoomsRooms>, ClientError> {
let client = Client::new("http://localhost:10000/graphql");
let variables = rooms_for_user::Variables {
user_id: user_id.to_owned(),
};
//TODO don't unwrap() option. map to err instead.
let response = client.call(RoomsForUser, variables).await?;
let response: graphql_client_web::Response<rooms_for_user::ResponseData> = response;
let rooms = response
.data
.map(|d| d.user_rooms.rooms)
.unwrap_or_default();
Ok(rooms)
}

View File

@ -60,11 +60,17 @@ fn view_room(room: &Room) -> Html {
} }
async fn do_things(dispatch: &RoomListDispatch) { async fn do_things(dispatch: &RoomListDispatch) {
let rooms = crate::graphql::rooms_for_user("@projectmoon:agnos.is")
.await
.unwrap();
for room in rooms {
dispatch.send(Action::AddRoom(Room { dispatch.send(Action::AddRoom(Room {
room_id: "asdf".into(), room_id: room.room_id,
display_name: "adslkjg".into(), display_name: room.display_name,
})); }));
} }
}
impl Component for YewduxRoomList { impl Component for YewduxRoomList {
type Message = (); type Message = ();