mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-13 21:42:34 +00:00
Add authentication with session cookie
This commit is contained in:
@@ -16,4 +16,4 @@ thiserror = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
actix-web = { workspace = true }
|
||||
rustical_store = { workspace = true }
|
||||
actix-files = "0.6.6"
|
||||
actix-files = "0.6"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[general]
|
||||
dirs = ["frontend/dist/src/templates"]
|
||||
dirs = ["frontend/dist/templates"]
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{% block title %}RustiCal{% endblock %}</title>
|
||||
<script type="module" src="htmx.org"></script>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
{% block imports %}{% endblock %}
|
||||
</head>
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{% extends "layouts/default.html" %}
|
||||
|
||||
{% block imports %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Test</h1>
|
||||
<a href="/frontend/user/{{ calendar.principal }}">Back</a>
|
||||
{% endblock %}
|
||||
@@ -1,20 +1,21 @@
|
||||
{% extends "layouts/default.html" %}
|
||||
|
||||
{% block imports %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<style>
|
||||
li {
|
||||
list-style: none;
|
||||
display: block;
|
||||
margin: 12px;
|
||||
height: 80px;
|
||||
min-height: 80px;
|
||||
background: #EEE;
|
||||
padding: 8px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Welcome {{ owner }}!</h2>
|
||||
<h2>Welcome {{ user_id }}!</h2>
|
||||
<ul>
|
||||
{% for calendar in calendars %}
|
||||
<li>
|
||||
@@ -23,9 +24,12 @@ li {
|
||||
{% else %}
|
||||
{{ calendar.id }}
|
||||
{% endif %}
|
||||
<p>
|
||||
{% let color = calendar.color.to_owned().unwrap_or("red".to_owned()) %}
|
||||
<p style="color: {{ color }}">
|
||||
{% if let Some(description) = calendar.description %}{{ description }}{% endif %}
|
||||
</p>
|
||||
<!-- <a href="{{ calendar.id}}">Test</a> -->
|
||||
<a href="/frontend/user/{{ user_id }}/{{ calendar.id}}">Test</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
@@ -3,19 +3,9 @@ import { globSync } from 'glob'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
console.log(
|
||||
Object.fromEntries(globSync('src/templates/**/*.html').map(file => [
|
||||
path.relative(
|
||||
'src',
|
||||
file.slice(0, file.length - path.extname(file).length)
|
||||
),
|
||||
// This expands the relative paths to absolute paths, so e.g.
|
||||
// src/nested/foo becomes /project/src/nested/foo.js
|
||||
fileURLToPath(new URL(file, import.meta.url))
|
||||
])),
|
||||
)
|
||||
|
||||
export default defineConfig({
|
||||
root: "src",
|
||||
base: "/frontend",
|
||||
build: {
|
||||
modulePreload: {
|
||||
polyfill: false
|
||||
|
||||
@@ -8,7 +8,7 @@ use actix_web::{
|
||||
use askama::Template;
|
||||
use routes::login::{route_get_login, route_post_login};
|
||||
use rustical_store::{
|
||||
auth::{AuthenticationMiddleware, AuthenticationProvider},
|
||||
auth::{AuthenticationMiddleware, AuthenticationProvider, User},
|
||||
model::Calendar,
|
||||
CalendarStore,
|
||||
};
|
||||
@@ -23,19 +23,39 @@ pub use config::FrontendConfig;
|
||||
#[derive(Template)]
|
||||
#[template(path = "pages/user.html")]
|
||||
struct UserPage {
|
||||
pub owner: String,
|
||||
pub user_id: String,
|
||||
pub calendars: Vec<Calendar>,
|
||||
}
|
||||
|
||||
async fn route_user<C: CalendarStore + ?Sized>(
|
||||
path: Path<String>,
|
||||
store: Data<RwLock<C>>,
|
||||
user: User,
|
||||
) -> impl Responder {
|
||||
let store = store.read().await;
|
||||
let owner = path.into_inner();
|
||||
let user_id = path.into_inner();
|
||||
UserPage {
|
||||
calendars: store.get_calendars(&user.id).await.unwrap(),
|
||||
user_id: user.id,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "pages/calendar.html")]
|
||||
struct CalendarPage {
|
||||
owner: String,
|
||||
calendar: Calendar,
|
||||
}
|
||||
|
||||
async fn route_calendar<C: CalendarStore + ?Sized>(
|
||||
path: Path<(String, String)>,
|
||||
store: Data<RwLock<C>>,
|
||||
) -> impl Responder {
|
||||
let store = store.read().await;
|
||||
let (owner, cid) = path.into_inner();
|
||||
CalendarPage {
|
||||
owner: owner.to_owned(),
|
||||
calendars: store.get_calendars(&owner).await.unwrap(),
|
||||
calendar: store.get_calendar(&owner, &cid).await.unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +83,10 @@ pub fn configure_frontend<AP: AuthenticationProvider, C: CalendarStore + ?Sized>
|
||||
.service(
|
||||
web::resource("/user/{user}").route(web::method(Method::GET).to(route_user::<C>)),
|
||||
)
|
||||
.service(
|
||||
web::resource("/user/{user}/{calendar}")
|
||||
.route(web::method(Method::GET).to(route_calendar::<C>)),
|
||||
)
|
||||
.service(
|
||||
web::resource("/login")
|
||||
.route(web::method(Method::GET).to(route_get_login))
|
||||
|
||||
@@ -23,6 +23,7 @@ rstest_reuse = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
password-auth = { workspace = true }
|
||||
actix-web = { workspace = true }
|
||||
actix-session = { workspace = true }
|
||||
actix-web-httpauth = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
pbkdf2 = { workspace = true }
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use super::AuthenticationProvider;
|
||||
use super::{AuthenticationProvider, User};
|
||||
use actix_session::Session;
|
||||
use actix_web::{
|
||||
dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
|
||||
http::header::Header,
|
||||
HttpMessage,
|
||||
FromRequest, HttpMessage,
|
||||
};
|
||||
use actix_web_httpauth::headers::authorization::{Authorization, Basic};
|
||||
use std::{
|
||||
@@ -77,6 +78,20 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract user from session cookie
|
||||
if let Ok(session) = Session::extract(req.request()).await {
|
||||
println!("There's a session!");
|
||||
match session.get::<User>("user") {
|
||||
Ok(Some(user)) => {
|
||||
req.extensions_mut().insert(user);
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
dbg!(err);
|
||||
}
|
||||
};
|
||||
}
|
||||
service.call(req).await
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user