#pragma clang diagnostic push #pragma ide diagnostic ignored "readability-make-member-function-const" #pragma ide diagnostic ignored "readability-convert-member-functions-to-static" #include #include #include #include #include #if defined(BOTAN_HAS_SYSTEM_RNG) #include #else #include #endif #include #include #include #include "controllers/controllers.h" #include "db/db.h" #include "dto/dto.h" namespace api { #if defined(BOTAN_HAS_SYSTEM_RNG) std::unique_ptr auth::rng = std::make_unique(); #else std::unique_ptr auth::rng = std::make_unique(); #endif bool auth::verify2fa(const db::User& user, uint32_t totp) { size_t allowed_skew = db::User_getEnumTfaType(user) == db::tfaTypes::TOTP ? 0 : 10; const auto& totp_secret = (const std::vector&) user.getValueOfTfaSecret(); return Botan::TOTP(Botan::OctetString(totp_secret)).verify_totp(totp, std::chrono::system_clock::now(), allowed_skew); } void auth::send_mail(const db::User& user) { std::time_t t = std::time(nullptr); const auto& totp_secret = (const std::vector&) user.getValueOfTfaSecret(); char totp[16]; std::snprintf(totp, 16, "%06d", Botan::TOTP(Botan::OctetString(totp_secret)).generate_totp(t)); mailio::message msg; msg.from(mailio::mail_address("Fileserver", "fileserver@mattv.de")); msg.add_recipient(mailio::mail_address(user.getValueOfName(), user.getValueOfName())); msg.subject("Subject: Fileserver - Email 2fa code"); msg.content("Your code is: " + std::string(totp) +"\r\nIt is valid for 5 Minutes"); mailio::smtps conn("mail.mattv.de", 587); conn.authenticate("no-reply@mattv.de", "noreplyLONGPASS123", mailio::smtps::auth_method_t::START_TLS); conn.submit(msg); } std::string auth::get_token(const db::User& user) { auto db = drogon::app().getDbClient(); db::MapperToken token_mapper(db); const auto iat = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()); const auto exp = iat + std::chrono::hours{24}; db::Token new_token; new_token.setOwnerId(user.getValueOfId()); new_token.setExp(exp.count()); token_mapper.insert(new_token); return jwt::create() .set_type("JWT") .set_payload_claim("sub", picojson::value((int64_t)user.getValueOfId())) .set_payload_claim("jti", picojson::value((int64_t)new_token.getValueOfId())) .set_issued_at(std::chrono::system_clock::from_time_t(iat.count())) .set_expires_at(std::chrono::system_clock::from_time_t(exp.count())) .sign(jwt::algorithm::hs256{jwt_secret}); } void auth::generate_root(db::User& user) { db::MapperUser user_mapper(drogon::app().getDbClient()); auto node = fs::create_node("", user, false, std::nullopt, true); user.setRootId(std::get(node).getValueOfId()); user_mapper.update(user); } void auth::revoke_all(const db::User& user) { db::MapperToken token_mapper(drogon::app().getDbClient()); token_mapper.deleteBy(db::Criteria(db::Token::Cols::_owner_id, db::CompareOps::EQ, user.getValueOfId())); } } #pragma clang diagnostic pop