Browse Source

Reformatted code according to rustfmt

master
Keanu D?lle 2 years ago
parent
commit
04a9eb1619
  1. 14
      src/database/connection.rs
  2. 66
      src/database/login.rs
  3. 28
      src/database/permissions.rs
  4. 265
      src/database/profile.rs
  5. 247
      src/database/profile_communication.rs
  6. 10
      src/lang/lang.rs
  7. 24
      src/lang/parse.rs
  8. 51
      src/lang/setup.rs
  9. 77
      src/main.rs
  10. 114
      src/modules/login.rs
  11. 135
      src/modules/mod.rs
  12. 42
      src/modules/permissions.rs
  13. 25
      src/modules/portal.rs
  14. 191
      src/modules/profile.rs
  15. 1
      src/modules/resources.rs
  16. 4
      src/sitebuilder/builder.rs
  17. 42
      src/sitebuilder/internal_site.rs
  18. 13
      src/sitebuilder/mod.rs
  19. 74
      src/sitebuilder/profile_communication.rs
  20. 57
      src/sitebuilder/sidebar.rs
  21. 18
      src/sitebuilder/stylesheets.rs

14
src/database/connection.rs

@ -1,6 +1,14 @@
use crate::SETTINGS;
pub fn connect() -> mysql::Pool{
pub fn connect() -> mysql::Pool {
let settings = SETTINGS.read().unwrap();
mysql::Pool::new(format!("mysql://{}:{}@{}:{}/{}", settings.get::<String>("mysql_username").unwrap(), settings.get::<String>("mysql_password").unwrap(), settings.get::<String>("mysql_host").unwrap(), settings.get::<String>("mysql_port").unwrap(), settings.get::<String>("mysql_database").unwrap())).unwrap()
}
mysql::Pool::new(format!(
"mysql://{}:{}@{}:{}/{}",
settings.get::<String>("mysql_username").unwrap(),
settings.get::<String>("mysql_password").unwrap(),
settings.get::<String>("mysql_host").unwrap(),
settings.get::<String>("mysql_port").unwrap(),
settings.get::<String>("mysql_database").unwrap()
))
.unwrap()
}

66
src/database/login.rs

@ -1,23 +1,30 @@
use crate::database::connection::connect;
use crate::lang::parse::{parse_fallback, parse_or_fallback};
use crate::modules::login::UserData;
use crate::lang::parse::{parse_or_fallback, parse_fallback};
use mysql::Value;
use crate::sitebuilder::sidebar::parse;
use mysql::Value;
pub fn get_user_hash(email : String) -> Option<String>{
pub fn get_user_hash(email: String) -> Option<String> {
let pool = connect();
pool.prep_exec(r"SELECT password_hash FROM users WHERE email = :email", params!{"email" => email}).map(|mut result|{
match result.next(){
Some(row) => Some(row.unwrap().take("password_hash").unwrap()),
None => None
}
}).unwrap()
pool.prep_exec(
r"SELECT password_hash FROM users WHERE email = :email",
params! {"email" => email},
)
.map(|mut result| match result.next() {
Some(row) => Some(row.unwrap().take("password_hash").unwrap()),
None => None,
})
.unwrap()
}
pub fn get_user_login_data(email : &str) -> Option<UserData>{
pub fn get_user_login_data(email: &str) -> Option<UserData> {
let pool = connect();
pool.prep_exec(r"SELECT id, firstname, lastname, language FROM users WHERE email = :email", params!{"email" => email}).map(|mut result|{
match result.next(){
pool.prep_exec(
r"SELECT id, firstname, lastname, language FROM users WHERE email = :email",
params! {"email" => email},
)
.map(|mut result| {
match result.next() {
Some(row) => {
let mut row = row.unwrap().clone();
@ -25,24 +32,25 @@ pub fn get_user_login_data(email : &str) -> Option<UserData>{
id: row.take("id").unwrap(),
firstname: row.take("firstname").unwrap(),
lastname: row.take("lastname").unwrap(),
language:
match row.take_opt("language") {
Some(language) => {
match language{
Ok(langid) => match parse_or_fallback(langid){
Some(langid) => langid,
None => return None
},
Err(_) => { //Use fallback language when there is no language
parse_fallback().unwrap()
}
}},
None => parse_fallback().unwrap()
language: match row.take_opt("language") {
Some(language) => {
match language {
Ok(langid) => match parse_or_fallback(langid) {
Some(langid) => langid,
None => return None,
},
Err(_) => {
//Use fallback language when there is no language
parse_fallback().unwrap()
}
}
}
None => parse_fallback().unwrap(),
},
})
},
None => None
}
None => None,
}
}).unwrap()
})
.unwrap()
}

28
src/database/permissions.rs

@ -1,36 +1,44 @@
use crate::modules::permissions::UserPermissions;
use crate::database::connection::connect;
use crate::modules::permissions::UserPermissions;
use mysql::Pool;
use std::collections::HashMap;
pub fn get_permissions(id : i32) -> UserPermissions{
pub fn get_permissions(id: i32) -> UserPermissions {
let pool = connect();
UserPermissions {
user_permissions: get_user_permissions(&pool, id),
group_permissions: get_group_permissions(&pool, id)
group_permissions: get_group_permissions(&pool, id),
}
}
pub fn get_user_permissions(pool : &Pool, id : i32) -> HashMap<String, bool>{
pool.prep_exec(r"SELECT f_permission_id, value FROM user_permissions WHERE f_user_id = :id", params!{"id" => id}).map(|mut result|{
pub fn get_user_permissions(pool: &Pool, id: i32) -> HashMap<String, bool> {
pool.prep_exec(
r"SELECT f_permission_id, value FROM user_permissions WHERE f_user_id = :id",
params! {"id" => id},
)
.map(|mut result| {
let mut permissions: HashMap<String, bool> = HashMap::new();
loop {
match result.next() {
Some(row) => {
let mut row = row.unwrap().clone();
permissions.insert(row.take("f_permission_id").unwrap(), row.take("value").unwrap());
permissions.insert(
row.take("f_permission_id").unwrap(),
row.take("value").unwrap(),
);
}
_ => break
_ => break,
}
}
permissions
}).unwrap()
})
.unwrap()
}
pub fn get_group_permissions(pool : &Pool, id : i32) -> HashMap<String, bool>{
pub fn get_group_permissions(pool: &Pool, id: i32) -> HashMap<String, bool> {
pool.prep_exec(r"SELECT f_permission_id, value FROM group_permissions WHERE f_group_id IN (SELECT f_group_id FROM users_groups WHERE f_user_id = :id)", params!{"id" => id}).map(|mut result|{
let mut permissions: HashMap<String, bool> = HashMap::new(); //TODO: filter permissions with priority
@ -47,4 +55,4 @@ pub fn get_group_permissions(pool : &Pool, id : i32) -> HashMap<String, bool>{
permissions
}).unwrap()
}
}

265
src/database/profile.rs

@ -1,129 +1,168 @@
use crate::database::connection::connect;
use crate::modules::permissions::{check_for_permission, UserPermissions};
use chrono::NaiveDate;
use crate::modules::permissions::{UserPermissions, check_for_permission};
use rocket::request::Form;
pub enum Sex{
pub enum Sex {
Unknown,
Male,
Female,
Other
Other,
}
#[derive(FromForm)]
pub struct ProfileFormData{
pub firstname : String,
pub lastname : String,
pub email : String,
pub date_of_birth : String,
pub birthplace : String,
pub sex : String,
pub academic_title : String,
pub salutation : String,
pub formal_salutation : String,
pub personnel_number : i32,
pub street : String,
pub street_number : String,
pub postcode : String,
pub place : String
pub struct ProfileFormData {
pub firstname: String,
pub lastname: String,
pub email: String,
pub date_of_birth: String,
pub birthplace: String,
pub sex: String,
pub academic_title: String,
pub salutation: String,
pub formal_salutation: String,
pub personnel_number: i32,
pub street: String,
pub street_number: String,
pub postcode: String,
pub place: String,
}
pub struct ProfileData{
pub firstname : String,
pub lastname : String,
pub email : Option<String>,
pub date_of_birth : Option<NaiveDate>,
pub birthplace : Option<String>,
pub sex : Option<Sex>,
pub academic_title : Option<String>,
pub salutation : Option<String>,
pub formal_salutation : Option<String>,
pub personnel_number : Option<i32>,
pub street : Option<String>,
pub street_number : Option<String>,
pub postcode : Option<String>,
pub place : Option<String>
pub struct ProfileData {
pub firstname: String,
pub lastname: String,
pub email: Option<String>,
pub date_of_birth: Option<NaiveDate>,
pub birthplace: Option<String>,
pub sex: Option<Sex>,
pub academic_title: Option<String>,
pub salutation: Option<String>,
pub formal_salutation: Option<String>,
pub personnel_number: Option<i32>,
pub street: Option<String>,
pub street_number: Option<String>,
pub postcode: Option<String>,
pub place: Option<String>,
}
pub fn sex_from_i8(val : Option<i8>) -> Option<Sex>{
pub fn sex_from_i8(val: Option<i8>) -> Option<Sex> {
if val.is_some() {
Some(match val.unwrap() {
0 => Sex::Unknown,
1 => Sex::Male,
2 => Sex::Female,
9 => Sex::Other,
_ => Sex::Other
_ => Sex::Other,
})
}else{
} else {
None
}
}
pub fn sex_to_i8(val : Sex) -> i8{
pub fn sex_to_i8(val: Sex) -> i8 {
match val {
Sex::Unknown => 0,
Sex::Male => 1,
Sex::Female => 2,
Sex::Other => 9
Sex::Unknown => 0,
Sex::Male => 1,
Sex::Female => 2,
Sex::Other => 9,
}
}
impl ProfileData{
pub fn to_vec(&self) -> Vec<(String, String)>{
return vec!(("firstname".to_string(), self.firstname.clone()), ("lastname".to_string(), self.lastname.clone()), ("email".to_string(), self.email.string_convert()), ("date_of_birth".to_string(), self.date_of_birth.string_convert()), ("birthplace".to_string(), self.birthplace.string_convert()), ("birthplace".to_string(), self.birthplace.string_convert()), ("sex".to_string(), self.sex.string_convert()), ("academic_title".to_string(), self.academic_title.string_convert()), ("salutation".to_string(), self.salutation.string_convert()), ("formal_salutation".to_string(), self.formal_salutation.string_convert()), ("personnel_number".to_string(), self.personnel_number.string_convert()), ("street".to_string(), self.street.string_convert()), ("street_number".to_string(), self.street_number.string_convert()), ("postcode".to_string(), self.postcode.string_convert()), ("place".to_string(), self.place.string_convert()))
impl ProfileData {
pub fn to_vec(&self) -> Vec<(String, String)> {
return vec![
("firstname".to_string(), self.firstname.clone()),
("lastname".to_string(), self.lastname.clone()),
("email".to_string(), self.email.string_convert()),
(
"date_of_birth".to_string(),
self.date_of_birth.string_convert(),
),
("birthplace".to_string(), self.birthplace.string_convert()),
("birthplace".to_string(), self.birthplace.string_convert()),
("sex".to_string(), self.sex.string_convert()),
(
"academic_title".to_string(),
self.academic_title.string_convert(),
),
("salutation".to_string(), self.salutation.string_convert()),
(
"formal_salutation".to_string(),
self.formal_salutation.string_convert(),
),
(
"personnel_number".to_string(),
self.personnel_number.string_convert(),
),
("street".to_string(), self.street.string_convert()),
(
"street_number".to_string(),
self.street_number.string_convert(),
),
("postcode".to_string(), self.postcode.string_convert()),
("place".to_string(), self.place.string_convert()),
];
}
}
pub trait StringConvert<T>{
pub trait StringConvert<T> {
fn string_convert(&self) -> String;
}
impl StringConvert<String> for Option<String>{
fn string_convert(&self) -> String{
impl StringConvert<String> for Option<String> {
fn string_convert(&self) -> String {
if self.is_some() {
self.as_ref().unwrap().to_string()
} else {
String::from("")
}.parse().unwrap()
}
.parse()
.unwrap()
}
}
impl StringConvert<i32> for Option<i32>{
fn string_convert(&self) -> String{
impl StringConvert<i32> for Option<i32> {
fn string_convert(&self) -> String {
if self.is_some() {
self.as_ref().unwrap().to_string()
} else {
String::from("")
}.parse().unwrap()
}
.parse()
.unwrap()
}
}
impl StringConvert<Sex> for Option<Sex>{
fn string_convert(&self) -> String{
impl StringConvert<Sex> for Option<Sex> {
fn string_convert(&self) -> String {
if self.is_some() {
match self.as_ref().unwrap(){
match self.as_ref().unwrap() {
Sex::Unknown => String::from(""),
Sex::Male => String::from("männlich"),
Sex::Female => String::from("weiblich"),
Sex::Other => String::from("sonstiges")
Sex::Other => String::from("sonstiges"),
}
} else {
String::from("")
}.parse().unwrap()
}
.parse()
.unwrap()
}
}
impl StringConvert<NaiveDate> for Option<NaiveDate>{
fn string_convert(&self) -> String{
impl StringConvert<NaiveDate> for Option<NaiveDate> {
fn string_convert(&self) -> String {
if self.is_some() {
self.as_ref().unwrap().format("%d.%m.%Y").to_string()
} else {
String::from("")
}.parse().unwrap()
}
.parse()
.unwrap()
}
}
pub fn get_profile_data(id : i32) -> Option<ProfileData>{
pub fn get_profile_data(id: i32) -> Option<ProfileData> {
let pool = connect();
pool.prep_exec(r"SELECT firstname, lastname, email, birthplace, date_of_birth, sex, academic_title, salutation, formal_salutation, personnel_number, street, street_number, postcode, place FROM users WHERE id = :id", params!{"id" => id}).map(| result| {
@ -148,7 +187,11 @@ pub fn get_profile_data(id : i32) -> Option<ProfileData>{
}).unwrap()
}
pub fn update_profile_data(id : i32, user_permissions : &UserPermissions, data : Form<ProfileFormData>) -> bool{
pub fn update_profile_data(
id: i32,
user_permissions: &UserPermissions,
data: Form<ProfileFormData>,
) -> bool {
let pool = connect();
let old_data = get_profile_data(id).unwrap();
@ -156,7 +199,7 @@ pub fn update_profile_data(id : i32, user_permissions : &UserPermissions, data :
debug!("Form: {}", data.firstname);
let mut stmt = pool.prepare(r"UPDATE users SET firstname = :firstname, lastname = :lastname, email = :email, birthplace = :birthplace, date_of_birth = :date_of_birth, sex = :sex, academic_title = :academic_title, salutation = :salutation, formal_salutation = :formal_salutation, personnel_number = :personnel_number, street = :street, street_number = :street_number, postcode = :postcode, place = :place WHERE id = :id").unwrap();
stmt.execute(params!{
stmt.execute(params! {
"firstname" => data.firstname,
"lastname" => data.lastname,
"email" => data.email,
@ -172,12 +215,17 @@ pub fn update_profile_data(id : i32, user_permissions : &UserPermissions, data :
"postcode" => data.postcode,
"place" => data.place,
"id" => id
}).unwrap();
})
.unwrap();
true
}
fn check_profile_data_permissions(user_permissions : &UserPermissions, new_data: Form<ProfileFormData>, old_data : ProfileData) -> ProfileData{
fn check_profile_data_permissions(
user_permissions: &UserPermissions,
new_data: Form<ProfileFormData>,
old_data: ProfileData,
) -> ProfileData {
let mut profile_data: ProfileData = ProfileData {
firstname: "".to_string(),
lastname: "".to_string(),
@ -192,87 +240,118 @@ fn check_profile_data_permissions(user_permissions : &UserPermissions, new_data:
street: None,
street_number: None,
postcode: None,
place: None
place: None,
};
if !check_for_permission("modules.edit.profile.own.general.firstname", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.general.firstname",
&user_permissions,
) {
profile_data.firstname = old_data.firstname;
}else{
} else {
profile_data.firstname = new_data.firstname.clone();
}
if !check_for_permission("modules.edit.profile.own.general.lastname", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.general.lastname",
&user_permissions,
) {
profile_data.lastname = old_data.lastname;
}else{
} else {
profile_data.lastname = new_data.lastname.clone();
}
if !check_for_permission("modules.edit.profile.own.general.email", &user_permissions) {
profile_data.email = old_data.email;
}else{
} else {
profile_data.email = Some(new_data.email.clone());
}
if !check_for_permission("modules.edit.profile.own.general.birthplace", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.general.birthplace",
&user_permissions,
) {
profile_data.birthplace = old_data.birthplace;
}else{
} else {
profile_data.birthplace = Some(new_data.birthplace.clone());
}
if !check_for_permission("modules.edit.profile.own.general.date_of_birth", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.general.date_of_birth",
&user_permissions,
) {
profile_data.date_of_birth = old_data.date_of_birth;
}else{
} else {
debug!("date: {}", new_data.date_of_birth);
profile_data.date_of_birth = Some(NaiveDate::parse_from_str(&new_data.date_of_birth, "%d.%m.%Y").unwrap());
profile_data.date_of_birth =
Some(NaiveDate::parse_from_str(&new_data.date_of_birth, "%d.%m.%Y").unwrap());
}
if !check_for_permission("modules.edit.profile.own.general.sex", &user_permissions) {
profile_data.sex = old_data.sex;
}else{
let sex = match new_data.sex.as_str(){
} else {
let sex = match new_data.sex.as_str() {
"" => Sex::Unknown,
"männlich" => Sex::Male,
"weiblich" => Sex::Female,
"sonstiges" => Sex::Other,
_ => Sex::Unknown
_ => Sex::Unknown,
};
profile_data.sex = Some(sex);
}
if !check_for_permission("modules.edit.profile.own.general.academic_title", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.general.academic_title",
&user_permissions,
) {
profile_data.academic_title = old_data.academic_title;
}else{
} else {
profile_data.academic_title = Some(new_data.academic_title.clone());
}
if !check_for_permission("modules.edit.profile.own.general.salutation", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.general.salutation",
&user_permissions,
) {
profile_data.salutation = old_data.salutation;
}else{
} else {
profile_data.salutation = Some(new_data.salutation.clone());
}
if !check_for_permission("modules.edit.profile.own.general.formal_salutation", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.general.formal_salutation",
&user_permissions,
) {
profile_data.formal_salutation = old_data.formal_salutation;
}else{
} else {
profile_data.formal_salutation = Some(new_data.formal_salutation.clone());
}
if !check_for_permission("modules.edit.profile.own.general.personnel_number", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.general.personnel_number",
&user_permissions,
) {
profile_data.personnel_number = old_data.personnel_number;
}else{
} else {
profile_data.personnel_number = Some(new_data.personnel_number.clone());
}
if !check_for_permission("modules.edit.profile.own.general.street", &user_permissions) {
profile_data.street = old_data.street;
}else{
} else {
profile_data.street = Some(new_data.street.clone());
}
if !check_for_permission("modules.edit.profile.own.general.street_number", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.general.street_number",
&user_permissions,
) {
profile_data.street_number = old_data.street_number;
}else{
} else {
profile_data.street_number = Some(new_data.street_number.clone());
}
if !check_for_permission("modules.edit.profile.own.general.postcode", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.general.postcode",
&user_permissions,
) {
profile_data.postcode = old_data.postcode;
}else{
} else {
profile_data.postcode = Some(new_data.postcode.clone());
}
if !check_for_permission("modules.edit.profile.own.general.place", &user_permissions) {
profile_data.place = old_data.place;
}else{
} else {
profile_data.place = Some(new_data.place.clone());
}
profile_data
}
}

247
src/database/profile_communication.rs

@ -1,87 +1,87 @@
//TODO: CHECK if UserCommunicationEmail belongs to userid!!!!!!!!!!!!!!
use std::collections::HashMap;
use crate::database::connection::connect;
use crate::database::profile::StringConvert;
use rocket::request::Form;
use crate::modules::permissions::{check_for_permission, UserPermissions};
use mysql::Pool;
use crate::modules::permissions::{UserPermissions, check_for_permission};
use rocket::request::Form;
use std::collections::HashMap;
#[derive(Debug, Clone, Copy)]
pub enum UserCommunicationVisibility{
pub enum UserCommunicationVisibility {
Private,
Limited,
Public
Public,
}
#[derive(FromForm)]
pub struct UserCommunicationFormEntry{
pub profile_communication_id : i32,
pub profile_communication_description : Option<String>,
pub profile_communication_type : String,
pub profile_communication_visibility : String,
pub profile_communication_value : String
pub struct UserCommunicationFormEntry {
pub profile_communication_id: i32,
pub profile_communication_description: Option<String>,
pub profile_communication_type: String,
pub profile_communication_visibility: String,
pub profile_communication_value: String,
}
pub struct UserCommunicationEmail{
pub id : i32,
pub email : String,
pub description : Option<String>,
pub visibility : UserCommunicationVisibility
pub struct UserCommunicationEmail {
pub id: i32,
pub email: String,
pub description: Option<String>,
pub visibility: UserCommunicationVisibility,
}
pub struct UserCommunicationPhoneNumber{
pub id : i32,
pub country_prefix : i16,
pub number : i64,
pub description : Option<String>,
pub visibility : UserCommunicationVisibility
pub struct UserCommunicationPhoneNumber {
pub id: i32,
pub country_prefix: i16,
pub number: i64,
pub description: Option<String>,
pub visibility: UserCommunicationVisibility,
}
pub struct UserCommunicationData{
pub emails : HashMap<i32, UserCommunicationEmail>,
pub phone_numbers : HashMap<i32, UserCommunicationPhoneNumber>
pub struct UserCommunicationData {
pub emails: HashMap<i32, UserCommunicationEmail>,
pub phone_numbers: HashMap<i32, UserCommunicationPhoneNumber>,
}
impl StringConvert<UserCommunicationVisibility> for UserCommunicationVisibility{
fn string_convert(&self) -> String{
match self{
UserCommunicationVisibility::Private => String::from("0"),
UserCommunicationVisibility::Limited => String::from("1"),
UserCommunicationVisibility::Public => String::from("2")
}
impl StringConvert<UserCommunicationVisibility> for UserCommunicationVisibility {
fn string_convert(&self) -> String {
match self {
UserCommunicationVisibility::Private => String::from("0"),
UserCommunicationVisibility::Limited => String::from("1"),
UserCommunicationVisibility::Public => String::from("2"),
}
}
}
pub fn visibility_generate_label(visibility : UserCommunicationVisibility) -> String{
match visibility{
pub fn visibility_generate_label(visibility: UserCommunicationVisibility) -> String {
match visibility {
UserCommunicationVisibility::Private => String::from("privat"),
UserCommunicationVisibility::Limited => String::from("bedingt sichtbar"),
UserCommunicationVisibility::Public => String::from("öffentlich")
UserCommunicationVisibility::Public => String::from("öffentlich"),
}
}
fn visibility_from_i8(visibility : i8) -> UserCommunicationVisibility{
match visibility{
fn visibility_from_i8(visibility: i8) -> UserCommunicationVisibility {
match visibility {
0 => UserCommunicationVisibility::Private,
1 => UserCommunicationVisibility::Limited,
2 => UserCommunicationVisibility::Public,
_ => UserCommunicationVisibility::Private
_ => UserCommunicationVisibility::Private,
}
}
fn visibility_to_i8(visibility : UserCommunicationVisibility) -> i8{
match visibility{
fn visibility_to_i8(visibility: UserCommunicationVisibility) -> i8 {
match visibility {
UserCommunicationVisibility::Private => 0,
UserCommunicationVisibility::Limited => 1,
UserCommunicationVisibility::Public => 2
UserCommunicationVisibility::Public => 2,
}
}
pub fn get_communication_data(userid : i32) -> UserCommunicationData{
let mut communication_data = UserCommunicationData{
pub fn get_communication_data(userid: i32) -> UserCommunicationData {
let mut communication_data = UserCommunicationData {
emails: HashMap::new(),
phone_numbers: HashMap::new()
phone_numbers: HashMap::new(),
};
let pool = connect();
@ -94,8 +94,8 @@ pub fn get_communication_data(userid : i32) -> UserCommunicationData{
communication_data
}
fn get_communication_data_emails(pool : &Pool, userid : i32) -> HashMap<i32, UserCommunicationEmail>{
let mut emails : HashMap<i32, UserCommunicationEmail> = HashMap::new();
fn get_communication_data_emails(pool: &Pool, userid: i32) -> HashMap<i32, UserCommunicationEmail> {
let mut emails: HashMap<i32, UserCommunicationEmail> = HashMap::new();
pool.prep_exec(r"SELECT id, email, description, visibility FROM communication_email_addresses WHERE f_users_id = :user_id", params!{"user_id" => userid}).map(|mut result|{
while let Some(row) = result.next() {
let mut row = row.unwrap().clone();
@ -113,8 +113,11 @@ fn get_communication_data_emails(pool : &Pool, userid : i32) -> HashMap<i32, Use
emails
}
fn get_communication_data_phone_numbers(pool : &Pool, userid : i32) -> HashMap<i32, UserCommunicationPhoneNumber>{
let mut numbers : HashMap<i32, UserCommunicationPhoneNumber> = HashMap::new();
fn get_communication_data_phone_numbers(
pool: &Pool,
userid: i32,
) -> HashMap<i32, UserCommunicationPhoneNumber> {
let mut numbers: HashMap<i32, UserCommunicationPhoneNumber> = HashMap::new();
pool.prep_exec(r"SELECT id, country_prefix, number, description, visibility FROM communication_phone_numbers WHERE f_users_id = :user_id", params!{"user_id" => userid}).map(|mut result|{
while let Some(row) = result.next() {
let mut row = row.unwrap().clone();
@ -133,21 +136,29 @@ fn get_communication_data_phone_numbers(pool : &Pool, userid : i32) -> HashMap<i
numbers
}
pub fn add_communication_data_email (user_id : i32, user_permissions : &UserPermissions, data : Form<UserCommunicationFormEntry>) {
if !check_for_permission("modules.add.profile.own.communication.email", user_permissions){
pub fn add_communication_data_email(
user_id: i32,
user_permissions: &UserPermissions,
data: Form<UserCommunicationFormEntry>,
) {
if !check_for_permission(
"modules.add.profile.own.communication.email",
user_permissions,
) {
return;
}
let pool = connect();
let visibility :i8 = data.profile_communication_visibility.parse().unwrap();
let visibility: i8 = data.profile_communication_visibility.parse().unwrap();
let mut stmt = pool.prepare(r"INSERT INTO communication_email_addresses (f_users_id, email, description, visibility) VALUES (:user_id, :email, :description, :visibility)").unwrap();
stmt.execute(params!{
stmt.execute(params! {
"user_id" => user_id,
"email" => data.profile_communication_value.clone(),
"description" => data.profile_communication_description.clone(),
"visibility" => visibility
}).unwrap();
})
.unwrap();
}
/*pub fn add_communication_data_phone_number (user_id : i32, user_permissions : &UserPermissions, data : Form<UserCommunicationFormEntry>){
@ -166,56 +177,61 @@ pub fn add_communication_data_email (user_id : i32, user_permissions : &UserPerm
}).unwrap();
}*/
pub enum FormTypes{
pub enum FormTypes {
Email(UserCommunicationEmail),
Phone(UserCommunicationPhoneNumber)
Phone(UserCommunicationPhoneNumber),
}
fn parse_phone_number_from_string(number : String) -> Option<((i16, i64))>{
fn parse_phone_number_from_string(number: String) -> Option<((i16, i64))> {
let mut parts: Vec<&str> = number.split(' ').collect();
if parts.len() > 0{
if parts.len() > 0 {
let country_code: i16 = parts[0].parse().unwrap();
parts.remove(0);
let number : String = parts.iter().map(|string| string.to_string()).collect();
let number: String = parts.iter().map(|string| string.to_string()).collect();
let number: i64 = number.parse().unwrap();
Some((country_code, number))
}else{
} else {
None
}
}
pub fn parse_communication_form_entry(data : Form<UserCommunicationFormEntry>) -> Option<FormTypes>{
let visibility :i8 = data.profile_communication_visibility.parse().unwrap();
pub fn parse_communication_form_entry(data: Form<UserCommunicationFormEntry>) -> Option<FormTypes> {
let visibility: i8 = data.profile_communication_visibility.parse().unwrap();
if data.profile_communication_type == "email"{
let data = UserCommunicationEmail{
if data.profile_communication_type == "email" {
let data = UserCommunicationEmail {
id: data.profile_communication_id,
email: data.profile_communication_value.clone(),
description: data.profile_communication_description.clone(),
visibility: visibility_from_i8(visibility)
visibility: visibility_from_i8(visibility),
};
Some(FormTypes::Email(data))
}else if data.profile_communication_type == "phone"{
let (country_prefix, number) = parse_phone_number_from_string(data.profile_communication_value.clone()).unwrap();
let data = UserCommunicationPhoneNumber{
} else if data.profile_communication_type == "phone" {
let (country_prefix, number) =
parse_phone_number_from_string(data.profile_communication_value.clone()).unwrap();
let data = UserCommunicationPhoneNumber {
id: data.profile_communication_id,
country_prefix,
description: data.profile_communication_description.clone(),
visibility: visibility_from_i8(visibility),
number
number,
};
Some(FormTypes::Phone(data))
}else{
} else {
None
}
}
pub fn update_communication_data_email(user_id : i32, user_permissions : &UserPermissions, data : UserCommunicationEmail) {
pub fn update_communication_data_email(
user_id: i32,
user_permissions: &UserPermissions,
data: UserCommunicationEmail,
) {
let pool = connect();
let old_data = get_communication_data_emails(&pool, user_id);
if !old_data.contains_key(&data.id){
if !old_data.contains_key(&data.id) {
debug!("Submitted wrong communication data id: {}", &data.id);
return;
}
@ -224,48 +240,66 @@ pub fn update_communication_data_email(user_id : i32, user_permissions : &UserPe
let data = check_communication_data_email_permissions(user_permissions, data, old_data);
let mut stmt = pool.prepare(r"UPDATE communication_email_addresses SET email = :email, description = :description, visibility = :visibility WHERE id = :id").unwrap();
stmt.execute(params!{
stmt.execute(params! {
"id" => data.id,
"email" => data.email,
"description" => data.description,
"visibility" => visibility_to_i8(data.visibility)
}).unwrap();
})
.unwrap();
}
fn check_communication_data_email_permissions(user_permissions : &UserPermissions, new_data: UserCommunicationEmail, old_data : &UserCommunicationEmail) -> UserCommunicationEmail {
let mut data : UserCommunicationEmail = UserCommunicationEmail{
fn check_communication_data_email_permissions(
user_permissions: &UserPermissions,
new_data: UserCommunicationEmail,
old_data: &UserCommunicationEmail,
) -> UserCommunicationEmail {
let mut data: UserCommunicationEmail = UserCommunicationEmail {
id: old_data.id,
email: "".to_string(),
description: None,
visibility: UserCommunicationVisibility::Private
visibility: UserCommunicationVisibility::Private,
};
if !check_for_permission("modules.edit.profile.own.communication.email.email", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.communication.email.email",
&user_permissions,
) {
data.email = old_data.email.clone();
}else{
} else {
data.email = new_data.email.clone();
}
if !check_for_permission("modules.edit.profile.own.communication.email.description", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.communication.email.description",
&user_permissions,
) {
data.description = old_data.description.clone();
}else{
} else {
data.description = new_data.description.clone();
}
if !check_for_permission("modules.edit.profile.own.communication.email.visibility", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.communication.email.visibility",
&user_permissions,
) {
data.visibility = old_data.visibility.clone();
}else{
} else {
data.visibility = new_data.visibility.clone();
}
new_data
}
pub fn update_communication_data_phone_number(user_id : i32, user_permissions : &UserPermissions, data : UserCommunicationPhoneNumber) {
pub fn update_communication_data_phone_number(
user_id: i32,
user_permissions: &UserPermissions,
data: UserCommunicationPhoneNumber,
) {
let pool = connect();
let old_data = get_communication_data_phone_numbers(&pool, user_id);
if !old_data.contains_key(&data.id){
if !old_data.contains_key(&data.id) {
debug!("Submitted wrong communication data id: {}", &data.id);
return;
}
@ -274,47 +308,64 @@ pub fn update_communication_data_phone_number(user_id : i32, user_permissions :
let data = check_communication_data_phone_permissions(user_permissions, data, old_data);
let mut stmt = pool.prepare(r"UPDATE communication_phone_numbers SET number = :number, country_prefix = :country_prefix, description = :description, visibility = :visibility WHERE id = :id").unwrap();
stmt.execute(params!{
stmt.execute(params! {
"id" => data.id,
"number" => data.number,
"country_prefix" => data.country_prefix,
"description" => data.description,
"visibility" => visibility_to_i8(data.visibility)
}).unwrap();
})
.unwrap();
}
fn check_communication_data_phone_permissions(user_permissions : &UserPermissions, new_data: UserCommunicationPhoneNumber, old_data : &UserCommunicationPhoneNumber) -> UserCommunicationPhoneNumber {
let mut data : UserCommunicationPhoneNumber = UserCommunicationPhoneNumber{
fn check_communication_data_phone_permissions(
user_permissions: &UserPermissions,
new_data: UserCommunicationPhoneNumber,
old_data: &UserCommunicationPhoneNumber,
) -> UserCommunicationPhoneNumber {
let mut data: UserCommunicationPhoneNumber = UserCommunicationPhoneNumber {
id: old_data.id,
country_prefix: 0,
description: None,
visibility: UserCommunicationVisibility::Private,
number: 0
number: 0,
};
if !check_for_permission("modules.edit.profile.own.communication.phone_number.number", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.communication.phone_number.number",
&user_permissions,
) {
data.number = old_data.number;
}else{
} else {
data.number = new_data.number;
}
if !check_for_permission("modules.edit.profile.own.communication.phone_number.country_prefix", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.communication.phone_number.country_prefix",
&user_permissions,
) {
data.country_prefix = old_data.country_prefix;
}else{
} else {
data.country_prefix = new_data.country_prefix;
}
if !check_for_permission("modules.edit.profile.own.communication.phone_number.description", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.communication.phone_number.description",
&user_permissions,
) {
data.description = old_data.description.clone();
}else{
} else {
data.description = new_data.description.clone();
}
if !check_for_permission("modules.edit.profile.own.communication.phone_number.visibility", &user_permissions) {
if !check_for_permission(
"modules.edit.profile.own.communication.phone_number.visibility",
&user_permissions,
) {
data.visibility = old_data.visibility.clone();
}else{
} else {
data.visibility = new_data.visibility.clone();
}
new_data
}
}

10
src/lang/lang.rs

@ -1,9 +1,9 @@
use fluent::{FluentBundle, FluentValue, FluentResource, FluentArgs};
use fluent::{FluentArgs, FluentBundle, FluentResource, FluentValue};
pub fn get(id : String, args : Vec<String>) -> String{
pub fn get(id: String, args: Vec<String>) -> String {
String::from(id)
}
pub fn get_simple(id : String) -> String{
get(id, vec!())
}
pub fn get_simple(id: String) -> String {
get(id, vec![])
}

24
src/lang/parse.rs

@ -18,30 +18,30 @@ pub fn parse_langid(input: String) -> Option<LanguageIdentifier> {
pub fn parse_or_fallback(input: String) -> Option<LanguageIdentifier> {
match parse_langid(input) {
Some(langid) => Some(langid),
None => {
return parse_fallback()
}
None => return parse_fallback(),
}
}
pub fn parse_fallback() -> Option<LanguageIdentifier>{
pub fn parse_fallback() -> Option<LanguageIdentifier> {
let langid: LanguageIdentifier = match SETTINGS
.read()
.unwrap()
.get::<String>("fallback_language")
{
Ok(fallback_language) => match parse_langid(fallback_language) {
{
Ok(fallback_language) => {
match parse_langid(fallback_language) {
Some(langid) => langid,
None => {
error!("Couldn't even parse fallback language! You should fix your fallback language");
return None;
}
},
Err(e) => {
error!("Couldn't read fallback language from config file! You should add a fallback language. {}", e);
return None;
}
};
}
Err(e) => {
error!("Couldn't read fallback language from config file! You should add a fallback language. {}", e);
return None;
}
};
return Some(langid)
return Some(langid);
}

51
src/lang/setup.rs

@ -1,56 +1,67 @@
use fluent::{FluentBundle, FluentValue, FluentResource, FluentArgs};
use unic_langid::LanguageIdentifier;
use crate::lang::LanguageManager;
use std::collections::HashMap;
use fluent::FluentError;
use fluent::{FluentArgs, FluentBundle, FluentResource, FluentValue};
use std::collections::HashMap;
use std::fs::{self, DirEntry};
use unic_langid::LanguageIdentifier;
/// Imports all language files from lang/
pub fn load_languages(){
for file in fs::read_dir(format!("lang/")).expect("Missing lang directory!"){
let file = match file{
pub fn load_languages() {
for file in fs::read_dir(format!("lang/")).expect("Missing lang directory!") {
let file = match file {
Ok(file) => file,
Err(e) => {
error!("Couldn't read language file: {}", e);
break;
}
};
let langid : LanguageIdentifier = match file.file_name().to_str().unwrap().parse(){
let langid: LanguageIdentifier = match file.file_name().to_str().unwrap().parse() {
Ok(langid) => langid,
Err(e) => {
error!("Couldn't parse language id: {} {}", file.file_name().to_str().unwrap(), e);
error!(
"Couldn't parse language id: {} {}",
file.file_name().to_str().unwrap(),
e
);
break;
}
};
let bundle = match create_bundle(fs::read_to_string(file.path()).unwrap(), langid.clone()){
let bundle = match create_bundle(fs::read_to_string(file.path()).unwrap(), langid.clone()) {
Some(bundle) => bundle,
None => break
None => break,
};
super::LM.write().unwrap().add_bundle(langid, bundle);
}
}
/// Creates bundle from string + langid
pub fn create_bundle(input : String, langid : LanguageIdentifier) -> Option<FluentBundle<FluentResource>>{
let (resource, errors) = match FluentResource::try_new(input){
Ok(resource) => (resource, vec!()),
Err((resource, errors)) => (resource, errors)
pub fn create_bundle(
input: String,
langid: LanguageIdentifier,
) -> Option<FluentBundle<FluentResource>> {
let (resource, errors) = match FluentResource::try_new(input) {
Ok(resource) => (resource, vec![]),
Err((resource, errors)) => (resource, errors),
};
for error in errors{
warn!("ParserError for langid {} at {}:{}", langid, error.pos.0, error.pos.1);
for error in errors {
warn!(
"ParserError for langid {} at {}:{}",
langid, error.pos.0, error.pos.1
);
}
let mut bundle = FluentBundle::new(&[langid.clone()]);
match bundle.add_resource(resource){
match bundle.add_resource(resource) {
Ok(bundle) => bundle,
Err(errors) => {
for error in errors{
for error in errors {
error!("ParserError for langid {}: {}", langid, error);
}
return None},
return None;
}
}
return Some(bundle);
}
}

77
src/main.rs

@ -1,67 +1,87 @@
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate mysql;
#[macro_use] extern crate rocket;
#[macro_use]
extern crate rocket;
use std::sync::RwLock;
use crate::lang::setup::load_languages;
use config::Config;
use rocket::http::Status;
use rocket::Request;
use rocket::response::{content, Redirect};
use rocket::Request;
use rocket_contrib::serve::StaticFiles;
use crate::lang::setup::load_languages;
pub mod database;
pub mod lang;
pub mod modules;
pub mod sitebuilder;
pub mod lang;
lazy_static! {
static ref SETTINGS: RwLock<Config> = RwLock::new(Config::default());
static ref SETTINGS: RwLock<Config> = RwLock::new(Config::default());
}
#[get("/?<error>")]
pub fn site_main(error: Option<String>) -> Result<content::Html<String>, Status>{
let mut error = match error{
pub fn site_main(error: Option<String>) -> Result<content::Html<String>, Status> {
let mut error = match error {
Some(error) => error,
None => String::from("")
None => String::from(""),
};
if error == "failed_login" {
error = "<div class=\"alert alert-danger\" role=\"alert\">E-mail Adresse oder Passwort falsch!</div>".to_string();
}else if error == "failed_authorization" {
} else if error == "failed_authorization" {
error = "<div class=\"alert alert-danger\" role=\"alert\">Autorisation abgelaufen! Bitte neu anmelden,</div>".to_string();
}else{
} else {
error = "".to_string();
}
let content = sitebuilder::builder::build("static/html/templates/index.html", vec!(("error".to_string(), error))).unwrap();
let footer = sitebuilder::builder::build("static/html/templates/footer.html", vec!()).unwrap();
Ok(content::Html::from(content::Html(format!("{}{}", content, footer))))
let content = sitebuilder::builder::build(
"static/html/templates/index.html",
vec![("error".to_string(), error)],
)
.unwrap();
let footer = sitebuilder::builder::build("static/html/templates/footer.html", vec![]).unwrap();
Ok(content::Html::from(content::Html(format!(
"{}{}",
content, footer
))))
}
#[catch(404)]
fn not_found(req: &Request) -> Result<content::Html<String>, Redirect> {
let mut path_parts = req.uri().path().split("/");
if path_parts.nth(1).unwrap() == "portal"{
if modules::login::check_login(req.cookies()).is_some(){
Ok(content::Html("Couldn't found resource. <a href=\"/portal\">You can return to the portal.</a>".to_string()))
}else{
if path_parts.nth(1).unwrap() == "portal" {
if modules::login::check_login(req.cookies()).is_some() {
Ok(content::Html(
"Couldn't found resource. <a href=\"/portal\">You can return to the portal.</a>"
.to_string(),
))
} else {
Err(Redirect::to("/?error=failed_authorization"))
}
}else{
Ok(content::Html("Couldn't found resource. <a href=\"/\">You can return to the login page.</a>".to_string()))
} else {
Ok(content::Html(
"Couldn't found resource. <a href=\"/\">You can return to the login page.</a>"
.to_string(),
))
}
}
fn main() {
env_logger::init(); //Initialize logger
SETTINGS.write().unwrap().merge(config::File::with_name("erms-config")).unwrap(); //Load erms-config.toml
SETTINGS
.write()
.unwrap()
.merge(config::File::with_name("erms-config"))
.unwrap(); //Load erms-config.toml
info!("Starting erms version {}.", env!("CARGO_PKG_VERSION"));
info!("Loading language files.");
@ -72,7 +92,18 @@ fn main() {
sitebuilder::builder::load_static_files();
rocket::ignite()
.mount("/", routes![site_main, modules::login::login_get, modules::login::login_post, modules::portal::portal_get, modules::profile::profile_get, modules::profile::profile_post, modules::profile::profile_communication_post])
.mount(
"/",
routes![
site_main,
modules::login::login_get,
modules::login::login_post,
modules::portal::portal_get,
modules::profile::profile_get,
modules::profile::profile_post,
modules::profile::profile_communication_post
],
)
.mount("/style/", StaticFiles::from("static/css")) //TODO: Switch to own FileCache
.mount("/script/", StaticFiles::from("static/js"))
.mount("/img/", StaticFiles::from("static/img"))

114
src/modules/login.rs

@ -15,27 +15,27 @@ pub struct LoginForm {
}
#[get("/login")]
pub fn login_get() -> Redirect{
pub fn login_get() -> Redirect {
Redirect::to("/")
}
#[post("/login", data = "<login_form>")]
pub fn login_post(mut cookies: Cookies, login_form : Form<LoginForm>) -> Redirect{
let hash = match database::login::get_user_hash(login_form.login_email.clone()){
pub fn login_post(mut cookies: Cookies, login_form: Form<LoginForm>) -> Redirect {
let hash = match database::login::get_user_hash(login_form.login_email.clone()) {
Some(hash) => hash,
None => return Redirect::to("/?error=failed_login")
None => return Redirect::to("/?error=failed_login"),
};
let matches = argon2::verify_encoded(&hash , login_form.login_password.as_bytes()).unwrap();
if matches{
let matches = argon2::verify_encoded(&hash, login_form.login_password.as_bytes()).unwrap();
if matches {
login(&mut cookies, login_form.login_email.clone());