Add permissions to the page
This commit is contained in:
+131
-248
@@ -6,32 +6,16 @@ use actix_web::{
|
||||
web, HttpResponse,
|
||||
};
|
||||
use argonautica::Verifier;
|
||||
use diesel::{prelude::*, result::Error::NotFound, sqlite::SqliteConnection};
|
||||
use dotenv::dotenv;
|
||||
use image::{DynamicImage, ImageOutputFormat, Luma};
|
||||
use qrcode::{render::svg, QrCode};
|
||||
use tera::{Context, Tera};
|
||||
|
||||
use super::forms::LinkForm;
|
||||
use super::models::{Count, Link, LoginUser, NewClick, NewLink, NewUser, User};
|
||||
use super::models::{LoginUser, NewUser};
|
||||
use crate::queries;
|
||||
use crate::ServerError;
|
||||
|
||||
pub(super) fn establish_connection() -> Result<SqliteConnection, ServerError> {
|
||||
dotenv().ok();
|
||||
|
||||
let database_url = std::env::var("DATABASE_URL")?;
|
||||
|
||||
match SqliteConnection::establish(&database_url) {
|
||||
Ok(c) => Ok(c),
|
||||
Err(e) => {
|
||||
info!("Error connecting to database: {}, {}", database_url, e);
|
||||
Err(ServerError::User(
|
||||
"Error connecting to Database".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn redirect_builder(target: &str) -> HttpResponse {
|
||||
HttpResponse::SeeOther()
|
||||
.set(CacheControl(vec![
|
||||
@@ -49,36 +33,11 @@ pub(crate) async fn index(
|
||||
tera: web::Data<Tera>,
|
||||
id: Identity,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
use super::schema::clicks;
|
||||
use super::schema::links;
|
||||
use super::schema::users;
|
||||
if let Some(id) = id.identity() {
|
||||
let connection = establish_connection()?;
|
||||
let query = links::dsl::links
|
||||
.inner_join(users::dsl::users)
|
||||
.left_join(clicks::dsl::clicks)
|
||||
.group_by(links::id)
|
||||
.select((
|
||||
(
|
||||
links::id,
|
||||
links::title,
|
||||
links::target,
|
||||
links::code,
|
||||
links::author,
|
||||
links::created_at,
|
||||
),
|
||||
(users::id, users::username, users::email, users::password),
|
||||
(diesel::dsl::sql::<diesel::sql_types::Integer>(
|
||||
"COUNT(clicks.id)",
|
||||
),),
|
||||
));
|
||||
let all_links: Vec<(Link, User, Count)> = query.load(&connection)?;
|
||||
|
||||
if let Ok(links) = queries::list_all_allowed(id) {
|
||||
let mut data = Context::new();
|
||||
data.insert("name", &id);
|
||||
data.insert("user", &links.user);
|
||||
data.insert("title", "Links der Freien Hochschule Stuttgart");
|
||||
data.insert("links_per_users", &all_links);
|
||||
|
||||
data.insert("links_per_users", &links.list);
|
||||
let rendered = tera.render("index.html", &data)?;
|
||||
Ok(HttpResponse::Ok().body(rendered))
|
||||
} else {
|
||||
@@ -91,20 +50,16 @@ pub(crate) async fn index_users(
|
||||
tera: web::Data<Tera>,
|
||||
id: Identity,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
use super::schema::users::dsl::users;
|
||||
if let Some(id) = id.identity() {
|
||||
let connection = establish_connection()?;
|
||||
let all_users: Vec<User> = users.load(&connection)?;
|
||||
|
||||
if let Ok(users) = queries::list_users(id) {
|
||||
let mut data = Context::new();
|
||||
data.insert("name", &id);
|
||||
data.insert("user", &users.user);
|
||||
data.insert("title", "Benutzer der Freien Hochschule Stuttgart");
|
||||
data.insert("users", &all_users);
|
||||
data.insert("users", &users.list);
|
||||
|
||||
let rendered = tera.render("index_users.html", &data)?;
|
||||
Ok(HttpResponse::Ok().body(rendered))
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
Ok(redirect_builder("/admin/login"))
|
||||
}
|
||||
}
|
||||
pub(crate) async fn view_link_fhs(
|
||||
@@ -119,18 +74,15 @@ pub(crate) async fn view_link(
|
||||
id: Identity,
|
||||
link_id: web::Path<String>,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
use super::schema::links::dsl::{code, links};
|
||||
if let Some(id) = id.identity() {
|
||||
let connection = establish_connection()?;
|
||||
let link: Link = links
|
||||
.filter(code.eq(&link_id.0))
|
||||
.first::<Link>(&connection)?;
|
||||
|
||||
if let Ok(link) = queries::get_link(id, &link_id.0) {
|
||||
dotenv().ok();
|
||||
let host = std::env::var("SLINK_HOST")?;
|
||||
let protocol = std::env::var("SLINK_PROTOCOL")?;
|
||||
let qr = QrCode::with_error_correction_level(
|
||||
&format!("http://fhs.li/{}", &link_id),
|
||||
&format!("http://{}/{}", &host, &link.item.id),
|
||||
qrcode::EcLevel::L,
|
||||
)
|
||||
.unwrap();
|
||||
)?;
|
||||
|
||||
let svg = qr
|
||||
.render()
|
||||
.min_dimensions(200, 200)
|
||||
@@ -139,13 +91,15 @@ pub(crate) async fn view_link(
|
||||
.build();
|
||||
|
||||
let mut data = Context::new();
|
||||
data.insert("name", &id);
|
||||
data.insert("user", &link.user);
|
||||
data.insert(
|
||||
"title",
|
||||
&format!("Links {} der Freien Hochschule Stuttgart", link_id.0),
|
||||
&format!("Links {} der Freien Hochschule Stuttgart", &link.item.id),
|
||||
);
|
||||
data.insert("link", &link);
|
||||
data.insert("link", &link.item);
|
||||
data.insert("qr", &svg);
|
||||
data.insert("host", &host);
|
||||
data.insert("protocol", &protocol);
|
||||
|
||||
let rendered = tera.render("view_link.html", &data)?;
|
||||
Ok(HttpResponse::Ok().body(rendered))
|
||||
@@ -156,65 +110,50 @@ pub(crate) async fn view_link(
|
||||
|
||||
pub(crate) async fn view_profile(
|
||||
tera: web::Data<Tera>,
|
||||
identity: Identity,
|
||||
id: Identity,
|
||||
user_id: web::Path<String>,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
use super::schema::users::dsl::{id, users};
|
||||
info!("Viewing Profile!");
|
||||
if let Some(identity) = identity.identity() {
|
||||
let connection = establish_connection()?;
|
||||
if let Ok(uid) = user_id.parse::<i32>() {
|
||||
let user = users.filter(id.eq(&uid)).first::<User>(&connection)?;
|
||||
if let Ok(query) = queries::get_user(id, &user_id.0) {
|
||||
let mut data = Context::new();
|
||||
data.insert("user", &query.user);
|
||||
data.insert(
|
||||
"title",
|
||||
&format!(
|
||||
"Benutzer {} der Freien Hochschule Stuttgart",
|
||||
&query.item.username
|
||||
),
|
||||
);
|
||||
data.insert("viewed_user", &query.item);
|
||||
|
||||
let mut data = Context::new();
|
||||
data.insert("name", &identity);
|
||||
data.insert(
|
||||
"title",
|
||||
&format!(
|
||||
"Benutzer {} der Freien Hochschule Stuttgart",
|
||||
&user.username
|
||||
),
|
||||
);
|
||||
data.insert("user", &user);
|
||||
|
||||
let rendered = tera.render("view_profile.html", &data)?;
|
||||
Ok(HttpResponse::Ok().body(rendered))
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/index/"))
|
||||
}
|
||||
let rendered = tera.render("view_profile.html", &data)?;
|
||||
Ok(HttpResponse::Ok().body(rendered))
|
||||
} else {
|
||||
// Parsing error -- do something else
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn edit_profile(
|
||||
tera: web::Data<Tera>,
|
||||
identity: Identity,
|
||||
id: Identity,
|
||||
user_id: web::Path<String>,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
use super::schema::users::dsl::{id, users};
|
||||
info!("Editing Profile!");
|
||||
if let Some(identity) = identity.identity() {
|
||||
let connection = establish_connection()?;
|
||||
if let Ok(uid) = user_id.parse::<i32>() {
|
||||
let user = users.filter(id.eq(&uid)).first::<User>(&connection)?;
|
||||
if let Ok(query) = queries::get_user(id, &user_id.0) {
|
||||
let mut data = Context::new();
|
||||
data.insert("user", &query.user);
|
||||
data.insert(
|
||||
"title",
|
||||
&format!(
|
||||
"Benutzer {} der Freien Hochschule Stuttgart",
|
||||
&query.user.username
|
||||
),
|
||||
);
|
||||
data.insert("user", &query.user);
|
||||
|
||||
let mut data = Context::new();
|
||||
data.insert("name", &identity);
|
||||
data.insert(
|
||||
"title",
|
||||
&format!(
|
||||
"Benutzer {} der Freien Hochschule Stuttgart",
|
||||
&user.username
|
||||
),
|
||||
);
|
||||
data.insert("user", &user);
|
||||
|
||||
let rendered = tera.render("edit_profile.html", &data)?;
|
||||
Ok(HttpResponse::Ok().body(rendered))
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/index/"))
|
||||
}
|
||||
let rendered = tera.render("edit_profile.html", &data)?;
|
||||
Ok(HttpResponse::Ok().body(rendered))
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
}
|
||||
@@ -225,43 +164,29 @@ pub(crate) async fn process_edit_profile(
|
||||
id: Identity,
|
||||
user_id: web::Path<String>,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
if let Some(_id) = id.identity() {
|
||||
use super::schema::users::dsl::{email, id, password, username, users};
|
||||
|
||||
if let Ok(uid) = user_id.parse::<i32>() {
|
||||
info!("Updating userinfo: ");
|
||||
let connection = establish_connection()?;
|
||||
diesel::update(users.filter(id.eq(uid)))
|
||||
.set((
|
||||
username.eq(data.username.clone()),
|
||||
email.eq(data.email.clone()),
|
||||
))
|
||||
.execute(&connection)?;
|
||||
if data.password.len() > 3 {
|
||||
let hash = NewUser::hash_password(data.password.clone())?;
|
||||
diesel::update(users.filter(id.eq(uid)))
|
||||
.set((password.eq(hash),))
|
||||
.execute(&connection)?;
|
||||
}
|
||||
Ok(HttpResponse::Ok().body(format!("Successfully saved user: {}", data.username)))
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/index/"))
|
||||
}
|
||||
if let Ok(query) = queries::update_user(id, &user_id.0, data) {
|
||||
Ok(redirect_builder(&format!(
|
||||
"admin/view/profile/{}",
|
||||
query.user.username
|
||||
)))
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
Ok(redirect_builder("/admin/index/"))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn download_png(
|
||||
id: Identity,
|
||||
link_id: web::Path<String>,
|
||||
link_code: web::Path<String>,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
if let Some(_id) = id.identity() {
|
||||
use super::schema::links::dsl::{code, links};
|
||||
let connection = establish_connection()?;
|
||||
if let Ok(_link) = links.filter(code.eq(&link_id.0)).first::<Link>(&connection) {
|
||||
match queries::get_link(id, &link_code.0) {
|
||||
Ok(query) => {
|
||||
dotenv().ok();
|
||||
let qr = QrCode::with_error_correction_level(
|
||||
&format!("http://fhs.li/{}", &link_id),
|
||||
&format!(
|
||||
"http://{}/{}",
|
||||
std::env::var("SLINK_HOST")?,
|
||||
&query.item.code
|
||||
),
|
||||
qrcode::EcLevel::L,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -272,11 +197,8 @@ pub(crate) async fn download_png(
|
||||
.unwrap();
|
||||
let image_data = temporary_data.into_inner();
|
||||
Ok(HttpResponse::Ok().set(ContentType::png()).body(image_data))
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/index/"))
|
||||
}
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,15 +206,18 @@ pub(crate) async fn signup(
|
||||
tera: web::Data<Tera>,
|
||||
id: Identity,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
if let Some(id) = id.identity() {
|
||||
let mut data = Context::new();
|
||||
data.insert("title", "Sign Up");
|
||||
data.insert("name", &id);
|
||||
match queries::authenticate(id)? {
|
||||
queries::Role::Admin { user } => {
|
||||
let mut data = Context::new();
|
||||
data.insert("title", "Ein Benutzerkonto erstellen");
|
||||
data.insert("user", &user);
|
||||
|
||||
let rendered = tera.render("signup.html", &data)?;
|
||||
Ok(HttpResponse::Ok().body(rendered))
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
let rendered = tera.render("signup.html", &data)?;
|
||||
Ok(HttpResponse::Ok().body(rendered))
|
||||
}
|
||||
queries::Role::Regular { .. }
|
||||
| queries::Role::NotAuthenticated
|
||||
| queries::Role::Disabled => Ok(redirect_builder("/admin/login/")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,26 +225,25 @@ pub(crate) async fn process_signup(
|
||||
data: web::Form<NewUser>,
|
||||
id: Identity,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
if let Some(_id) = id.identity() {
|
||||
use super::schema::users;
|
||||
|
||||
let connection = establish_connection()?;
|
||||
let new_user = NewUser::new(
|
||||
data.username.clone(),
|
||||
data.email.clone(),
|
||||
data.password.clone(),
|
||||
)?;
|
||||
|
||||
diesel::insert_into(users::table)
|
||||
.values(&new_user)
|
||||
.execute(&connection)?;
|
||||
|
||||
Ok(HttpResponse::Ok().body(format!("Successfully saved user: {}", data.username)))
|
||||
info!("Creating a User: {:?}", &data);
|
||||
if let Ok(item) = queries::create_user(id, data) {
|
||||
Ok(HttpResponse::Ok().body(format!("Successfully saved user: {}", item.item.username)))
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn toggle_admin(
|
||||
data: web::Path<String>,
|
||||
id: Identity,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
let update = queries::toggle_admin(id, &data.0)?;
|
||||
Ok(redirect_builder(&format!(
|
||||
"/admin/view/profile/{}",
|
||||
update.item.id
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) async fn login(
|
||||
tera: web::Data<Tera>,
|
||||
id: Identity,
|
||||
@@ -339,12 +263,7 @@ pub(crate) async fn process_login(
|
||||
data: web::Form<LoginUser>,
|
||||
id: Identity,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
use super::schema::users::dsl::{username, users};
|
||||
|
||||
let connection = establish_connection()?;
|
||||
let user = users
|
||||
.filter(username.eq(&data.username))
|
||||
.first::<User>(&connection);
|
||||
let user = queries::get_user_by_name(&data.username);
|
||||
|
||||
match user {
|
||||
Ok(u) => {
|
||||
@@ -381,22 +300,22 @@ pub(crate) async fn redirect(
|
||||
tera: web::Data<Tera>,
|
||||
data: web::Path<String>,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
use super::schema::links::dsl::{code, links};
|
||||
let connection = establish_connection()?;
|
||||
|
||||
let link = links.filter(code.eq(&data.0)).first::<Link>(&connection);
|
||||
info!("Redirecting to {:?}", data);
|
||||
let link = queries::get_link_simple(&data.0);
|
||||
info!("link: {:?}", link);
|
||||
match link {
|
||||
Ok(link) => {
|
||||
use super::schema::clicks;
|
||||
let new_click = NewClick::new(link.id);
|
||||
let connection = establish_connection()?;
|
||||
|
||||
diesel::insert_into(clicks::table)
|
||||
.values(&new_click)
|
||||
.execute(&connection)?;
|
||||
queries::click_link(link.id)?;
|
||||
Ok(redirect_builder(&link.target))
|
||||
}
|
||||
Err(NotFound) => {
|
||||
Err(ServerError::Diesel(e)) => {
|
||||
dotenv().ok();
|
||||
info!(
|
||||
"Link was not found: http://{}/{} \n {}",
|
||||
std::env::var("SLINK_HOST")?,
|
||||
&data.0,
|
||||
e
|
||||
);
|
||||
let mut data = Context::new();
|
||||
data.insert("title", "Wurde gelöscht");
|
||||
let rendered = tera.render("not_found.html", &data)?;
|
||||
@@ -416,44 +335,30 @@ pub(crate) async fn create_link(
|
||||
tera: web::Data<Tera>,
|
||||
id: Identity,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
if let Some(id) = id.identity() {
|
||||
let mut data = Context::new();
|
||||
data.insert("title", "Submit a Post");
|
||||
match queries::authenticate(id)? {
|
||||
queries::Role::Admin { user } | queries::Role::Regular { user } => {
|
||||
let mut data = Context::new();
|
||||
data.insert("title", "Einen Kurzlink erstellen");
|
||||
|
||||
data.insert("name", &id);
|
||||
let rendered = tera.render("submission.html", &data)?;
|
||||
return Ok(HttpResponse::Ok().body(rendered));
|
||||
data.insert("user", &user);
|
||||
let rendered = tera.render("submission.html", &data)?;
|
||||
Ok(HttpResponse::Ok().body(rendered))
|
||||
}
|
||||
queries::Role::NotAuthenticated | queries::Role::Disabled => {
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
}
|
||||
}
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
}
|
||||
|
||||
pub(crate) async fn process_link_creation(
|
||||
data: web::Form<LinkForm>,
|
||||
id: Identity,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
if let Some(id) = id.identity() {
|
||||
use super::schema::users::dsl::{username, users};
|
||||
|
||||
let connection = establish_connection()?;
|
||||
let user: Result<User, diesel::result::Error> =
|
||||
users.filter(username.eq(id)).first(&connection);
|
||||
|
||||
match user {
|
||||
Ok(u) => {
|
||||
use super::schema::links;
|
||||
let new_post = NewLink::from_link_form(data.into_inner(), u.id);
|
||||
|
||||
diesel::insert_into(links::table)
|
||||
.values(&new_post)
|
||||
.execute(&connection)?;
|
||||
|
||||
return Ok(redirect_builder("/admin/index/"));
|
||||
}
|
||||
Err(_e) => Ok(redirect_builder("/admin/login/")),
|
||||
}
|
||||
} else {
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
}
|
||||
let new_link = queries::create_link(id, data)?;
|
||||
Ok(redirect_builder(&format!(
|
||||
"/admin/view/link/{}",
|
||||
new_link.item.code
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) async fn edit_link(
|
||||
@@ -461,17 +366,12 @@ pub(crate) async fn edit_link(
|
||||
id: Identity,
|
||||
link_id: web::Path<String>,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
if let Some(id) = id.identity() {
|
||||
use super::schema::links::dsl::{code, links};
|
||||
let connection = establish_connection()?;
|
||||
let link: Link = links
|
||||
.filter(code.eq(&link_id.0))
|
||||
.first::<Link>(&connection)?;
|
||||
if let Ok(query) = queries::get_link(id, &link_id.0) {
|
||||
let mut data = Context::new();
|
||||
data.insert("title", "Submit a Post");
|
||||
data.insert("link", &link);
|
||||
data.insert("link", &query.item);
|
||||
|
||||
data.insert("name", &id);
|
||||
data.insert("user", &query.user);
|
||||
let rendered = tera.render("edit_link.html", &data)?;
|
||||
return Ok(HttpResponse::Ok().body(rendered));
|
||||
}
|
||||
@@ -480,38 +380,21 @@ pub(crate) async fn edit_link(
|
||||
pub(crate) async fn process_link_edit(
|
||||
data: web::Form<LinkForm>,
|
||||
id: Identity,
|
||||
link_id: web::Path<String>,
|
||||
link_code: web::Path<String>,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
if let Some(_id) = id.identity() {
|
||||
use super::schema::links::dsl::{code, links, target, title};
|
||||
|
||||
let connection = establish_connection()?;
|
||||
|
||||
diesel::update(links.filter(code.eq(&link_id.0)))
|
||||
.set((
|
||||
code.eq(&data.code),
|
||||
target.eq(&data.target),
|
||||
title.eq(&data.title),
|
||||
))
|
||||
.execute(&connection)?;
|
||||
|
||||
return Ok(redirect_builder(&format!(
|
||||
match queries::update_link(id, &link_code.0, data) {
|
||||
Ok(query) => Ok(redirect_builder(&format!(
|
||||
"/admin/view/link/{}",
|
||||
&data.code
|
||||
)));
|
||||
&query.item.code
|
||||
))),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
}
|
||||
|
||||
pub(crate) async fn process_link_delete(
|
||||
id: Identity,
|
||||
link_id: web::Path<String>,
|
||||
link_code: web::Path<String>,
|
||||
) -> Result<HttpResponse, ServerError> {
|
||||
if let Some(_id) = id.identity() {
|
||||
use super::schema::links::dsl::{code, links};
|
||||
let connection = establish_connection()?;
|
||||
diesel::delete(links.filter(code.eq(&link_id.0))).execute(&connection)?;
|
||||
return Ok(redirect_builder("/admin/index/"));
|
||||
}
|
||||
queries::delete_link(id, link_code.0)?;
|
||||
Ok(redirect_builder("/admin/login/"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user