extern crate time; use self::time::{Duration, Timespec}; #[derive(Clone)] pub struct SessionUser { pub id: i32, pub session_token: Option, // delete this to log out pub csrf_token: String, pub last_login: Option, pub last_activity: Option, pub permanent_login: bool, pub username: Option, pub password: Option, pub salt: Option, pub logincode: Option, pub email: Option, pub email_unconfirmed: Option, pub email_confirmationcode: Option, pub firstname: Option, pub lastname: Option, pub street: Option, pub zip: Option, pub city: Option, pub nation: Option, pub grade: i32, pub sex: Option, pub is_teacher: bool, pub managed_by: Option, pub oauth_foreign_id: Option, pub oauth_provider: Option, // pub oauth_extra_data: Option, // pub pms_id: Option, // pub pms_school_id: Option, } // Short version for display #[derive(Clone, Default)] pub struct UserInfo { pub id: i32, pub username: Option, pub logincode: Option, pub firstname: Option, pub lastname: Option, pub grade: i32, } #[derive(Clone)] pub struct Group { pub id: Option, pub name: String, pub groupcode: String, pub tag: String, pub admin: i32, pub members: Vec, } #[derive(Debug)] pub struct Contest { pub id: Option, pub location: String, pub filename: String, pub name: String, pub duration: i32, pub public: bool, pub start: Option, pub end: Option, pub min_grade: Option, pub max_grade: Option, pub positionalnumber: Option, pub requires_login: Option, pub secret: Option, pub taskgroups: Vec, } #[derive(Debug)] pub struct Taskgroup { pub id: Option, pub contest: i32, pub name: String, pub active: bool, pub positionalnumber: Option, pub tasks: Vec, } #[derive(Debug)] pub struct Task { pub id: Option, pub taskgroup: i32, pub location: String, pub stars: i32, } pub struct Submission { pub id: Option, pub session_user: i32, pub task: i32, pub grade: i32, pub validated: bool, pub nonvalidated_grade: i32, pub needs_validation: bool, pub subtask_identifier: Option, pub value: String, pub date: Timespec, } #[derive(Clone, Copy, Default, Debug)] pub struct Grade { pub taskgroup: i32, pub user: i32, pub grade: Option, pub validated: bool, } pub struct Participation { pub contest: i32, pub user: i32, pub start: Timespec, } pub trait HasId { fn get_id(&self) -> Option; fn set_id(&mut self, id: i32); } impl HasId for Submission { fn get_id(&self) -> Option { self.id } fn set_id(&mut self, id: i32) { self.id = Some(id); } } impl HasId for Task { fn get_id(&self) -> Option { self.id } fn set_id(&mut self, id: i32) { self.id = Some(id); } } impl HasId for Taskgroup { fn get_id(&self) -> Option { self.id } fn set_id(&mut self, id: i32) { self.id = Some(id); } } impl HasId for Contest { fn get_id(&self) -> Option { self.id } fn set_id(&mut self, id: i32) { self.id = Some(id); } } impl HasId for Group { fn get_id(&self) -> Option { self.id } fn set_id(&mut self, id: i32) { self.id = Some(id); } } impl Contest { // TODO: Rewrite, so this attribute can be removed #[allow(clippy::too_many_arguments)] pub fn new(location: String, filename: String, name: String, duration: i32, public: bool, start: Option, end: Option, min_grade: Option, max_grade: Option, positionalnumber: Option, requires_login: Option, secret: Option) -> Self { Contest { id: None, location: location, filename: filename, name: name, duration: duration, public: public, start: start, end: end, min_grade: min_grade, max_grade: max_grade, positionalnumber: positionalnumber, requires_login: requires_login, secret: secret, taskgroups: Vec::new() } } } impl SessionUser { pub fn minimal(id: i32, session_token: String, csrf_token: String) -> Self { SessionUser { id: id, session_token: Some(session_token), csrf_token: csrf_token, last_login: None, last_activity: None, // now? // müssen die überhaupt außerhalb der datenbankabstraktion sichtbar sein? permanent_login: false, username: None, password: None, salt: None, logincode: None, email: None, email_unconfirmed: None, email_confirmationcode: None, firstname: None, lastname: None, street: None, zip: None, city: None, nation: None, grade: 0, sex: None, is_teacher: false, managed_by: None, oauth_foreign_id: None, oauth_provider: None, // oauth_extra_data: Option, //pms_id: None, //pms_school_id: None, } } pub fn group_user_stub() -> Self { SessionUser { id: 0, session_token: None, csrf_token: "".to_string(), last_login: None, last_activity: None, permanent_login: false, username: None, password: None, salt: None, logincode: None, email: None, email_unconfirmed: None, email_confirmationcode: None, firstname: None, lastname: None, street: None, zip: None, city: None, nation: None, grade: 0, sex: None, is_teacher: false, managed_by: None, oauth_foreign_id: None, oauth_provider: None } } pub fn is_alive(&self) -> bool { let duration = if self.permanent_login { Duration::days(90) } else { Duration::hours(9) }; let now = time::get_time(); if let Some(last_activity) = self.last_activity { now - last_activity < duration } else { false } } pub fn is_logged_in(&self) -> bool { (self.password.is_some() || self.logincode.is_some() || self.oauth_foreign_id.is_some()) && self.is_alive() } pub fn ensure_alive(self) -> Option { if self.is_alive() { Some(self) } else { None } } pub fn ensure_logged_in(self) -> Option { if self.is_logged_in() { Some(self) } else { None } } } impl Taskgroup { pub fn new(name: String, positionalnumber: Option) -> Self { Taskgroup { id: None, contest: 0, name: name, active: true, positionalnumber: positionalnumber, tasks: Vec::new() } } } impl Task { pub fn new(location: String, stars: i32) -> Self { Task { id: None, taskgroup: 0, location: location, stars: stars } } } pub trait OptionSession { fn ensure_alive(self) -> Self; fn ensure_logged_in(self) -> Self; } impl OptionSession for Option { fn ensure_alive(self) -> Self { self?.ensure_alive() } fn ensure_logged_in(self) -> Self { self?.ensure_logged_in() } }