summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/boot/routes/get.rs9
-rw-r--r--src/boot/routes/test.rs6
-rw-r--r--src/channel/routes/channel/delete.rs4
-rw-r--r--src/channel/routes/channel/post.rs6
-rw-r--r--src/channel/routes/channel/test.rs52
-rw-r--r--src/channel/routes/post.rs4
-rw-r--r--src/channel/routes/test.rs6
-rw-r--r--src/event/routes/test.rs26
-rw-r--r--src/invite/routes/invite/post.rs6
-rw-r--r--src/invite/routes/post.rs10
-rw-r--r--src/login/extract.rs15
-rw-r--r--src/login/mod.rs1
-rw-r--r--src/login/routes/login/post.rs6
-rw-r--r--src/login/routes/login/test.rs29
-rw-r--r--src/login/routes/logout/post.rs6
-rw-r--r--src/login/routes/logout/test.rs14
-rw-r--r--src/message/app.rs2
-rw-r--r--src/message/routes/message.rs10
-rw-r--r--src/setup/routes/post.rs6
-rw-r--r--src/test/fixtures/cookie.rs37
-rw-r--r--src/test/fixtures/identity.rs48
-rw-r--r--src/test/fixtures/login.rs4
-rw-r--r--src/test/fixtures/mod.rs1
-rw-r--r--src/token/extract/cookie.rs (renamed from src/token/extract/identity_token.rs)22
-rw-r--r--src/token/extract/identity.rs6
-rw-r--r--src/token/extract/mod.rs4
-rw-r--r--src/ui/routes/ch/channel.rs6
-rw-r--r--src/ui/routes/get.rs6
28 files changed, 198 insertions, 154 deletions
diff --git a/src/boot/routes/get.rs b/src/boot/routes/get.rs
index 737b479..563fbf1 100644
--- a/src/boot/routes/get.rs
+++ b/src/boot/routes/get.rs
@@ -3,11 +3,14 @@ use axum::{
response::{self, IntoResponse},
};
-use crate::{app::App, boot::Snapshot, error::Internal, login::Login};
+use crate::{app::App, boot::Snapshot, error::Internal, login::Login, token::extract::Identity};
-pub async fn handler(State(app): State<App>, login: Login) -> Result<Response, Internal> {
+pub async fn handler(State(app): State<App>, identity: Identity) -> Result<Response, Internal> {
let snapshot = app.boot().snapshot().await?;
- Ok(Response { login, snapshot })
+ Ok(Response {
+ login: identity.login,
+ snapshot,
+ })
}
#[derive(serde::Serialize)]
diff --git a/src/boot/routes/test.rs b/src/boot/routes/test.rs
index 4023753..0430854 100644
--- a/src/boot/routes/test.rs
+++ b/src/boot/routes/test.rs
@@ -6,10 +6,10 @@ use crate::test::fixtures;
#[tokio::test]
async fn returns_identity() {
let app = fixtures::scratch_app().await;
- let login = fixtures::login::fictitious();
- let response = get::handler(State(app), login.clone())
+ let identity = fixtures::identity::fictitious();
+ let response = get::handler(State(app), identity.clone())
.await
.expect("boot always succeeds");
- assert_eq!(login, response.login);
+ assert_eq!(identity.login, response.login);
}
diff --git a/src/channel/routes/channel/delete.rs b/src/channel/routes/channel/delete.rs
index 5f40ddf..91eb506 100644
--- a/src/channel/routes/channel/delete.rs
+++ b/src/channel/routes/channel/delete.rs
@@ -9,14 +9,14 @@ use crate::{
channel::app,
clock::RequestedAt,
error::{Internal, NotFound},
- login::Login,
+ token::extract::Identity,
};
pub async fn handler(
State(app): State<App>,
Path(channel): Path<super::PathInfo>,
RequestedAt(deleted_at): RequestedAt,
- _: Login,
+ _: Identity,
) -> Result<StatusCode, Error> {
app.channels().delete(&channel, &deleted_at).await?;
diff --git a/src/channel/routes/channel/post.rs b/src/channel/routes/channel/post.rs
index d0cae05..b51e691 100644
--- a/src/channel/routes/channel/post.rs
+++ b/src/channel/routes/channel/post.rs
@@ -8,20 +8,20 @@ use crate::{
app::App,
clock::RequestedAt,
error::{Internal, NotFound},
- login::Login,
message::{app::SendError, Body, Message},
+ token::extract::Identity,
};
pub async fn handler(
State(app): State<App>,
Path(channel): Path<super::PathInfo>,
RequestedAt(sent_at): RequestedAt,
- login: Login,
+ identity: Identity,
Json(request): Json<Request>,
) -> Result<Response, Error> {
let message = app
.messages()
- .send(&channel, &login, &sent_at, &request.body)
+ .send(&channel, &identity.login, &sent_at, &request.body)
.await?;
Ok(Response(message))
diff --git a/src/channel/routes/channel/test.rs b/src/channel/routes/channel/test.rs
index b895b69..9a2227d 100644
--- a/src/channel/routes/channel/test.rs
+++ b/src/channel/routes/channel/test.rs
@@ -14,7 +14,7 @@ async fn messages_in_order() {
// Set up the environment
let app = fixtures::scratch_app().await;
- let sender = fixtures::login::create(&app, &fixtures::now()).await;
+ let sender = fixtures::identity::create(&app, &fixtures::now()).await;
let channel = fixtures::channel::create(&app, &fixtures::now()).await;
// Call the endpoint (twice)
@@ -35,7 +35,7 @@ async fn messages_in_order() {
Json(request),
)
.await
- .expect("sending to a valid channel");
+ .expect("sending to a valid channel succeeds");
}
// Verify the semantics
@@ -44,7 +44,7 @@ async fn messages_in_order() {
.events()
.subscribe(None)
.await
- .expect("subscribing to a valid channel")
+ .expect("subscribing to a valid channel succeeds")
.filter_map(fixtures::message::events)
.take(requests.len());
@@ -55,7 +55,7 @@ async fn messages_in_order() {
assert!(matches!(
event,
message::Event::Sent(event)
- if event.message.sender == sender.id
+ if event.message.sender == sender.login.id
&& event.message.body == message
));
}
@@ -66,7 +66,7 @@ async fn nonexistent_channel() {
// Set up the environment
let app = fixtures::scratch_app().await;
- let login = fixtures::login::create(&app, &fixtures::now()).await;
+ let sender = fixtures::identity::create(&app, &fixtures::now()).await;
// Call the endpoint
@@ -79,11 +79,49 @@ async fn nonexistent_channel() {
State(app),
Path(channel.clone()),
sent_at,
- login,
+ sender,
Json(request),
)
.await
- .expect_err("sending to a nonexistent channel");
+ .expect_err("sending to a nonexistent channel fails");
+
+ // Verify the structure of the response
+
+ assert!(matches!(
+ error,
+ SendError::ChannelNotFound(error_channel) if channel == error_channel
+ ));
+}
+
+#[tokio::test]
+async fn deleted_channel() {
+ // Set up the environment
+
+ let app = fixtures::scratch_app().await;
+ let sender = fixtures::identity::create(&app, &fixtures::now()).await;
+ let channel = fixtures::channel::create(&app, &fixtures::now()).await;
+
+ app.channels()
+ .delete(&channel.id, &fixtures::now())
+ .await
+ .expect("deleting a new channel succeeds");
+
+ // Call the endpoint
+
+ let sent_at = fixtures::now();
+ let channel = channel::Id::generate();
+ let request = post::Request {
+ body: fixtures::message::propose(),
+ };
+ let post::Error(error) = post::handler(
+ State(app),
+ Path(channel.clone()),
+ sent_at,
+ sender,
+ Json(request),
+ )
+ .await
+ .expect_err("sending to a deleted channel fails");
// Verify the structure of the response
diff --git a/src/channel/routes/post.rs b/src/channel/routes/post.rs
index 9781dd7..810445c 100644
--- a/src/channel/routes/post.rs
+++ b/src/channel/routes/post.rs
@@ -9,13 +9,13 @@ use crate::{
channel::{app, Channel},
clock::RequestedAt,
error::Internal,
- login::Login,
name::Name,
+ token::extract::Identity,
};
pub async fn handler(
State(app): State<App>,
- _: Login, // requires auth, but doesn't actually care who you are
+ _: Identity, // requires auth, but doesn't actually care who you are
RequestedAt(created_at): RequestedAt,
Json(request): Json<Request>,
) -> Result<Response, Error> {
diff --git a/src/channel/routes/test.rs b/src/channel/routes/test.rs
index 7879ba0..77f283b 100644
--- a/src/channel/routes/test.rs
+++ b/src/channel/routes/test.rs
@@ -14,7 +14,7 @@ async fn new_channel() {
// Set up the environment
let app = fixtures::scratch_app().await;
- let creator = fixtures::login::create(&app, &fixtures::now()).await;
+ let creator = fixtures::identity::create(&app, &fixtures::now()).await;
// Call the endpoint
@@ -65,7 +65,7 @@ async fn duplicate_name() {
// Set up the environment
let app = fixtures::scratch_app().await;
- let creator = fixtures::login::create(&app, &fixtures::now()).await;
+ let creator = fixtures::identity::create(&app, &fixtures::now()).await;
let channel = fixtures::channel::create(&app, &fixtures::now()).await;
// Call the endpoint
@@ -91,7 +91,7 @@ async fn name_reusable_after_delete() {
// Set up the environment
let app = fixtures::scratch_app().await;
- let creator = fixtures::login::create(&app, &fixtures::now()).await;
+ let creator = fixtures::identity::create(&app, &fixtures::now()).await;
let name = fixtures::channel::propose();
// Call the endpoint (first time)
diff --git a/src/event/routes/test.rs b/src/event/routes/test.rs
index e6a8b9d..49f8094 100644
--- a/src/event/routes/test.rs
+++ b/src/event/routes/test.rs
@@ -22,8 +22,7 @@ async fn includes_historical_message() {
// Call the endpoint
- let subscriber_creds = fixtures::login::create_with_password(&app, &fixtures::now()).await;
- let subscriber = fixtures::identity::identity(&app, &subscriber_creds, &fixtures::now()).await;
+ let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
let get::Response(events) = get::handler(State(app), subscriber, None, Query::default())
.await
.expect("subscribe never fails");
@@ -49,8 +48,7 @@ async fn includes_live_message() {
// Call the endpoint
- let subscriber_creds = fixtures::login::create_with_password(&app, &fixtures::now()).await;
- let subscriber = fixtures::identity::identity(&app, &subscriber_creds, &fixtures::now()).await;
+ let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
let get::Response(events) =
get::handler(State(app.clone()), subscriber, None, Query::default())
.await
@@ -95,8 +93,7 @@ async fn includes_multiple_channels() {
// Call the endpoint
- let subscriber_creds = fixtures::login::create_with_password(&app, &fixtures::now()).await;
- let subscriber = fixtures::identity::identity(&app, &subscriber_creds, &fixtures::now()).await;
+ let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
let get::Response(events) = get::handler(State(app), subscriber, None, Query::default())
.await
.expect("subscribe never fails");
@@ -133,8 +130,7 @@ async fn sequential_messages() {
// Call the endpoint
- let subscriber_creds = fixtures::login::create_with_password(&app, &fixtures::now()).await;
- let subscriber = fixtures::identity::identity(&app, &subscriber_creds, &fixtures::now()).await;
+ let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
let get::Response(events) = get::handler(State(app), subscriber, None, Query::default())
.await
.expect("subscribe never fails");
@@ -180,8 +176,7 @@ async fn resumes_from() {
// Call the endpoint
- let subscriber_creds = fixtures::login::create_with_password(&app, &fixtures::now()).await;
- let subscriber = fixtures::identity::identity(&app, &subscriber_creds, &fixtures::now()).await;
+ let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
let resume_at = {
// First subscription
@@ -258,8 +253,7 @@ async fn serial_resume() {
// Call the endpoint
- let subscriber_creds = fixtures::login::create_with_password(&app, &fixtures::now()).await;
- let subscriber = fixtures::identity::identity(&app, &subscriber_creds, &fixtures::now()).await;
+ let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
let resume_at = {
let initial_messages = [
@@ -382,7 +376,7 @@ async fn terminates_on_token_expiry() {
let subscriber_creds = fixtures::login::create_with_password(&app, &fixtures::now()).await;
let subscriber =
- fixtures::identity::identity(&app, &subscriber_creds, &fixtures::ancient()).await;
+ fixtures::identity::logged_in(&app, &subscriber_creds, &fixtures::ancient()).await;
let get::Response(events) =
get::handler(State(app.clone()), subscriber, None, Query::default())
@@ -426,11 +420,7 @@ async fn terminates_on_logout() {
// Subscribe via the endpoint
- let subscriber_creds = fixtures::login::create_with_password(&app, &fixtures::now()).await;
- let subscriber_token =
- fixtures::identity::logged_in(&app, &subscriber_creds, &fixtures::now()).await;
- let subscriber =
- fixtures::identity::from_token(&app, &subscriber_token, &fixtures::now()).await;
+ let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
let get::Response(events) = get::handler(
State(app.clone()),
diff --git a/src/invite/routes/invite/post.rs b/src/invite/routes/invite/post.rs
index a41207a..3ca4e6b 100644
--- a/src/invite/routes/invite/post.rs
+++ b/src/invite/routes/invite/post.rs
@@ -11,16 +11,16 @@ use crate::{
invite::app,
login::{Login, Password},
name::Name,
- token::extract::IdentityToken,
+ token::extract::IdentityCookie,
};
pub async fn handler(
State(app): State<App>,
RequestedAt(accepted_at): RequestedAt,
- identity: IdentityToken,
+ identity: IdentityCookie,
Path(invite): Path<super::PathInfo>,
Json(request): Json<Request>,
-) -> Result<(IdentityToken, Json<Login>), Error> {
+) -> Result<(IdentityCookie, Json<Login>), Error> {
let (login, secret) = app
.invites()
.accept(&invite, &request.name, &request.password, &accepted_at)
diff --git a/src/invite/routes/post.rs b/src/invite/routes/post.rs
index 80b1c27..eb7d706 100644
--- a/src/invite/routes/post.rs
+++ b/src/invite/routes/post.rs
@@ -1,17 +1,19 @@
use axum::extract::{Json, State};
-use crate::{app::App, clock::RequestedAt, error::Internal, invite::Invite, login::Login};
+use crate::{
+ app::App, clock::RequestedAt, error::Internal, invite::Invite, token::extract::Identity,
+};
pub async fn handler(
State(app): State<App>,
RequestedAt(issued_at): RequestedAt,
- login: Login,
- // Require `{}` as the only valid request for this endpoint.
+ identity: Identity,
_: Json<Request>,
) -> Result<Json<Invite>, Internal> {
- let invite = app.invites().create(&login, &issued_at).await?;
+ let invite = app.invites().create(&identity.login, &issued_at).await?;
Ok(Json(invite))
}
+// Require `{}` as the only valid request for this endpoint.
#[derive(Default, serde::Deserialize)]
pub struct Request {}
diff --git a/src/login/extract.rs b/src/login/extract.rs
deleted file mode 100644
index c2d97f2..0000000
--- a/src/login/extract.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use axum::{extract::FromRequestParts, http::request::Parts};
-
-use super::Login;
-use crate::{app::App, token::extract::Identity};
-
-#[async_trait::async_trait]
-impl FromRequestParts<App> for Login {
- type Rejection = <Identity as FromRequestParts<App>>::Rejection;
-
- async fn from_request_parts(parts: &mut Parts, state: &App) -> Result<Self, Self::Rejection> {
- let identity = Identity::from_request_parts(parts, state).await?;
-
- Ok(identity.login)
- }
-}
diff --git a/src/login/mod.rs b/src/login/mod.rs
index 64a3698..279e9a6 100644
--- a/src/login/mod.rs
+++ b/src/login/mod.rs
@@ -1,6 +1,5 @@
pub mod app;
pub mod event;
-pub mod extract;
mod history;
mod id;
pub mod password;
diff --git a/src/login/routes/login/post.rs b/src/login/routes/login/post.rs
index 20430db..96da5c5 100644
--- a/src/login/routes/login/post.rs
+++ b/src/login/routes/login/post.rs
@@ -10,15 +10,15 @@ use crate::{
error::Internal,
login::{Login, Password},
name::Name,
- token::{app, extract::IdentityToken},
+ token::{app, extract::IdentityCookie},
};
pub async fn handler(
State(app): State<App>,
RequestedAt(now): RequestedAt,
- identity: IdentityToken,
+ identity: IdentityCookie,
Json(request): Json<Request>,
-) -> Result<(IdentityToken, Json<Login>), Error> {
+) -> Result<(IdentityCookie, Json<Login>), Error> {
let (login, secret) = app
.tokens()
.login(&request.name, &request.password, &now)
diff --git a/src/login/routes/login/test.rs b/src/login/routes/login/test.rs
index c94f14c..7399796 100644
--- a/src/login/routes/login/test.rs
+++ b/src/login/routes/login/test.rs
@@ -8,14 +8,14 @@ async fn correct_credentials() {
// Set up the environment
let app = fixtures::scratch_app().await;
- let (login, password) = fixtures::login::create_with_password(&app, &fixtures::now()).await;
+ let (name, password) = fixtures::login::create_with_password(&app, &fixtures::now()).await;
// Call the endpoint
- let identity = fixtures::identity::not_logged_in();
+ let identity = fixtures::cookie::not_logged_in();
let logged_in_at = fixtures::now();
let request = post::Request {
- name: login.name.clone(),
+ name: name.clone(),
password,
};
let (identity, Json(response)) =
@@ -25,8 +25,10 @@ async fn correct_credentials() {
// Verify the return value's basic structure
- assert_eq!(login, response);
- let secret = identity.secret().expect("logged in with valid credentials");
+ assert_eq!(name, response.name);
+ let secret = identity
+ .secret()
+ .expect("logged in with valid credentials issues an identity cookie");
// Verify the semantics
@@ -37,7 +39,7 @@ async fn correct_credentials() {
.await
.expect("identity secret is valid");
- assert_eq!(login, validated_login);
+ assert_eq!(response, validated_login);
}
#[tokio::test]
@@ -48,7 +50,7 @@ async fn invalid_name() {
// Call the endpoint
- let identity = fixtures::identity::not_logged_in();
+ let identity = fixtures::cookie::not_logged_in();
let logged_in_at = fixtures::now();
let (name, password) = fixtures::login::propose();
let request = post::Request {
@@ -58,7 +60,7 @@ async fn invalid_name() {
let post::Error(error) =
post::handler(State(app.clone()), logged_in_at, identity, Json(request))
.await
- .expect_err("logged in with an incorrect password");
+ .expect_err("logged in with an incorrect password fails");
// Verify the return value's basic structure
@@ -75,7 +77,7 @@ async fn incorrect_password() {
// Call the endpoint
let logged_in_at = fixtures::now();
- let identity = fixtures::identity::not_logged_in();
+ let identity = fixtures::cookie::not_logged_in();
let request = post::Request {
name: login.name,
password: fixtures::login::propose_password(),
@@ -95,16 +97,13 @@ async fn token_expires() {
// Set up the environment
let app = fixtures::scratch_app().await;
- let (login, password) = fixtures::login::create_with_password(&app, &fixtures::now()).await;
+ let (name, password) = fixtures::login::create_with_password(&app, &fixtures::now()).await;
// Call the endpoint
let logged_in_at = fixtures::ancient();
- let identity = fixtures::identity::not_logged_in();
- let request = post::Request {
- name: login.name.clone(),
- password,
- };
+ let identity = fixtures::cookie::not_logged_in();
+ let request = post::Request { name, password };
let (identity, _) = post::handler(State(app.clone()), logged_in_at, identity, Json(request))
.await
.expect("logged in with valid credentials");
diff --git a/src/login/routes/logout/post.rs b/src/login/routes/logout/post.rs
index 6b7a62a..bb09b9f 100644
--- a/src/login/routes/logout/post.rs
+++ b/src/login/routes/logout/post.rs
@@ -8,15 +8,15 @@ use crate::{
app::App,
clock::RequestedAt,
error::{Internal, Unauthorized},
- token::{app, extract::IdentityToken},
+ token::{app, extract::IdentityCookie},
};
pub async fn handler(
State(app): State<App>,
RequestedAt(now): RequestedAt,
- identity: IdentityToken,
+ identity: IdentityCookie,
Json(_): Json<Request>,
-) -> Result<(IdentityToken, StatusCode), Error> {
+) -> Result<(IdentityCookie, StatusCode), Error> {
if let Some(secret) = identity.secret() {
let (token, _) = app.tokens().validate(&secret, &now).await?;
app.tokens().logout(&token).await?;
diff --git a/src/login/routes/logout/test.rs b/src/login/routes/logout/test.rs
index 91837fe..775fa9f 100644
--- a/src/login/routes/logout/test.rs
+++ b/src/login/routes/logout/test.rs
@@ -12,9 +12,9 @@ async fn successful() {
let app = fixtures::scratch_app().await;
let now = fixtures::now();
- let login = fixtures::login::create_with_password(&app, &fixtures::now()).await;
- let identity = fixtures::identity::logged_in(&app, &login, &now).await;
- let secret = fixtures::identity::secret(&identity);
+ let creds = fixtures::login::create_with_password(&app, &fixtures::now()).await;
+ let identity = fixtures::cookie::logged_in(&app, &creds, &now).await;
+ let secret = fixtures::cookie::secret(&identity);
// Call the endpoint
@@ -49,10 +49,10 @@ async fn no_identity() {
// Call the endpoint
- let identity = fixtures::identity::not_logged_in();
+ let identity = fixtures::cookie::not_logged_in();
let (identity, status) = post::handler(State(app), fixtures::now(), identity, Json::default())
.await
- .expect("logged out with no token");
+ .expect("logged out with no token succeeds");
// Verify the return value's basic structure
@@ -68,10 +68,10 @@ async fn invalid_token() {
// Call the endpoint
- let identity = fixtures::identity::fictitious();
+ let identity = fixtures::cookie::fictitious();
let post::Error(error) = post::handler(State(app), fixtures::now(), identity, Json::default())
.await
- .expect_err("logged out with an invalid token");
+ .expect_err("logged out with an invalid token fails");
// Verify the return value's basic structure
diff --git a/src/message/app.rs b/src/message/app.rs
index 852b958..eed6ba4 100644
--- a/src/message/app.rs
+++ b/src/message/app.rs
@@ -136,8 +136,6 @@ impl From<channel::repo::LoadError> for SendError {
#[derive(Debug, thiserror::Error)]
pub enum DeleteError {
- #[error("channel {0} not found")]
- ChannelNotFound(channel::Id),
#[error("message {0} not found")]
NotFound(Id),
#[error("message {0} deleted")]
diff --git a/src/message/routes/message.rs b/src/message/routes/message.rs
index fbef35a..f83cb39 100644
--- a/src/message/routes/message.rs
+++ b/src/message/routes/message.rs
@@ -9,15 +9,15 @@ pub mod delete {
app::App,
clock::RequestedAt,
error::{Internal, NotFound},
- login::Login,
message::{self, app::DeleteError},
+ token::extract::Identity,
};
pub async fn handler(
State(app): State<App>,
Path(message): Path<message::Id>,
RequestedAt(deleted_at): RequestedAt,
- _: Login,
+ _: Identity,
) -> Result<StatusCode, Error> {
app.messages().delete(&message, &deleted_at).await?;
@@ -33,9 +33,9 @@ pub mod delete {
let Self(error) = self;
#[allow(clippy::match_wildcard_for_single_variants)]
match error {
- DeleteError::ChannelNotFound(_)
- | DeleteError::NotFound(_)
- | DeleteError::Deleted(_) => NotFound(error).into_response(),
+ DeleteError::NotFound(_) | DeleteError::Deleted(_) => {
+ NotFound(error).into_response()
+ }
other => Internal::from(other).into_response(),
}
}
diff --git a/src/setup/routes/post.rs b/src/setup/routes/post.rs
index fb2280a..f7b256e 100644
--- a/src/setup/routes/post.rs
+++ b/src/setup/routes/post.rs
@@ -11,15 +11,15 @@ use crate::{
login::{Login, Password},
name::Name,
setup::app,
- token::extract::IdentityToken,
+ token::extract::IdentityCookie,
};
pub async fn handler(
State(app): State<App>,
RequestedAt(setup_at): RequestedAt,
- identity: IdentityToken,
+ identity: IdentityCookie,
Json(request): Json<Request>,
-) -> Result<(IdentityToken, Json<Login>), Error> {
+) -> Result<(IdentityCookie, Json<Login>), Error> {
let (login, secret) = app
.setup()
.initial(&request.name, &request.password, &setup_at)
diff --git a/src/test/fixtures/cookie.rs b/src/test/fixtures/cookie.rs
new file mode 100644
index 0000000..58777c8
--- /dev/null
+++ b/src/test/fixtures/cookie.rs
@@ -0,0 +1,37 @@
+use uuid::Uuid;
+
+use crate::{
+ app::App,
+ clock::RequestedAt,
+ login::Password,
+ name::Name,
+ token::{extract::IdentityCookie, Secret},
+};
+
+pub fn not_logged_in() -> IdentityCookie {
+ IdentityCookie::new()
+}
+
+pub async fn logged_in(
+ app: &App,
+ credentials: &(Name, Password),
+ now: &RequestedAt,
+) -> IdentityCookie {
+ let (name, password) = credentials;
+ let (_, token) = app
+ .tokens()
+ .login(name, password, now)
+ .await
+ .expect("should succeed given known-valid credentials");
+
+ IdentityCookie::new().set(token)
+}
+
+pub fn secret(identity: &IdentityCookie) -> Secret {
+ identity.secret().expect("identity contained a secret")
+}
+
+pub fn fictitious() -> IdentityCookie {
+ let token = Uuid::new_v4().to_string();
+ IdentityCookie::new().set(token)
+}
diff --git a/src/test/fixtures/identity.rs b/src/test/fixtures/identity.rs
index c434473..e438f2b 100644
--- a/src/test/fixtures/identity.rs
+++ b/src/test/fixtures/identity.rs
@@ -1,31 +1,21 @@
-use uuid::Uuid;
-
use crate::{
app::App,
clock::RequestedAt,
- login::{Login, Password},
+ login::Password,
+ name::Name,
+ test::fixtures,
token::{
- extract::{Identity, IdentityToken},
- Secret,
+ self,
+ extract::{Identity, IdentityCookie},
},
};
-pub fn not_logged_in() -> IdentityToken {
- IdentityToken::new()
-}
-
-pub async fn logged_in(app: &App, login: &(Login, Password), now: &RequestedAt) -> IdentityToken {
- let (login, password) = login;
- let (_, token) = app
- .tokens()
- .login(&login.name, password, now)
- .await
- .expect("should succeed given known-valid credentials");
-
- IdentityToken::new().set(token)
+pub async fn create(app: &App, created_at: &RequestedAt) -> Identity {
+ let credentials = fixtures::login::create_with_password(app, created_at).await;
+ logged_in(app, &credentials, created_at).await
}
-pub async fn from_token(app: &App, token: &IdentityToken, issued_at: &RequestedAt) -> Identity {
+pub async fn from_cookie(app: &App, token: &IdentityCookie, issued_at: &RequestedAt) -> Identity {
let secret = token.secret().expect("identity token has a secret");
let (token, login) = app
.tokens()
@@ -36,16 +26,18 @@ pub async fn from_token(app: &App, token: &IdentityToken, issued_at: &RequestedA
Identity { token, login }
}
-pub async fn identity(app: &App, login: &(Login, Password), issued_at: &RequestedAt) -> Identity {
- let secret = logged_in(app, login, issued_at).await;
- from_token(app, &secret, issued_at).await
+pub async fn logged_in(
+ app: &App,
+ credentials: &(Name, Password),
+ issued_at: &RequestedAt,
+) -> Identity {
+ let secret = fixtures::cookie::logged_in(app, credentials, issued_at).await;
+ from_cookie(app, &secret, issued_at).await
}
-pub fn secret(identity: &IdentityToken) -> Secret {
- identity.secret().expect("identity contained a secret")
-}
+pub fn fictitious() -> Identity {
+ let token = token::Id::generate();
+ let login = fixtures::login::fictitious();
-pub fn fictitious() -> IdentityToken {
- let token = Uuid::new_v4().to_string();
- IdentityToken::new().set(token)
+ Identity { token, login }
}
diff --git a/src/test/fixtures/login.rs b/src/test/fixtures/login.rs
index 714b936..e308289 100644
--- a/src/test/fixtures/login.rs
+++ b/src/test/fixtures/login.rs
@@ -8,7 +8,7 @@ use crate::{
name::Name,
};
-pub async fn create_with_password(app: &App, created_at: &RequestedAt) -> (Login, Password) {
+pub async fn create_with_password(app: &App, created_at: &RequestedAt) -> (Name, Password) {
let (name, password) = propose();
let login = app
.logins()
@@ -16,7 +16,7 @@ pub async fn create_with_password(app: &App, created_at: &RequestedAt) -> (Login
.await
.expect("should always succeed if the login is actually new");
- (login, password)
+ (login.name, password)
}
pub async fn create(app: &App, created_at: &RequestedAt) -> Login {
diff --git a/src/test/fixtures/mod.rs b/src/test/fixtures/mod.rs
index 9658831..5609ebc 100644
--- a/src/test/fixtures/mod.rs
+++ b/src/test/fixtures/mod.rs
@@ -3,6 +3,7 @@ use chrono::{TimeDelta, Utc};
use crate::{app::App, clock::RequestedAt, db};
pub mod channel;
+pub mod cookie;
pub mod event;
pub mod future;
pub mod identity;
diff --git a/src/token/extract/identity_token.rs b/src/token/extract/cookie.rs
index a1e900e..af5787d 100644
--- a/src/token/extract/identity_token.rs
+++ b/src/token/extract/cookie.rs
@@ -12,19 +12,21 @@ use crate::token::Secret;
// The usage pattern here - receive the extractor as an argument, return it in
// the response - is heavily modelled after CookieJar's own intended usage.
#[derive(Clone)]
-pub struct IdentityToken {
+pub struct Identity {
cookies: CookieJar,
}
-impl fmt::Debug for IdentityToken {
+impl fmt::Debug for Identity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("IdentityToken")
+ f.debug_struct("IdentityCookie")
.field("identity", &self.secret())
.finish()
}
}
-impl IdentityToken {
+impl Identity {
+ const COOKIE_NAME: &str = "identity";
+
// Creates a new, unpopulated identity token store.
#[cfg(test)]
pub fn new() -> Self {
@@ -40,7 +42,7 @@ impl IdentityToken {
// included.
pub fn secret(&self) -> Option<Secret> {
self.cookies
- .get(IDENTITY_COOKIE)
+ .get(Self::COOKIE_NAME)
.map(Cookie::value)
.map(Secret::from)
}
@@ -49,7 +51,7 @@ impl IdentityToken {
// back to the client when this extractor is included in a response.
pub fn set(self, secret: impl Into<Secret>) -> Self {
let secret = secret.into().reveal();
- let identity_cookie = Cookie::build((IDENTITY_COOKIE, secret))
+ let identity_cookie = Cookie::build((Self::COOKIE_NAME, secret))
.http_only(true)
.path("/")
.permanent()
@@ -64,15 +66,13 @@ impl IdentityToken {
// extractor is included in a response.
pub fn clear(self) -> Self {
Self {
- cookies: self.cookies.remove(IDENTITY_COOKIE),
+ cookies: self.cookies.remove(Self::COOKIE_NAME),
}
}
}
-const IDENTITY_COOKIE: &str = "identity";
-
#[async_trait::async_trait]
-impl<S> FromRequestParts<S> for IdentityToken
+impl<S> FromRequestParts<S> for Identity
where
S: Send + Sync,
{
@@ -84,7 +84,7 @@ where
}
}
-impl IntoResponseParts for IdentityToken {
+impl IntoResponseParts for Identity {
type Error = <CookieJar as IntoResponseParts>::Error;
fn into_response_parts(self, res: ResponseParts) -> Result<ResponseParts, Self::Error> {
diff --git a/src/token/extract/identity.rs b/src/token/extract/identity.rs
index 8b3cd94..a69f509 100644
--- a/src/token/extract/identity.rs
+++ b/src/token/extract/identity.rs
@@ -4,7 +4,7 @@ use axum::{
response::{IntoResponse, Response},
};
-use super::IdentityToken;
+use super::IdentityCookie;
use crate::{
app::App,
@@ -25,10 +25,10 @@ impl FromRequestParts<App> for Identity {
type Rejection = LoginError<Internal>;
async fn from_request_parts(parts: &mut Parts, state: &App) -> Result<Self, Self::Rejection> {
- let Ok(identity_token) = IdentityToken::from_request_parts(parts, state).await;
+ let Ok(cookie) = IdentityCookie::from_request_parts(parts, state).await;
let RequestedAt(used_at) = RequestedAt::from_request_parts(parts, state).await?;
- let secret = identity_token.secret().ok_or(LoginError::Unauthorized)?;
+ let secret = cookie.secret().ok_or(LoginError::Unauthorized)?;
let app = State::<App>::from_request_parts(parts, state).await?;
match app.tokens().validate(&secret, &used_at).await {
diff --git a/src/token/extract/mod.rs b/src/token/extract/mod.rs
index b4800ae..fc0f52b 100644
--- a/src/token/extract/mod.rs
+++ b/src/token/extract/mod.rs
@@ -1,4 +1,4 @@
+mod cookie;
mod identity;
-mod identity_token;
-pub use self::{identity::Identity, identity_token::IdentityToken};
+pub use self::{cookie::Identity as IdentityCookie, identity::Identity};
diff --git a/src/ui/routes/ch/channel.rs b/src/ui/routes/ch/channel.rs
index 353d000..a338f1f 100644
--- a/src/ui/routes/ch/channel.rs
+++ b/src/ui/routes/ch/channel.rs
@@ -8,7 +8,7 @@ pub mod get {
app::App,
channel,
error::Internal,
- login::Login,
+ token::extract::Identity,
ui::{
assets::{Asset, Assets},
error::NotFound,
@@ -17,10 +17,10 @@ pub mod get {
pub async fn handler(
State(app): State<App>,
- login: Option<Login>,
+ identity: Option<Identity>,
Path(channel): Path<channel::Id>,
) -> Result<Asset, Error> {
- login.ok_or(Error::NotLoggedIn)?;
+ let _ = identity.ok_or(Error::NotLoggedIn)?;
app.channels()
.get(&channel)
.await
diff --git a/src/ui/routes/get.rs b/src/ui/routes/get.rs
index 97737e1..2fcb51c 100644
--- a/src/ui/routes/get.rs
+++ b/src/ui/routes/get.rs
@@ -2,12 +2,12 @@ use axum::response::{self, IntoResponse, Redirect};
use crate::{
error::Internal,
- login::Login,
+ token::extract::Identity,
ui::assets::{Asset, Assets},
};
-pub async fn handler(login: Option<Login>) -> Result<Asset, Error> {
- login.ok_or(Error::NotLoggedIn)?;
+pub async fn handler(identity: Option<Identity>) -> Result<Asset, Error> {
+ let _ = identity.ok_or(Error::NotLoggedIn)?;
Assets::index().map_err(Error::Internal)
}