Commit a7ae9cd4 authored by Robert Czechowski's avatar Robert Czechowski
Browse files

Add config switch to enable password login

parent 02741ce1
Pipeline #801 passed with stages
in 24 minutes and 8 seconds
......@@ -31,6 +31,7 @@ pub struct Config {
pub open_browser: Option<bool>,
pub cookie_signing_secret: Option<String>,
pub disable_results_page: Option<bool>,
pub enable_password_login: Option<bool>,
pub server_message: Option<String>,
pub teacher_page: Option<String>,
}
......@@ -74,6 +75,10 @@ pub struct Opt {
#[structopt(long = "disable-results-page")]
pub disableresultspage: bool,
/// Automatically open medal in the default browser
#[structopt(short = "P", long = "passwordlogin")]
pub enablepasswordlogin: bool,
/// Teacher page in task directory
#[structopt(short = "t", long = "teacherpage")]
pub teacherpage: Option<String>,
......@@ -118,6 +123,9 @@ pub fn read_config_from_file(file: &Path) -> Config {
if config.open_browser.is_none() {
config.open_browser = Some(false)
}
if config.enable_password_login.is_none() {
config.enable_password_login = Some(false)
}
println!("OAuth providers will be told to redirect to {}", config.self_url.as_ref().unwrap());
......
......@@ -55,6 +55,12 @@ pub enum MedalError {
UnmatchedPasswords,
}
pub struct LoginInfo {
pub password_login: bool,
pub self_url: Option<String>,
pub oauth_providers: Option<Vec<OauthProvider>>,
}
type MedalValue = (String, json_val::Map<String, json_val::Value>);
type MedalResult<T> = Result<T, MedalError>;
type MedalValueResult = MedalResult<MedalValue>;
......@@ -76,11 +82,9 @@ fn fill_user_data(session: &SessionUser, data: &mut json_val::Map<String, serde_
data.insert("medal_version".to_string(), to_json(&env!("CARGO_PKG_VERSION")));
}
fn fill_oauth_data((self_url, oauth_providers): (Option<String>, Option<Vec<OauthProvider>>),
data: &mut json_val::Map<String, serde_json::Value>)
{
fn fill_oauth_data(login_info: LoginInfo, data: &mut json_val::Map<String, serde_json::Value>) {
let mut oauth_links: Vec<(String, String, String)> = Vec::new();
if let Some(oauth_providers) = oauth_providers {
if let Some(oauth_providers) = login_info.oauth_providers {
for oauth_provider in oauth_providers {
oauth_links.push((oauth_provider.provider_id.to_owned(),
oauth_provider.login_link_text.to_owned(),
......@@ -88,8 +92,10 @@ fn fill_oauth_data((self_url, oauth_providers): (Option<String>, Option<Vec<Oaut
}
}
data.insert("self_url".to_string(), to_json(&self_url));
data.insert("self_url".to_string(), to_json(&login_info.self_url));
data.insert("oauth_links".to_string(), to_json(&oauth_links));
data.insert("password_login".to_string(), to_json(&login_info.password_login));
}
fn grade_to_string(grade: i32) -> String {
......@@ -107,26 +113,38 @@ fn grade_to_string(grade: i32) -> String {
}
}
pub fn index<T: MedalConnection>(conn: &T, session_token: Option<String>,
oauth_infos: (Option<String>, Option<Vec<OauthProvider>>))
-> (String, json_val::Map<String, json_val::Value>)
{
pub fn index<T: MedalConnection>(conn: &T, session_token: Option<String>, login_info: LoginInfo)
-> (String, json_val::Map<String, json_val::Value>) {
let mut data = json_val::Map::new();
//let mut contests = Vec::new();
if let Some(token) = session_token {
if let Some(session) = conn.get_session(&token) {
fill_user_data(&session, &mut data);
}
}
fill_oauth_data(oauth_infos, &mut data);
fill_oauth_data(login_info, &mut data);
data.insert("parent".to_string(), to_json(&"base"));
("index".to_owned(), data)
}
pub fn show_login<T: MedalConnection>(conn: &T, session_token: Option<String>, login_info: LoginInfo)
-> (String, json_val::Map<String, json_val::Value>) {
let mut data = json_val::Map::new();
if let Some(token) = session_token {
if let Some(session) = conn.get_session(&token) {
fill_user_data(&session, &mut data);
}
}
fill_oauth_data(login_info, &mut data);
data.insert("parent".to_string(), to_json(&"base"));
("login".to_owned(), data)
}
pub fn status<T: MedalConnection>(conn: &T, _: ()) -> String { conn.get_debug_information() }
pub fn debug<T: MedalConnection>(conn: &T, session_token: Option<String>)
......@@ -179,8 +197,7 @@ pub enum ContestVisibility {
LoginRequired,
}
pub fn show_contests<T: MedalConnection>(conn: &T, session_token: &str,
oauth_infos: (Option<String>, Option<Vec<OauthProvider>>),
pub fn show_contests<T: MedalConnection>(conn: &T, session_token: &str, login_info: LoginInfo,
visibility: ContestVisibility)
-> MedalValue
{
......@@ -193,7 +210,7 @@ pub fn show_contests<T: MedalConnection>(conn: &T, session_token: &str,
data.insert("can_start".to_string(), to_json(&true));
}
fill_oauth_data(oauth_infos, &mut data);
fill_oauth_data(login_info, &mut data);
let now = time::get_time();
let v: Vec<ContestInfo> =
......@@ -279,8 +296,7 @@ fn check_contest_constraints(session: &SessionUser, contest: &Contest) -> Contes
}
pub fn show_contest<T: MedalConnection>(conn: &T, contest_id: i32, session_token: &str,
query_string: Option<String>,
oauth_infos: (Option<String>, Option<Vec<OauthProvider>>))
query_string: Option<String>, login_info: LoginInfo)
-> MedalValueResult
{
let session = conn.get_session_or_new(&session_token);
......@@ -300,7 +316,7 @@ pub fn show_contest<T: MedalConnection>(conn: &T, contest_id: i32, session_token
data.insert("empty".to_string(), to_json(&"empty"));
data.insert("contest".to_string(), to_json(&ci));
data.insert("message".to_string(), to_json(&contest.message));
fill_oauth_data(oauth_infos, &mut data);
fill_oauth_data(login_info, &mut data);
let constraints = check_contest_constraints(&session, &contest);
......@@ -492,10 +508,8 @@ pub fn start_contest<T: MedalConnection>(conn: &T, contest_id: i32, session_toke
}
}
pub fn login<T: MedalConnection>(conn: &T, login_data: (String, String),
oauth_infos: (Option<String>, Option<Vec<OauthProvider>>))
-> Result<String, MedalValue>
{
pub fn login<T: MedalConnection>(conn: &T, login_data: (String, String), login_info: LoginInfo)
-> Result<String, MedalValue> {
let (username, password) = login_data;
match conn.login(None, &username, &password) {
......@@ -506,7 +520,7 @@ pub fn login<T: MedalConnection>(conn: &T, login_data: (String, String),
data.insert("username".to_string(), to_json(&username));
data.insert("parent".to_string(), to_json(&"base"));
fill_oauth_data(oauth_infos, &mut data);
fill_oauth_data(login_info, &mut data);
Err(("login".to_owned(), data))
}
......@@ -514,7 +528,7 @@ pub fn login<T: MedalConnection>(conn: &T, login_data: (String, String),
}
pub fn login_with_code<T: MedalConnection>(
conn: &T, code: &str, oauth_infos: (Option<String>, Option<Vec<OauthProvider>>))
conn: &T, code: &str, login_info: LoginInfo)
-> Result<Result<String, String>, (String, json_val::Map<String, json_val::Value>)> {
match conn.login_with_code(None, &code) {
Ok(session_token) => Ok(Ok(session_token)),
......@@ -526,7 +540,7 @@ pub fn login_with_code<T: MedalConnection>(
data.insert("code".to_string(), to_json(&code));
data.insert("parent".to_string(), to_json(&"base"));
fill_oauth_data(oauth_infos, &mut data);
fill_oauth_data(login_info, &mut data);
Err(("login".to_owned(), data))
}
......
......@@ -218,6 +218,7 @@ fn main() {
config.no_contest_scan = if opt.nocontestscan { Some(true) } else { config.no_contest_scan };
config.open_browser = if opt.openbrowser { Some(true) } else { config.open_browser };
config.disable_results_page = if opt.disableresultspage { Some(true) } else { config.disable_results_page };
config.enable_password_login = if opt.enablepasswordlogin { Some(true) } else { config.enable_password_login };
// Use default database file if none set
config.database_file.get_or_insert(Path::new("medal.db").to_owned());
......
......@@ -291,15 +291,19 @@ impl<'c, 'a: 'c, 'b: 'c + 'a, T> RequestAugmentMedalError<'c, 'a, 'b, T> for Res
}
}
fn login_info(config: &Config) -> core::LoginInfo {
core::LoginInfo { password_login: config.enable_password_login == Some(true),
self_url: config.self_url.clone(),
oauth_providers: config.oauth_providers.clone() }
}
fn greet_personal<C>(req: &mut Request) -> IronResult<Response>
where C: MedalConnection + std::marker::Send + 'static {
let session_token = req.get_session_token();
// hier ggf. Daten aus dem Request holen
let config = req.get::<Read<SharedConfiguration>>().unwrap();
let oauth_infos = (config.self_url.clone(), config.oauth_providers.clone());
let (template, mut data) = with_conn![core::index, C, req, session_token, oauth_infos];
let (template, mut data) = with_conn![core::index, C, req, session_token, login_info(&config)];
/*if let Some(server_message) = &config.server_message {
data.insert("server_message".to_string(), to_json(&server_message));
......@@ -382,10 +386,7 @@ fn contests<C>(req: &mut Request) -> IronResult<Response>
};
let config = req.get::<Read<SharedConfiguration>>().unwrap();
let (self_url, oauth_providers) = (config.self_url.clone(), config.oauth_providers.clone());
let (template, mut data) =
with_conn![core::show_contests, C, req, &session_token, (self_url, oauth_providers), visibility];
let (template, mut data) = with_conn![core::show_contests, C, req, &session_token, login_info(&config), visibility];
config.server_message.as_ref().map(|sm| data.insert("server_message".to_string(), to_json(&sm)));
......@@ -405,10 +406,8 @@ fn contest<C>(req: &mut Request) -> IronResult<Response>
let query_string = req.url.query().map(|s| s.to_string());
let config = req.get::<Read<SharedConfiguration>>().unwrap();
let oauth_infos = (config.self_url.clone(), config.oauth_providers.clone());
let (template, data) =
with_conn![core::show_contest, C, req, contest_id, &session_token, query_string, oauth_infos].aug(req)?;
with_conn![core::show_contest, C, req, contest_id, &session_token, query_string, login_info(&config)].aug(req)?;
let mut resp = Response::new();
resp.set_mut(Template::new(&template, data)).set_mut(status::Ok);
......@@ -488,31 +487,19 @@ fn contest_post<C>(req: &mut Request) -> IronResult<Response>
fn login<C>(req: &mut Request) -> IronResult<Response>
where C: MedalConnection + std::marker::Send + 'static {
let config = req.get::<Read<SharedConfiguration>>().unwrap();
let (self_url, oauth_providers) = (config.self_url.clone(), config.oauth_providers.clone());
let session_token = req.get_session_token();
let mut data = json_val::Map::new();
let config = req.get::<Read<SharedConfiguration>>().unwrap();
let (template, mut data) = with_conn![core::show_login, C, req, session_token, login_info(&config)];
let query_string = req.url.query().map(|s| s.to_string());
if let Some(query) = query_string {
data.insert("forward".to_string(), to_json(&query));
}
let mut oauth_links: Vec<(String, String, String)> = Vec::new();
if let Some(oauth_providers) = oauth_providers {
for oauth_provider in oauth_providers {
oauth_links.push((oauth_provider.provider_id.to_owned(),
oauth_provider.login_link_text.to_owned(),
oauth_provider.url.to_owned()));
}
}
data.insert("self_url".to_string(), to_json(&self_url));
data.insert("oauth_links".to_string(), to_json(&oauth_links));
data.insert("parent".to_string(), to_json(&"base"));
// Antwort erstellen und zurücksenden
let mut resp = Response::new();
resp.set_mut(Template::new("login", data)).set_mut(status::Ok);
resp.set_mut(Template::new(&template, data)).set_mut(status::Ok);
Ok(resp)
}
......@@ -524,11 +511,8 @@ fn login_post<C>(req: &mut Request) -> IronResult<Response>
};
let config = req.get::<Read<SharedConfiguration>>().unwrap();
let (self_url, oauth_providers) = (config.self_url.clone(), config.oauth_providers.clone());
// TODO: Submit current session to login
let loginresult = with_conn![core::login, C, req, logindata, (self_url, oauth_providers)];
let loginresult = with_conn![core::login, C, req, logindata, login_info(&config)];
match loginresult {
// Login successful
......@@ -553,11 +537,8 @@ fn login_code_post<C>(req: &mut Request) -> IronResult<Response>
};
let config = req.get::<Read<SharedConfiguration>>().unwrap();
let (self_url, oauth_providers) = (config.self_url.clone(), config.oauth_providers.clone());
// TODO: Submit current session to login
let loginresult = with_conn![core::login_with_code, C, req, &code, (self_url, oauth_providers)];
let loginresult = with_conn![core::login_with_code, C, req, &code, login_info(&config)];
match loginresult {
// Login successful
......
......@@ -59,19 +59,17 @@
</div>
{{/if}}
{{else}}
<!-- form action="/login" method="post">
<div class="columns blogin">
<div class="column is-three-fifths"><input class="input is-small" type="text" name="username" autofocus placeholder="Benutzername" style="width:50%"><input class="input is-small" type="password" name="password" placeholder="Passwort" style="width:50%"></div>
<div class="column"><input class="button is-small is-success" type="submit" value="↪ &nbsp; Login" onclick="login();"></div>
</div>
</form -->
{{#if password_login}}
<form action="/login" method="post" class="columns blogin">
<div class="column is-8"><input class="input is-small" type="text" name="username" autofocus placeholder="Benutzername" style="width:50%"><input class="input is-small" type="password" name="password" placeholder="Passwort" style="width:50%"></div>
<div class="column"><input class="button is-small is-success" type="submit" value="↪ &nbsp; Login" style="font-weight:bold;"></div>
</form>
{{/if}}
<form action="/clogin" method="post" autocomplete="off" class="columns blogin">
<!-- <div class=> -->
<div class="column is-8"><input class="input is-small" type="text" name="code" placeholder="Gruppencode oder Logincode" autofocus></div>
<div class="column"><input class="button is-small is-success" type="submit" value="↪ &nbsp; Login" style="font-weight:bold;">
&nbsp; <a href="https://bwinf.de/jugendwettbewerb/teilnehmen/schueler/" style="font-size: small;"> (?)</a>
</div>
<!-- </div> -->
<div class="column is-8"><input class="input is-small" type="text" name="code" placeholder="Gruppencode oder Logincode" autofocus></div>
<div class="column"><input class="button is-small is-success" type="submit" value="↪ &nbsp; Login" style="font-weight:bold;">
&nbsp; <a href="https://bwinf.de/jugendwettbewerb/teilnehmen/schueler/" style="font-size: small;"> (?)</a>
</div>
</form>
{{#if self_url}}
{{#each oauth_links}}
......
......@@ -11,7 +11,8 @@
</div>
<!-- - <div class="columns">
{{#if password_login}}
<div class="columns">
<div class="column">
<h2 class="title is-4">Login mit Benutzername und Passwort (nicht PMS-Account)</h2>
</div>
......@@ -26,8 +27,8 @@
<div class="column">
<input class="button is-success" type="submit" value="↪ &nbsp; Login" onclick="login();">
</div>
</form> -->
</form>
{{/if}}
<div class="columns">
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment