Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Force update cache for auth via postgresql #558

Open
h1laryz opened this issue Apr 29, 2024 · 0 comments
Open

Force update cache for auth via postgresql #558

h1laryz opened this issue Apr 29, 2024 · 0 comments

Comments

@h1laryz
Copy link

h1laryz commented Apr 29, 2024

Hi, I watched into documentation at userver.tech. There was an example Custom Authorization/Authentication via PostgreSQL "Creation of tokens and user registration is out of scope of this tutorial."

I made a custom basic registration:

hpp

namespace rl::handlers
{
class Register final : public userver::server::handlers::HttpHandlerBase
{
public:
    Register( const userver::components::ComponentConfig& config,
              const userver::components::ComponentContext& context );

public:
    static constexpr std::string_view kName = "handler-register";
    using HttpHandlerBase::HttpHandlerBase;

    std::string
    HandleRequestThrow( const userver::server::http::HttpRequest& request,
                        userver::server::request::RequestContext& request_context ) const override;

private:
    userver::storages::postgres::ClusterPtr pg_cluster_;
};
} // namespace rl::handlers

cpp

namespace rl::handlers
{
Register::Register( const userver::components::ComponentConfig& config,
                    const userver::components::ComponentContext& context )
    : userver::server::handlers::HttpHandlerBase{ config, context }
    , pg_cluster_{
        context.FindComponent< userver::components::Postgres >( "auth-database" ).GetCluster()
    }
{
}

std::string
Register::HandleRequestThrow( const userver::server::http::HttpRequest& request,
                              userver::server::request::RequestContext& ) const
{
    const auto request_body{ userver::formats::json::FromString( request.RequestBody() ) };

    const auto& username { request_body["username"].As<std::string>() };
    const auto& password { request_body[ "password" ].As< std::string >() };
    const auto& mail { request_body["mail"].As<std::string>() };

    const auto token = jwt::create()
                     .set_type( "JWT" )
                     .set_id( "rsa-create-example" )
                     .set_issued_now()
                     .set_expires_in( std::chrono::seconds{ 36000 } )
                     .set_payload_claim( "sample", jwt::claim( std::string{ "test" } ) )
                     .sign( jwt::algorithm::hs256( "secret" ) );

    auto trx { pg_cluster_->Begin("sample_transaction_insert_key_value", userver::storages::postgres::ClusterHostType::kMaster, {})};

    const auto pg_query_register = "INSERT INTO auth_schema.users(username, mail, password) "
        "VALUES ($1, $2, $3) "
        "RETURNING id;";

    auto trx_result{ pg_cluster_->Execute(
        userver::storages::postgres::ClusterHostType::kSlave,
        pg_query_register,
        username,
        mail,
        password ) };

    if ( trx_result.IsEmpty() )
    {
        request.SetResponseStatus( userver::server::http::HttpStatus::kBadRequest );
        return {};
    }

    const auto user_id { trx_result.AsSingleRow<int>() };

    const auto pg_query_save_token{ "INSERT INTO auth_schema.tokens(token, user_id) "
    "VALUES ($1, $2);" };

    trx_result = pg_cluster_->Execute(
    userver::storages::postgres::ClusterHostType::kMaster,
    pg_query_save_token,
        token,
        user_id);

    trx.Commit();

    userver::formats::json::ValueBuilder response;
    response[ "token" ] = token;

    return userver::formats::json::ToString( response.ExtractValue() );
}
} // namespace rl::handlers

Cache for auth from example:

namespace rl::pg::auth
{
struct UserDbInfo
{
    userver::server::auth::UserAuthInfo::Ticket token;
    std::int64_t user_id;
    std::vector< std::string > scopes;
};

struct AuthCachePolicy
{
    static constexpr std::string_view kName = "auth-pg-cache";

    using ValueType                  = UserDbInfo;
    static constexpr auto kKeyMember = &UserDbInfo::token;
    static constexpr const char* kQuery =
        "SELECT token, user_id, scopes, name FROM auth_schema.tokens";
    static constexpr const char* kUpdatedField = "updated";
    using UpdatedFieldType                     = userver::storages::postgres::TimePointTz;

    // Using crypto::algorithm::StringsEqualConstTimeComparator to avoid timing
    // attack at find(token).
    using CacheContainer =
        std::unordered_map< userver::server::auth::UserAuthInfo::Ticket,
                            UserDbInfo,
                            std::hash< userver::server::auth::UserAuthInfo::Ticket >,
                            userver::crypto::algorithm::StringsEqualConstTimeComparator >;
};

using AuthCache = userver::components::PostgreCache< AuthCachePolicy >;
} // namespace rl::pg::auth

Is it possible to force updating cache? Or it is ok to wait until it updates itself each 10 seconds?

@h1laryz h1laryz changed the title Registration for future auth via postgresql Force update cache for auth via postgresql Apr 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant