extern crate time;
use self::time::{Duration, Timespec};
#[derive(Clone, Debug)]
pub struct SessionUser {
pub id: i32,
pub session_token: Option<String>, pub csrf_token: String,
pub last_login: Option<Timespec>,
pub last_activity: Option<Timespec>,
pub account_created: Option<Timespec>,
pub username: Option<String>,
pub password: Option<String>,
pub salt: Option<String>,
pub logincode: Option<String>,
pub email: Option<String>,
pub email_unconfirmed: Option<String>,
pub email_confirmationcode: Option<String>,
pub firstname: Option<String>,
pub lastname: Option<String>,
pub street: Option<String>,
pub zip: Option<String>,
pub city: Option<String>,
pub nation: Option<String>,
pub grade: i32,
pub sex: Option<i32>,
pub anonymous: bool,
pub is_admin: Option<bool>,
pub is_teacher: bool,
pub managed_by: Option<i32>,
pub school_name: Option<String>,
pub oauth_foreign_id: Option<String>,
pub oauth_provider: Option<String>,
}
pub enum Sex {
#[allow(dead_code)]
NotStated = 0,
Male = 1,
Female = 2,
Diverse = 3,
#[allow(dead_code)]
Other = 4,
}
#[derive(Clone, Default)]
pub struct UserInfo {
pub id: i32,
pub username: Option<String>,
pub logincode: Option<String>,
pub firstname: Option<String>,
pub lastname: Option<String>,
pub grade: i32,
pub annotation: Option<String>,
}
#[derive(Clone, Debug)]
pub struct Group {
pub id: Option<i32>,
pub name: String,
pub groupcode: String,
pub tag: String,
pub admins: Vec<i32>,
pub members: Vec<SessionUser>,
}
#[derive(Debug)]
pub struct Contest {
pub id: Option<i32>,
pub location: String,
pub filename: String,
pub name: String,
pub duration: i32,
pub public: bool,
pub start: Option<Timespec>,
pub end: Option<Timespec>,
pub review_start: Option<Timespec>,
pub review_end: Option<Timespec>,
pub min_grade: Option<i32>,
pub max_grade: Option<i32>,
pub max_teamsize: Option<i32>,
pub positionalnumber: Option<i32>,
pub requires_login: Option<bool>,
pub requires_contest: Option<String>,
pub protected: bool,
pub secret: Option<String>,
pub message: Option<String>,
pub image: Option<String>,
pub language: Option<String>,
pub category: Option<String>,
pub standalone_task: Option<bool>,
pub tags: Vec<String>,
pub taskgroups: Vec<Taskgroup>,
}
#[derive(Debug)]
pub struct Taskgroup {
pub id: Option<i32>,
pub contest: i32,
pub name: String,
pub active: bool,
pub positionalnumber: Option<i32>,
pub tasks: Vec<Task>,
}
#[derive(Debug)]
pub struct Task {
pub id: Option<i32>,
pub taskgroup: i32,
pub location: String,
pub language: Option<String>,
pub stars: i32,
}
pub struct Submission {
pub id: Option<i32>,
pub user: i32,
pub task: i32,
pub grade: i32,
pub validated: bool,
pub nonvalidated_grade: i32,
pub needs_validation: bool,
pub subtask_identifier: Option<String>,
pub value: String,
pub date: Timespec,
}
#[derive(Clone, Copy, Default, Debug)]
pub struct Grade {
pub taskgroup: i32,
pub user: i32,
pub grade: Option<i32>,
pub validated: bool,
}
pub struct Participation {
pub contest: i32,
pub user: i32,
pub start: Timespec,
pub team: Option<i32>,
}
pub trait HasId {
fn get_id(&self) -> Option<i32>;
fn set_id(&mut self, id: i32);
}
impl HasId for Submission {
fn get_id(&self) -> Option<i32> { self.id }
fn set_id(&mut self, id: i32) { self.id = Some(id); }
}
impl HasId for Task {
fn get_id(&self) -> Option<i32> { self.id }
fn set_id(&mut self, id: i32) { self.id = Some(id); }
}
impl HasId for Taskgroup {
fn get_id(&self) -> Option<i32> { self.id }
fn set_id(&mut self, id: i32) { self.id = Some(id); }
}
impl HasId for Contest {
fn get_id(&self) -> Option<i32> { self.id }
fn set_id(&mut self, id: i32) { self.id = Some(id); }
}
impl HasId for Group {
fn get_id(&self) -> Option<i32> { self.id }
fn set_id(&mut self, id: i32) { self.id = Some(id); }
}
impl SessionUser {
pub fn minimal(id: i32, session_token: String, csrf_token: String) -> Self {
SessionUser { id,
session_token: Some(session_token),
csrf_token,
last_login: None,
last_activity: None,
account_created: Some(time::get_time()),
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,
anonymous: false,
is_admin: Some(false),
is_teacher: false,
managed_by: None,
school_name: None,
oauth_foreign_id: None,
oauth_provider: None }
}
pub fn group_user_stub() -> Self {
SessionUser { id: 0,
session_token: None,
csrf_token: "".to_string(),
last_login: None,
last_activity: None,
account_created: Some(time::get_time()),
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,
anonymous: false,
is_admin: None,
is_teacher: false,
managed_by: None,
school_name: None,
oauth_foreign_id: None,
oauth_provider: None }
}
pub fn is_alive(&self) -> bool {
let duration = 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 is_teacher(&self) -> bool { self.is_teacher }
pub fn is_admin(&self) -> bool { self.is_admin == Some(true) }
pub fn ensure_alive(self) -> Option<Self> {
if self.is_alive() {
Some(self)
} else {
None
}
}
pub fn ensure_logged_in(self) -> Option<Self> {
if self.is_logged_in() {
Some(self)
} else {
None
}
}
pub fn ensure_teacher(self) -> Option<Self> {
if self.is_logged_in() && self.is_teacher() {
Some(self)
} else {
None
}
}
pub fn ensure_admin(self) -> Option<Self> {
if self.is_logged_in() && self.is_admin() {
Some(self)
} else {
None
}
}
pub fn ensure_teacher_or_admin(self) -> Option<Self> {
if self.is_logged_in() && (self.is_admin() || self.is_teacher()) {
Some(self)
} else {
None
}
}
}
impl Taskgroup {
pub fn new(name: String, positionalnumber: Option<i32>) -> Self {
Taskgroup { id: None, contest: 0, name, active: true, positionalnumber, tasks: Vec::new() }
}
}
impl Task {
pub fn new(location: String, language: Option<String>, stars: i32) -> Self {
Task { id: None, taskgroup: 0, location, language, stars }
}
}
pub trait OptionSession {
fn ensure_alive(self) -> Self;
fn ensure_logged_in(self) -> Self;
#[allow(dead_code)]
fn ensure_teacher(self) -> Self;
#[allow(dead_code)]
fn ensure_admin(self) -> Self;
}
impl OptionSession for Option<SessionUser> {
fn ensure_alive(self) -> Self { self?.ensure_alive() }
fn ensure_logged_in(self) -> Self { self?.ensure_logged_in() }
fn ensure_teacher(self) -> Self { self?.ensure_teacher() }
fn ensure_admin(self) -> Self { self?.ensure_admin() }
}