mirror of
https://github.com/arun11299/cpp-jwt.git
synced 2025-05-14 16:58:34 +00:00
jwt_object design
This commit is contained in:
parent
81e6b2392e
commit
cb925fee3a
6 changed files with 372 additions and 0 deletions
|
@ -2,11 +2,15 @@
|
||||||
#define CPP_JWT_META_HPP
|
#define CPP_JWT_META_HPP
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include "jwt/string_view.hpp"
|
||||||
|
|
||||||
namespace jwt {
|
namespace jwt {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
namespace meta {
|
namespace meta {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The famous void_t trick.
|
||||||
|
*/
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
struct make_void
|
struct make_void
|
||||||
{
|
{
|
||||||
|
@ -16,7 +20,16 @@ struct make_void
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
using void_t = typename make_void<T...>::type;
|
using void_t = typename make_void<T...>::type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A type tag representing an empty tag.
|
||||||
|
* To be used to represent a `result-not-found`
|
||||||
|
* situation.
|
||||||
|
*/
|
||||||
|
struct empty_type {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
template <typename T, typename=void>
|
template <typename T, typename=void>
|
||||||
struct has_create_json_obj_member: std::false_type
|
struct has_create_json_obj_member: std::false_type
|
||||||
{
|
{
|
||||||
|
@ -34,6 +47,91 @@ struct has_create_json_obj_member<T,
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the type `T` models MappingConcept.
|
||||||
|
*
|
||||||
|
* Requirements on type `T` for matching the requirements:
|
||||||
|
* a. Must be able to construct jwt::string_view from the
|
||||||
|
* `key_type` of the map.
|
||||||
|
* b. Must be able to construct jwt::string_view from the
|
||||||
|
* `mapped_type` of the map.
|
||||||
|
* c. The type `T` must have an access operator i.e. operator[].
|
||||||
|
* d. The type `T` must have `begin` and `end` member functions
|
||||||
|
* for iteration.
|
||||||
|
*
|
||||||
|
* NOTE: Requirements `a` and `b` means that the concept
|
||||||
|
* type can only hold values that are string or constructible
|
||||||
|
* to form a string_view (basically C strings and std::string)
|
||||||
|
*/
|
||||||
|
template <typename T, typename=void>
|
||||||
|
struct is_mapping_concept: std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_mapping_concept<T,
|
||||||
|
void_t<
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_constructible<jwt::string_view, typename T::key_type>::value,
|
||||||
|
void
|
||||||
|
>::type,
|
||||||
|
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_constructible<jwt::string_view, typename T::mapped_type>::value,
|
||||||
|
void
|
||||||
|
>::type,
|
||||||
|
|
||||||
|
decltype(
|
||||||
|
std::declval<T&>().operator[](std::declval<const typename T::key_type&>()),
|
||||||
|
std::declval<T&>().begin(),
|
||||||
|
std::declval<T&>().end(),
|
||||||
|
(void)0
|
||||||
|
)
|
||||||
|
|
||||||
|
>
|
||||||
|
>: std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the type `T` models the ParameterConcept.
|
||||||
|
*
|
||||||
|
* Requirements on type `T` for matching the requirements:
|
||||||
|
* a. The type must have a `get` method.
|
||||||
|
*/
|
||||||
|
template <typename T, typename=void>
|
||||||
|
struct is_parameter_concept: std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_parameter_concept<T,
|
||||||
|
void_t<
|
||||||
|
decltype(
|
||||||
|
std::declval<T&>().get(),
|
||||||
|
(void)0
|
||||||
|
)
|
||||||
|
>
|
||||||
|
>: std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <bool... V>
|
||||||
|
struct bool_pack {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <bool... B>
|
||||||
|
using all_true = std::is_same<bool_pack<true, B...>, bool_pack<B..., true>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <typename... T>
|
||||||
|
using are_all_params = all_true<is_parameter_concept<T>{}...>;
|
||||||
|
|
||||||
|
|
||||||
} // END namespace meta
|
} // END namespace meta
|
||||||
} // END namespace detail
|
} // END namespace detail
|
||||||
|
|
|
@ -197,6 +197,51 @@ jwt_signature::get_verify_algorithm_impl(const jwt_header& hdr) const noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
template <typename... Args>
|
||||||
|
jwt_object::jwt_object(Args&&... args)
|
||||||
|
{
|
||||||
|
static_assert (detail::meta::are_all_params<Args...>::value,
|
||||||
|
"All constructor argument types must model ParameterConcept");
|
||||||
|
|
||||||
|
set_parameters(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Map, typename... Rest>
|
||||||
|
void jwt_object::set_parameters(
|
||||||
|
params::detail::payload_param<Map>&& payload, Rest&&... rargs)
|
||||||
|
{
|
||||||
|
set_parameters(std::forward<Rest>(rargs)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Rest>
|
||||||
|
void jwt_object::set_parameters(
|
||||||
|
params::detail::secret_param secret, Rest&&... rargs)
|
||||||
|
{
|
||||||
|
set_parameters(std::forward<Rest>(rargs)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Map, typename... Rest>
|
||||||
|
void jwt_object::set_parameters(
|
||||||
|
params::detail::headers_param<Map>&& header, Rest&&... rargs)
|
||||||
|
{
|
||||||
|
set_parameters(std::forward<Rest>(rargs)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jwt_object::set_parameters()
|
||||||
|
{
|
||||||
|
//setinel call
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
jwt_payload& jwt_object::add_payload(const std::string& name, T&& value)
|
||||||
|
{
|
||||||
|
payload_.add_claim(name, std::forward<T>(value));
|
||||||
|
return payload_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
|
|
||||||
void jwt_decode(const string_view encoded_str, const string_view key, bool validate)
|
void jwt_decode(const string_view encoded_str, const string_view key, bool validate)
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "jwt/base64.hpp"
|
#include "jwt/base64.hpp"
|
||||||
#include "jwt/algorithm.hpp"
|
#include "jwt/algorithm.hpp"
|
||||||
#include "jwt/string_view.hpp"
|
#include "jwt/string_view.hpp"
|
||||||
|
#include "jwt/parameters.hpp"
|
||||||
#include "jwt/json/json.hpp"
|
#include "jwt/json/json.hpp"
|
||||||
|
|
||||||
// For convenience
|
// For convenience
|
||||||
|
@ -442,6 +443,7 @@ private: // Private implementation
|
||||||
verify_func_t get_verify_algorithm_impl(const jwt_header& hdr) const noexcept;
|
verify_func_t get_verify_algorithm_impl(const jwt_header& hdr) const noexcept;
|
||||||
|
|
||||||
private: // Data members;
|
private: // Data members;
|
||||||
|
|
||||||
/// The key for creating the JWS
|
/// The key for creating the JWS
|
||||||
std::string key_;
|
std::string key_;
|
||||||
};
|
};
|
||||||
|
@ -452,16 +454,84 @@ private: // Data members;
|
||||||
class jwt_object
|
class jwt_object
|
||||||
{
|
{
|
||||||
public: // 'tors
|
public: // 'tors
|
||||||
|
/**
|
||||||
|
*/
|
||||||
jwt_object() = default;
|
jwt_object() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <typename... Args>
|
||||||
|
jwt_object(Args&&... args);
|
||||||
|
|
||||||
public: // Exposed APIs
|
public: // Exposed APIs
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
jwt_payload& payload() noexcept
|
||||||
|
{
|
||||||
|
return payload_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
const jwt_payload& payload() const noexcept
|
||||||
|
{
|
||||||
|
return payload_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
jwt_header& header() noexcept
|
||||||
|
{
|
||||||
|
return header_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
const jwt_header& header() const noexcept
|
||||||
|
{
|
||||||
|
return header_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
jwt_payload& add_payload(const std::string& name, T&& value);
|
||||||
|
|
||||||
|
private: // private APIs
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <typename... Args>
|
||||||
|
void set_parameters(Args&&... args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <typename M, typename... Rest>
|
||||||
|
void set_parameters(params::detail::payload_param<M>&&, Rest&&...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <typename... Rest>
|
||||||
|
void set_parameters(params::detail::secret_param, Rest&&...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <typename M, typename... Rest>
|
||||||
|
void set_parameters(params::detail::headers_param<M>&&, Rest&&...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
void set_parameters();
|
||||||
|
|
||||||
private: // Data Members
|
private: // Data Members
|
||||||
|
|
||||||
/// JWT header section
|
/// JWT header section
|
||||||
jwt_header header_;
|
jwt_header header_;
|
||||||
|
|
||||||
/// JWT payload section
|
/// JWT payload section
|
||||||
jwt_payload payload_;
|
jwt_payload payload_;
|
||||||
|
|
||||||
|
/// The secret key
|
||||||
|
std::string secret_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
143
include/jwt/parameters.hpp
Normal file
143
include/jwt/parameters.hpp
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
#ifndef CPP_JWT_PARAMETERS_HPP
|
||||||
|
#define CPP_JWT_PARAMETERS_HPP
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "jwt/detail/meta.hpp"
|
||||||
|
#include "jwt/string_view.hpp"
|
||||||
|
|
||||||
|
namespace jwt {
|
||||||
|
namespace params {
|
||||||
|
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
/**
|
||||||
|
* Parameter for providing the payload.
|
||||||
|
* Takes a Mapping concept representing
|
||||||
|
* key-value pairs.
|
||||||
|
*
|
||||||
|
* NOTE: MappingConcept allows only strings
|
||||||
|
* for both keys and values. Use `add_header`
|
||||||
|
* API of `jwt_object` otherwise.
|
||||||
|
*
|
||||||
|
* Modeled as ParameterConcept.
|
||||||
|
*/
|
||||||
|
template <typename MappingConcept>
|
||||||
|
struct payload_param
|
||||||
|
{
|
||||||
|
payload_param(MappingConcept&& mc)
|
||||||
|
: payload_(std::forward<MappingConcept>(mc))
|
||||||
|
{}
|
||||||
|
|
||||||
|
MappingConcept get() && { return std::move(payload_); }
|
||||||
|
const MappingConcept& get() const& { return payload_; }
|
||||||
|
|
||||||
|
MappingConcept payload_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameter for providing the secret key.
|
||||||
|
* Stores only the view of the provided string
|
||||||
|
* as string_view. Later the implementation may or
|
||||||
|
* may-not copy it.
|
||||||
|
*
|
||||||
|
* Modeled as ParameterConcept.
|
||||||
|
*/
|
||||||
|
struct secret_param
|
||||||
|
{
|
||||||
|
secret_param(string_view sv)
|
||||||
|
: secret_(sv)
|
||||||
|
{}
|
||||||
|
|
||||||
|
string_view get() { return secret_; }
|
||||||
|
string_view secret_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameter for providing additional headers.
|
||||||
|
* Takes a mapping concept representing
|
||||||
|
* key-value pairs.
|
||||||
|
*
|
||||||
|
* Modeled as ParameterConcept.
|
||||||
|
*/
|
||||||
|
template <typename MappingConcept>
|
||||||
|
struct headers_param
|
||||||
|
{
|
||||||
|
headers_param(MappingConcept&& mc)
|
||||||
|
: headers_(std::forward<MappingConcept>(mc))
|
||||||
|
{}
|
||||||
|
|
||||||
|
MappingConcept get() && { return std::move(headers_); }
|
||||||
|
const MappingConcept& get() const& { return headers_; }
|
||||||
|
|
||||||
|
MappingConcept headers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // END namespace detail
|
||||||
|
|
||||||
|
// Useful typedef
|
||||||
|
using param_init_list_t = std::initializer_list<std::pair<jwt::string_view, jwt::string_view>>;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <typename MappingConcept,
|
||||||
|
typename=typename jwt::detail::meta::is_mapping_concept<MappingConcept>::type>
|
||||||
|
detail::payload_param<MappingConcept>
|
||||||
|
payload(MappingConcept&& mc)
|
||||||
|
{
|
||||||
|
return { std::forward<MappingConcept>(mc) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
detail::payload_param<std::unordered_map<std::string, std::string>>
|
||||||
|
payload(const param_init_list_t& kvs)
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, std::string> m;
|
||||||
|
|
||||||
|
for (const auto& elem : kvs) {
|
||||||
|
m.emplace(elem.first.data(), elem.second.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
return { std::move(m) };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
detail::secret_param secret(string_view sv)
|
||||||
|
{
|
||||||
|
return { sv };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template <typename MappingConcept,
|
||||||
|
typename=typename jwt::detail::meta::is_mapping_concept<MappingConcept>::type>
|
||||||
|
detail::headers_param<MappingConcept>
|
||||||
|
headers(MappingConcept&& mc)
|
||||||
|
{
|
||||||
|
return { std::forward<MappingConcept>(mc) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
detail::headers_param<std::map<std::string, std::string>>
|
||||||
|
headers(const param_init_list_t& kvs)
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string> m;
|
||||||
|
|
||||||
|
for (const auto& elem : kvs) {
|
||||||
|
m.emplace(elem.first.data(), elem.second.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
return { std::move(m) };
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END namespace params
|
||||||
|
} // END namespace jwt
|
||||||
|
|
||||||
|
#endif
|
BIN
include/jwt/test/test_jwt_object
Executable file
BIN
include/jwt/test/test_jwt_object
Executable file
Binary file not shown.
16
include/jwt/test/test_jwt_object.cc
Normal file
16
include/jwt/test/test_jwt_object.cc
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include "jwt/jwt.hpp"
|
||||||
|
|
||||||
|
void basic_jwt_object_test()
|
||||||
|
{
|
||||||
|
using namespace jwt::params;
|
||||||
|
jwt::jwt_object obj(payload({
|
||||||
|
{"a", "b"},
|
||||||
|
{"c", "d"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
basic_jwt_object_test();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue