diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000000000000000000000000000000000000..45edb19df793bf299025d157846ee84ae901c192
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,4 @@
+reorder_impl_items = true
+imports_granularity = "Module"
+group_imports = "StdExternalCrate"
+use_try_shorthand = true
diff --git a/src/broadcaster.rs b/src/broadcaster.rs
index c71b9685e6134516d0a2d9c717354dc241ab34f1..5082e5847a90cd3617212298d600114c2ca48bc9 100644
--- a/src/broadcaster.rs
+++ b/src/broadcaster.rs
@@ -1,15 +1,17 @@
-use crate::queue::job_protocol::{job_result, JobResult};
-use actix_web::rt::time::{interval_at, Instant};
-use actix_web::web::{Bytes, Data};
-use actix_web::Error;
-use futures::Stream;
 use std::pin::Pin;
 use std::sync::Mutex;
 use std::task::{Context, Poll};
 use std::time::Duration;
+
+use actix_web::rt::time::{interval_at, Instant};
+use actix_web::web::{Bytes, Data};
+use actix_web::Error;
+use futures::Stream;
 use tokio::sync::broadcast;
 use tokio::sync::mpsc::{channel, Receiver, Sender};
 
+use crate::queue::job_protocol::{job_result, JobResult};
+
 pub struct Broadcaster {
     clients: Vec<Sender<Bytes>>,
 }
diff --git a/src/import_contest.rs b/src/import_contest.rs
index 2d77f528dd2b35504bc8386a07a108ad6cb403bc..bbeac6228aba2fc3ef4dd38de86548b1e47e7c19 100644
--- a/src/import_contest.rs
+++ b/src/import_contest.rs
@@ -1,12 +1,13 @@
-use lazy_static::lazy_static;
-use regex::Captures;
-use regex::Regex;
 use std::io::{Read, Seek};
+
+use lazy_static::lazy_static;
+use regex::{Captures, Regex};
 use zip::ZipArchive;
 
 mod error {
-    use quick_xml::de::DeError;
     use std::io;
+
+    use quick_xml::de::DeError;
     use thiserror::Error;
     use zip::result::ZipError;
 
@@ -37,10 +38,12 @@ mod xml {
     }
 
     pub mod prelude {
-        pub use super::super::ImportContestError;
-        pub use serde::Deserialize;
         pub use std::io::{Read, Seek};
+
+        pub use serde::Deserialize;
         pub use zip::ZipArchive;
+
+        pub use super::super::ImportContestError;
     }
 
     pub mod contest {
diff --git a/src/language.rs b/src/language.rs
index 2272ae6f30db073f05a9ea8a89ae8d4370fab577..0c7d4726141bd0cc4c36213dc6d914c9e18bba2b 100644
--- a/src/language.rs
+++ b/src/language.rs
@@ -1,11 +1,11 @@
-use crate::queue::job_protocol::job_result;
-use crate::queue::job_protocol::{job, Job, JobResult};
 use async_channel::Sender;
 use log::info;
 use thiserror::Error;
 use tokio::sync::broadcast;
 use uuid::Uuid;
 
+use crate::queue::job_protocol::{job, job_result, Job, JobResult};
+
 #[derive(Error, Debug, Clone)]
 #[error("job failed")]
 struct JobFailedError;
diff --git a/src/lib.rs b/src/lib.rs
index 4b4c22247a98385c56f8875fb05925436426aed6..f67ac48b43161ce875ad2ef8a7fdd755153d51e5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,7 @@
-pub mod import_contest;
 mod queue;
 
+pub mod import_contest;
+
 pub mod job_protocol {
     pub use crate::queue::job_protocol::*;
 }
diff --git a/src/main.rs b/src/main.rs
index 083bc5026c85ae0549784f9ec4d7214dea250b4e..65f3e9aee25dd0d59414de46e50b3288ec924906 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,24 +1,64 @@
-use lazy_static::lazy_static;
-use serde::{Deserialize, Serialize};
+use std::collections::HashMap;
+use std::convert::TryFrom;
+use std::error::Error;
+use std::fs::{create_dir_all, File};
+use std::future::Future;
+use std::io::{Cursor, Read, Write};
+use std::iter::FromIterator;
+use std::path::PathBuf;
+use std::pin::Pin;
+use std::sync::{Arc, Mutex};
+use std::time::Duration;
+use std::{env, fs, str};
 
-use actix_files::Files;
-use actix_identity::Identity;
-use actix_identity::IdentityMiddleware;
+use actix_files::{Files, NamedFile};
+use actix_identity::{Identity, IdentityMiddleware};
+use actix_multipart::Multipart;
 use actix_session::storage::CookieSessionStore;
-use actix_session::Session;
-use actix_session::SessionMiddleware;
+use actix_session::{Session, SessionMiddleware};
+use actix_web::cookie::Key;
+use actix_web::dev::Payload;
+use actix_web::http::header::{ContentType, HeaderValue};
+use actix_web::http::{header, StatusCode};
 use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers};
-use actix_web::HttpResponse;
-use actix_web::{dev, get, http, middleware, post, web, App, HttpServer};
+use actix_web::web::Data;
+use actix_web::{
+    dev, get, http, middleware, post, web, App, FromRequest, HttpMessage, HttpRequest,
+    HttpResponse, HttpServer,
+};
+use actix_web_flash_messages::storage::CookieMessageStore;
+use actix_web_flash_messages::{
+    FlashMessage, FlashMessagesFramework, IncomingFlashMessages, Level,
+};
+use async_channel::Sender;
+use base64;
+use broadcaster::Broadcaster;
 use chrono::prelude::*;
+use chrono_tz::Tz;
+use contest::{Contest, ContestWithAcs};
+use dashmap::DashMap;
 use diesel::pg::PgConnection;
 use diesel::r2d2::ConnectionManager;
+use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
+use futures::{StreamExt, TryFutureExt, TryStreamExt};
 use handlebars::Handlebars;
+use itertools::Itertools;
+use lazy_static::lazy_static;
+use listenfd::ListenFd;
 use log::{error, info};
-use models::submission;
-use models::user;
-use std::env;
-use std::fs::File;
+use models::problem::ProblemByContest;
+use models::{contest, problem, submission, user};
+use problem::{ProblemByContestMetadata, ProblemByContestWithScore};
+use queue::job_protocol::job_queue_server::JobQueueServer;
+use queue::job_protocol::{job, job_result, Job, JobResult, Language};
+use queue::JobQueuer;
+use regex::Regex;
+use serde::{Deserialize, Serialize};
+use submission::{ContestProblem, Submission, SubmissionCompletion};
+use thiserror::Error;
+use tokio::sync::broadcast;
+use tonic::transport::Server;
+use user::{PasswordMatched, User, UserHashingError};
 use uuid::Uuid;
 
 mod broadcaster;
@@ -29,24 +69,7 @@ mod queue;
 mod schema;
 mod setup;
 
-use broadcaster::Broadcaster;
-use listenfd::ListenFd;
-use std::sync::Mutex;
 type DbPool = r2d2::Pool<ConnectionManager<PgConnection>>;
-use actix_web::web::Data;
-use actix_web::HttpMessage;
-use async_channel::Sender;
-use chrono_tz::Tz;
-use futures::TryFutureExt;
-use queue::job_protocol::job_queue_server::JobQueueServer;
-use queue::job_protocol::{job, job_result, Job, JobResult, Language};
-use queue::JobQueuer;
-use std::error::Error;
-use std::fs;
-use std::time::Duration;
-use submission::SubmissionCompletion;
-use tokio::sync::broadcast;
-use tonic::transport::Server;
 
 async fn update_database(
     mut job_result_receiver: broadcast::Receiver<JobResult>,
@@ -98,18 +121,6 @@ async fn update_database(
     }
 }
 
-use base64;
-
-use actix_web::cookie::Key;
-use diesel_migrations::MigrationHarness;
-use diesel_migrations::{embed_migrations, EmbeddedMigrations};
-pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
-
-use actix_web_flash_messages::storage::CookieMessageStore;
-use actix_web_flash_messages::{FlashMessagesFramework, Level};
-
-use problem::ProblemByContestMetadata;
-use submission::Submission;
 fn create_job_from_submission(submission: Submission, metadata: ProblemByContestMetadata) -> Job {
     Job {
         uuid: submission.uuid,
@@ -127,6 +138,8 @@ fn create_job_from_submission(submission: Submission, metadata: ProblemByContest
     }
 }
 
+pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
+
 #[actix_web::main]
 async fn main() -> Result<(), Box<dyn Error>> {
     std::env::set_var("RUST_LOG", "info");
@@ -271,9 +284,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
     Ok(())
 }
 
-use actix_web::http::StatusCode;
-use thiserror::Error;
-
 #[derive(Error, Debug)]
 #[error("unauthorized")]
 struct UnauthorizedError {}
@@ -377,8 +387,6 @@ impl actix_web::error::ResponseError for GetError {
     }
 }
 
-use actix_web_flash_messages::IncomingFlashMessages;
-
 type GetResult = Result<HttpResponse, GetError>;
 
 #[derive(Serialize)]
@@ -388,10 +396,6 @@ struct BaseContext {
     base_url: String,
 }
 
-use actix_web::dev::Payload;
-use actix_web::FromRequest;
-use std::future::Future;
-use std::pin::Pin;
 impl FromRequest for BaseContext {
     type Error = actix_web::Error;
     type Future = Pin<Box<dyn Future<Output = Result<Self, Self::Error>>>>;
@@ -431,8 +435,6 @@ async fn get_me(base: BaseContext, identity: Identity, hb: web::Data<Handlebars<
     Ok(HttpResponse::Ok().body(hb.render("me", &Context { base })?))
 }
 
-use actix_files::NamedFile;
-
 #[get("/problems/{id}/assets/{filename}")]
 async fn get_problem_by_id_assets(
     identity: Identity,
@@ -452,11 +454,6 @@ async fn get_problem_by_id_assets(
     Ok(NamedFile::open(file_path)?)
 }
 
-use actix_web::http::header;
-use actix_web::http::header::ContentType;
-use actix_web::http::header::HeaderValue;
-use actix_web_flash_messages::FlashMessage;
-
 fn render_401<B>(mut res: dev::ServiceResponse<B>) -> actix_web::Result<ErrorHandlerResponse<B>> {
     FlashMessage::error("Você precisa estar logado para acessar esta página").send();
     res.response_mut().headers_mut().insert(
@@ -482,9 +479,6 @@ struct LoginForm {
     password: String,
 }
 
-use models::problem;
-use models::problem::ProblemByContest;
-
 fn get_identity(identity: &Identity) -> Option<LoggedUser> {
     let identity = identity.id();
     identity
@@ -514,8 +508,6 @@ fn format_duration(duration: chrono::Duration) -> String {
     )
 }
 
-use contest::{Contest, ContestWithAcs};
-
 #[derive(Serialize)]
 struct FormattedProblemByContestWithScore {
     pub first_ac_submission_time: String,
@@ -529,8 +521,6 @@ struct FormattedProblemByContestWithScore {
     pub time_limit: String,
 }
 
-use problem::ProblemByContestWithScore;
-
 fn get_formatted_problem_by_contest_with_score(
     p: &ProblemByContestWithScore,
     contest: &Contest,
@@ -607,9 +597,6 @@ async fn get_contest_by_id(
     ))
 }
 
-use itertools::Itertools;
-use std::convert::TryFrom;
-
 #[get("/contests/{id}/scoreboard")]
 async fn get_contest_scoreboard_by_id(
     base: BaseContext,
@@ -796,8 +783,6 @@ async fn post_login(
 ) -> PostResult {
     let mut connection = pool.get()?;
 
-    use user::PasswordMatched;
-    use user::UserHashingError;
     match web::block(move || {
         user::check_matching_password(&mut connection, &form.name, &form.password)
     })
@@ -860,8 +845,6 @@ fn format_utc_date_time(tz: &Tz, input: NaiveDateTime) -> String {
         .to_string()
 }
 
-use submission::ContestProblem;
-use user::User;
 fn get_formatted_submissions(
     tz: &Tz,
     vec: &Vec<(Submission, ContestProblem, User)>,
@@ -1088,12 +1071,6 @@ struct SubmissionForm {
     source_text: String,
 }
 
-use dashmap::DashMap;
-use std::collections::HashMap;
-use std::sync::Arc;
-
-use actix_web::HttpRequest;
-
 fn redirect_to_root() -> HttpResponse {
     HttpResponse::SeeOther()
         .append_header((
@@ -1140,7 +1117,6 @@ async fn change_password(
 
     let mut connection = pool.get()?;
 
-    use user::PasswordMatched;
     match user::change_password(
         &mut connection,
         identity.id,
@@ -1478,19 +1454,6 @@ async fn get_contests(
     )?))
 }
 
-use crate::models::contest;
-use actix_multipart::Multipart;
-use futures::StreamExt;
-use futures::TryStreamExt;
-use regex::Regex;
-use std::fs::create_dir_all;
-use std::io::Cursor;
-use std::io::Read;
-use std::io::Write;
-use std::iter::FromIterator;
-use std::path::PathBuf;
-use std::str;
-
 #[post("/contests/")]
 async fn create_contest(
     identity: Identity,
diff --git a/src/models/contest.rs b/src/models/contest.rs
index 410c57e6e4cbb2617afe0ba15676e6ce75a4d075..34187dcdd6802ed23234db93b4a22b5016e8f3b4 100644
--- a/src/models/contest.rs
+++ b/src/models/contest.rs
@@ -2,8 +2,7 @@ use chrono::prelude::*;
 use diesel::insert_into;
 use diesel::prelude::*;
 
-use crate::schema::contest;
-use crate::schema::contest_problems;
+use crate::schema::{contest, contest_problems};
 
 #[derive(Queryable)]
 pub struct Contest {
diff --git a/src/models/problem.rs b/src/models/problem.rs
index 34e46ccd3453e9bfa32b0c102acb83d5d5de0b70..9cc1b359205e0e62237828485b118db7456b63e9 100644
--- a/src/models/problem.rs
+++ b/src/models/problem.rs
@@ -4,8 +4,7 @@ use diesel::pg::PgConnection;
 use diesel::prelude::*;
 use serde::Serialize;
 
-use crate::schema::contest_problems;
-use crate::schema::problem;
+use crate::schema::{contest_problems, problem};
 
 #[derive(Queryable)]
 pub struct Problem {
diff --git a/src/models/submission.rs b/src/models/submission.rs
index 077d3e089066a1d0ad9504dd4bace051d2210460..ac095c5d0eb2b546491bc2a1a6566017d03970b1 100644
--- a/src/models/submission.rs
+++ b/src/models/submission.rs
@@ -1,14 +1,11 @@
-use crate::contest::{Contest, CONTEST_COLUMNS};
-use crate::schema::contest;
-use crate::schema::contest_problems;
-use crate::schema::problem;
-use crate::schema::submission;
-use crate::schema::user;
-use crate::user::{User, USER_COLUMNS};
 use chrono::prelude::*;
 use diesel::insert_into;
 use diesel::prelude::*;
 
+use crate::contest::{Contest, CONTEST_COLUMNS};
+use crate::schema::{contest, contest_problems, problem, submission, user};
+use crate::user::{User, USER_COLUMNS};
+
 #[derive(Queryable)]
 pub struct Submission {
     pub uuid: String,
diff --git a/src/models/user.rs b/src/models/user.rs
index 0d9a04ff87be8a0f9ee6110615262530788c4ff4..02d477079f77de182a36f63e06fde432d01aadd2 100644
--- a/src/models/user.rs
+++ b/src/models/user.rs
@@ -1,9 +1,10 @@
+use std::env;
+
 use chrono::prelude::*;
 use diesel::insert_into;
 use diesel::pg::PgConnection;
 use diesel::prelude::*;
 use serde::Serialize;
-use std::env;
 use thiserror::Error;
 
 use crate::schema::user;
diff --git a/src/queue.rs b/src/queue.rs
index ebd293ed9e13ee4ac2ca2c1ab64dc53a56f2a436..237418852b9e919c625489afe4c212c95f5935b5 100644
--- a/src/queue.rs
+++ b/src/queue.rs
@@ -1,9 +1,10 @@
+use std::sync::Arc;
+
 use async_channel::Receiver;
 use dashmap::DashMap;
 use job_protocol::job_queue_server::JobQueue;
 use job_protocol::{GetJobRequest, Job, JobResult, JobResultConfirmation, Language};
 use log::info;
-use std::sync::Arc;
 use tokio::sync::broadcast;
 use tonic::{Request, Response, Status};
 
diff --git a/src/setup.rs b/src/setup.rs
index cd1807086cede4db5d5beb2c53133258a57d8b0b..c85a0e74dd0f945481aecdd72e91e2f44cac0e77 100644
--- a/src/setup.rs
+++ b/src/setup.rs
@@ -1,9 +1,9 @@
 use chrono::prelude::*;
+use diesel::PgConnection;
 use log::info;
 
 use crate::models::user;
 use crate::models::user::NewUser;
-use diesel::PgConnection;
 
 pub fn setup_admin(connection: &mut PgConnection) {
     use user::PasswordMatched;