-module(foodog_gen).
-export([jti/2, exp/2, iss/2, sub_jwk/2, token/2]).
-spec jti(map(), integer()) -> map().
jti(Payload, N) ->
Payload#{<<"jti">> => do_random_num(N)}.
-spec do_random_num(integer()) -> binary().
do_random_num(N) ->
integer_to_binary(rand:uniform(N)).
-spec exp(map(),
{seconds | minutes | hours | days | weeks | months | years, integer()}) ->
map().
exp(Payload, Option) ->
Payload#{<<"exp">> => do_exp(Option)}.
-spec do_exp({seconds | minutes | hours | days | weeks | months | years, integer()}) ->
integer().
do_exp({seconds, N}) ->
erlang:system_time(seconds) + N;
do_exp({minutes, N}) ->
erlang:system_time(seconds) + N * 60;
do_exp({hours, N}) ->
erlang:system_time(seconds) + N * 60 * 60;
do_exp({days, N}) ->
erlang:system_time(seconds) + N * 60 * 60 * 24;
do_exp({weeks, N}) ->
erlang:system_time(seconds) + N * 60 * 60 * 24 * 7;
do_exp({months, N}) ->
erlang:system_time(seconds) + N * 60 * 60 * 24 * 7 * 4;
do_exp({years, N}) ->
erlang:system_time(seconds) + N * 60 * 60 * 24 * 365;
do_exp(N) ->
N.
-spec iss(map(), binary()) -> map().
iss(Payload, Issuer) ->
Payload#{<<"iss">> => Issuer}.
-spec sub_jwk(map(), binary()) -> map().
sub_jwk(Payload, KeyId) ->
Payload#{<<"sub_jwk">> => KeyId}.
-spec token(map(), binary()) -> {ok, binary()} | {error, any()}.
token(Payload, Key) ->
try jose_jwt:sign(
foodog_util:binary_to_key(Key), #{<<"alg">> => <<"HS256">>}, Payload)
of
Signed ->
{_, Result} = jose_jws:compact(Signed),
{ok, Result}
catch
Err ->
{error, Err}
end.
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
jti_test() ->
#{<<"jti">> := Jti} = jti(#{}, 10),
?assert(is_binary(Jti)).
exp_test() ->
#{<<"exp">> := Exp0} = exp(#{}, {seconds, 1}),
?assert(is_integer(Exp0)),
#{<<"exp">> := Exp1} = exp(#{}, {minutes, 1}),
?assert(is_integer(Exp1)),
#{<<"exp">> := Exp2} = exp(#{}, {hours, 1}),
?assert(is_integer(Exp2)),
#{<<"exp">> := Exp3} = exp(#{}, {days, 1}),
?assert(is_integer(Exp3)),
#{<<"exp">> := Exp4} = exp(#{}, {weeks, 1}),
?assert(is_integer(Exp4)),
#{<<"exp">> := Exp5} = exp(#{}, {months, 1}),
?assert(is_integer(Exp5)),
#{<<"exp">> := Exp6} = exp(#{}, {years, 1}),
?assert(is_integer(Exp6)).
iss_test() ->
#{<<"iss">> := Issuer} = iss(#{}, <<"example.com">>),
?assertEqual(<<"example.com">>, Issuer).
sub_jwk_test() ->
#{<<"sub_jwk">> := Key} = sub_jwk(#{}, <<"123456789">>),
?assertEqual(<<"123456789">>, Key).
token_test() ->
{ok, Token} = token(#{<<"foobar">> => <<"barfoo">>}, <<"123456789">>),
?assert(is_binary(Token)).
-endif.