mirror of
https://github.com/pcvolkmer/arsnova-client.git
synced 2025-04-19 11:06:51 +00:00
feat: apply typestate pattern to client
This prevents using the client without using guest login and without token.
This commit is contained in:
parent
b116457796
commit
9cdd68abed
@ -10,7 +10,7 @@ Create a client using and request guest login.
|
||||
|
||||
```rust
|
||||
let client = Client::new("https://ars.particify.de/api").expect("client created");
|
||||
client.guest_login().await;
|
||||
let client = client.guest_login().await.expect("logged in");
|
||||
```
|
||||
|
||||
### Request room information
|
||||
|
@ -55,14 +55,12 @@ pub struct Cli {
|
||||
async fn main() -> Result<(), ()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
let mut client = match Client::new(&cli.url) {
|
||||
let client = match Client::new(&cli.url) {
|
||||
Ok(client) => client,
|
||||
Err(_) => return Err(()),
|
||||
};
|
||||
|
||||
if client.guest_login().await.is_err() {
|
||||
return Err(());
|
||||
}
|
||||
let client = client.guest_login().await.map_err(|_| ())?;
|
||||
|
||||
let (tx, rx) = channel::<Feedback>(10);
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
use std::error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::marker::PhantomData;
|
||||
use std::time::Duration;
|
||||
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
@ -199,10 +200,14 @@ impl Display for ClientError {
|
||||
|
||||
impl error::Error for ClientError {}
|
||||
|
||||
pub struct Client {
|
||||
pub struct LoggedIn;
|
||||
pub struct LoggedOut;
|
||||
|
||||
pub struct Client<State = LoggedOut> {
|
||||
api_url: String,
|
||||
http_client: reqwest::Client,
|
||||
token: Option<String>,
|
||||
state: PhantomData<State>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
@ -216,10 +221,13 @@ impl Client {
|
||||
api_url: api_url.to_string(),
|
||||
http_client: client,
|
||||
token: None,
|
||||
state: PhantomData::<LoggedOut>,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn guest_login(&mut self) -> Result<(), ClientError> {
|
||||
impl Client<LoggedOut> {
|
||||
pub async fn guest_login(self) -> Result<Client<LoggedIn>, ClientError> {
|
||||
match self
|
||||
.http_client
|
||||
.post(format!("{}/auth/login/guest", self.api_url))
|
||||
@ -227,15 +235,28 @@ impl Client {
|
||||
.await
|
||||
{
|
||||
Ok(res) => match res.json::<LoginResponse>().await {
|
||||
Ok(res) => {
|
||||
self.token = Some(res.token);
|
||||
Ok(())
|
||||
}
|
||||
Ok(res) => Ok(Client {
|
||||
api_url: self.api_url,
|
||||
http_client: self.http_client,
|
||||
token: Some(res.token),
|
||||
state: PhantomData::<LoggedIn>,
|
||||
}),
|
||||
Err(_) => Err(LoginError),
|
||||
},
|
||||
Err(_) => Err(ConnectionError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Client<LoggedIn> {
|
||||
pub fn logout(self) -> Client<LoggedOut> {
|
||||
Client {
|
||||
api_url: self.api_url,
|
||||
http_client: self.http_client,
|
||||
token: None,
|
||||
state: PhantomData::<LoggedOut>,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_room_info(&self, short_id: &str) -> Result<RoomInfo, ClientError> {
|
||||
let token = self.token.as_ref().unwrap();
|
||||
|
Loading…
x
Reference in New Issue
Block a user