Skip to content

Commit f584058

Browse files
committed
delete invalid token
1 parent 6b28835 commit f584058

File tree

4 files changed

+91
-40
lines changed

4 files changed

+91
-40
lines changed

tmc-langs-cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ dirs = "3"
2323
tempfile = "3"
2424
base64 = "0.12"
2525
schemars = "0.7"
26+
thiserror = "1"
2627

2728
[dev-dependencies]
2829
tempfile = "3"

tmc-langs-cli/src/main.rs

Lines changed: 86 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
//! CLI client for TMC
22
33
mod app;
4+
mod error;
45
mod output;
56

67
use anyhow::{Context, Result};
78
use clap::{ArgMatches, Error, ErrorKind};
9+
use error::InvalidTokenError;
810
use output::{CombinedCourseData, DownloadTarget, ErrorData, Kind, Output, OutputResult, Status};
911
use serde::Serialize;
1012
use std::collections::HashMap;
@@ -62,6 +64,11 @@ fn main() {
6264
/// Goes through the error chain and checks for special error types that should be indicated by the Kind.
6365
fn solve_error_kind(e: &anyhow::Error) -> Kind {
6466
for cause in e.chain() {
67+
// check for invalid token
68+
if cause.downcast_ref::<InvalidTokenError>().is_some() {
69+
return Kind::InvalidToken;
70+
}
71+
6572
// check for http errors
6673
if let Some(CoreError::HttpError {
6774
url: _,
@@ -181,7 +188,79 @@ fn run() -> Result<()> {
181188
};
182189
print_output(&output)?
183190
}
184-
("core", Some(matches)) => run_core(matches)?,
191+
("core", Some(matches)) => {
192+
let client_name = matches.value_of("client-name").unwrap();
193+
194+
let client_version = matches.value_of("client-version").unwrap();
195+
196+
let root_url = env::var("TMC_LANGS_ROOT_URL")
197+
.unwrap_or_else(|_| "https://tmc.mooc.fi".to_string());
198+
let mut core = TmcCore::new_in_config(
199+
root_url,
200+
client_name.to_string(),
201+
client_version.to_string(),
202+
)
203+
.context("Failed to create TmcCore")?;
204+
205+
// set token if a credentials.json is found for the client name
206+
let tmc_dir = format!("tmc-{}", client_name);
207+
let config_dir = match env::var("TMC_LANGS_CONFIG_DIR") {
208+
Ok(v) => PathBuf::from(v),
209+
Err(_) => dirs::config_dir().context("Failed to find config directory")?,
210+
};
211+
let credentials_path = config_dir.join(tmc_dir).join("credentials.json");
212+
if let Ok(file) = File::open(&credentials_path) {
213+
match serde_json::from_reader(file) {
214+
Ok(token) => core.set_token(token),
215+
Err(e) => {
216+
log::error!(
217+
"Failed to deserialize credentials.json due to \"{}\", deleting",
218+
e
219+
);
220+
fs::remove_file(&credentials_path).with_context(|| {
221+
format!(
222+
"Failed to remove malformed credentials.json file {}",
223+
credentials_path.display()
224+
)
225+
})?;
226+
}
227+
}
228+
};
229+
230+
match run_core(core, client_name, &credentials_path, matches) {
231+
Ok(token) => token,
232+
Err(error) => {
233+
for cause in error.chain() {
234+
// check if the token was rejected and delete it if so
235+
if let Some(CoreError::HttpError { status, .. }) =
236+
cause.downcast_ref::<CoreError>()
237+
{
238+
if status.as_u16() == 401 {
239+
// delete token
240+
log::info!(
241+
"deleting credentials file at {} due to error {}",
242+
credentials_path.display(),
243+
error
244+
);
245+
fs::remove_file(&credentials_path).with_context(|| {
246+
format!(
247+
"Failed to remove credentials file at {} while handling error {}",
248+
credentials_path.display(),
249+
error
250+
)
251+
})?;
252+
return Err(InvalidTokenError {
253+
path: credentials_path,
254+
source: error,
255+
}
256+
.into());
257+
}
258+
}
259+
}
260+
return Err(error);
261+
}
262+
}
263+
}
185264
("extract-project", Some(matches)) => {
186265
let archive_path = matches.value_of("archive-path").unwrap();
187266
let archive_path = Path::new(archive_path);
@@ -494,19 +573,12 @@ fn run() -> Result<()> {
494573
Ok(())
495574
}
496575

497-
fn run_core(matches: &ArgMatches) -> Result<PrintToken> {
498-
let client_name = matches.value_of("client-name").unwrap();
499-
500-
let client_version = matches.value_of("client-version").unwrap();
501-
502-
let root_url =
503-
env::var("TMC_LANGS_ROOT_URL").unwrap_or_else(|_| "https://tmc.mooc.fi".to_string());
504-
let mut core = TmcCore::new_in_config(
505-
root_url,
506-
client_name.to_string(),
507-
client_version.to_string(),
508-
)
509-
.context("Failed to create TmcCore")?;
576+
fn run_core(
577+
mut core: TmcCore,
578+
client_name: &str,
579+
credentials_path: &Path,
580+
matches: &ArgMatches,
581+
) -> Result<PrintToken> {
510582
// set progress report to print the updates to stdout as JSON
511583
core.set_progress_report(|update| {
512584
// convert to output
@@ -553,31 +625,6 @@ fn run_core(matches: &ArgMatches) -> Result<PrintToken> {
553625
Ok(())
554626
});
555627

556-
// set token if a credentials.json is found for the client name
557-
let tmc_dir = format!("tmc-{}", client_name);
558-
let config_dir = match env::var("TMC_LANGS_CONFIG_DIR") {
559-
Ok(v) => PathBuf::from(v),
560-
Err(_) => dirs::config_dir().context("Failed to find config directory")?,
561-
};
562-
let credentials_path = config_dir.join(tmc_dir).join("credentials.json");
563-
if let Ok(file) = File::open(&credentials_path) {
564-
match serde_json::from_reader(file) {
565-
Ok(token) => core.set_token(token),
566-
Err(e) => {
567-
log::error!(
568-
"Failed to deserialize credentials.json due to \"{}\", deleting",
569-
e
570-
);
571-
fs::remove_file(&credentials_path).with_context(|| {
572-
format!(
573-
"Failed to remove malformed credentials.json file {}",
574-
credentials_path.display()
575-
)
576-
})?;
577-
}
578-
}
579-
};
580-
581628
// proof of having printed the output
582629
let printed: PrintToken = match matches.subcommand() {
583630
("download-model-solution", Some(matches)) => {

tmc-langs-cli/src/output.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ pub enum Kind {
8484
ConnectionError,
8585
/// Client out of date
8686
ObsoleteClient,
87+
/// Invalid token
88+
InvalidToken,
8789
}
8890

8991
#[derive(Debug, Serialize, JsonSchema)]

tmc-langs-framework/src/plugin.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::io::{file_util, submission_processing, tmc_zip};
99
use crate::policy::StudentFilePolicy;
1010
pub use isolang::Language;
1111
use log::debug;
12-
use nom::{branch, bytes, character, combinator, multi, sequence, IResult};
12+
use nom::{branch, bytes, combinator, multi, sequence, IResult};
1313
use std::collections::{HashMap, HashSet};
1414
use std::io::{Read, Seek, Write};
1515
use std::path::{Path, PathBuf};
@@ -506,6 +506,7 @@ enum Parse {
506506
#[cfg(test)]
507507
mod test {
508508
use super::*;
509+
use nom::character;
509510

510511
struct MockPlugin {}
511512

0 commit comments

Comments
 (0)