From 16f10af4f1fbf8c21d127d2163c3ace9611cbb91 Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Sat, 4 Aug 2018 18:03:07 +0200 Subject: Working on player accounts... --- src/shared/struct/shr_player.erl | 202 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 src/shared/struct/shr_player.erl (limited to 'src/shared/struct') diff --git a/src/shared/struct/shr_player.erl b/src/shared/struct/shr_player.erl new file mode 100644 index 0000000..b036cb6 --- /dev/null +++ b/src/shared/struct/shr_player.erl @@ -0,0 +1,202 @@ +-module(shr_player). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-type id() :: binary(). + +-record +( + player, + { + id :: id(), + username :: binary(), + % {salt(crypto:strong_rand_bytes(128)), hash(sha384)} + password :: {binary(), binary()}, + token :: binary(), % salt(crypto:strong_rand_bytes(512)) + email :: binary(), + last_active :: integer(), + maps :: list(binary()), + characters :: list(binary()) + } +). + +-opaque type() :: #player{}. + +-export_type([type/0, id/0]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( + [ + new/3 + ] +). + +%%%% Accessors +-export +( + [ + get_id/1, + get_username/1, + get_password/1, + get_token/1, + get_email/1, + get_last_active/1, + get_maps/1, + get_characters/1, + + set_username/2, + set_password/2, + new_token/1, + set_email/2, + refresh_active/1, + set_maps/2, + set_characters/2 + ] +). + +-export +( + [ + get_id_field/0, + get_username_field/0, + get_password_field/0, + get_token_field/0, + get_email_field/0, + get_last_active_field/0, + get_maps_field/0, + get_characters_field/0 + ] +). + +-export +( + [ + password_is/2 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec secure_value (binary(), binary()) -> binary(). +secure_value (Salt, Val) -> + SaltedVal = erlang:iolist_to_binary([Salt, Val]), + HashedSaltedVal = crypto:hash(sha384, SaltedVal), + + HashedSaltedVal. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec new (binary(), binary(), binary()) -> type(). +new (ID, Username, Password) -> + Result = + #player + { + id = ID, + username = Username, + password = {<<"">>, <<"">>}, + token = <<"">>, + email = <<"">>, + last_active = 0, + maps = [], + characters = [] + }, + + S0Result = set_password(Password, Result), + S1Result = new_token(S0Result), + S2Result = refresh_active(S1Result), + + S2Result. + +%%%% Accessors +-spec get_id (type()) -> id(). +get_id (Player) -> Player#player.id. + +-spec get_username (type()) -> binary(). +get_username (Player) -> Player#player.username. + +-spec get_password (type()) -> {binary(), binary()}. +get_password (Player) -> Player#player.password. + +-spec get_token (type()) -> binary(). +get_token (Player) -> Player#player.token. + +-spec get_email (type()) -> binary(). +get_email (Player) -> Player#player.email. + +-spec get_last_active (type()) -> integer(). +get_last_active (Player) -> Player#player.last_active. + +-spec get_maps (type()) -> list(binary()). +get_maps (Player) -> Player#player.maps. + +-spec get_characters (type()) -> list(binary()). +get_characters (Player) -> Player#player.characters. + +-spec set_username (binary(), type()) -> type(). +set_username (Val, Player) -> Player#player{ username = Val }. + +-spec set_password (binary(), type()) -> type(). +set_password (Val, Player) -> + NewSalt = crypto:strong_rand_bytes(128), + HashedSaltedVal = secure_value(NewSalt, Val), + + Player#player + { + password = {NewSalt, HashedSaltedVal} + }. + +-spec new_token (type()) -> type(). +new_token (Player) -> Player#player{ token = crypto:strong_rand_bytes(512) }. + +-spec set_email (binary(), type()) -> type(). +set_email (Val, Player) -> Player#player{ email = Val }. + +-spec refresh_active (type()) -> type(). +refresh_active (Player) -> + Player#player + { + last_active = erlang:system_time(second) + }. + +-spec set_maps (list(binary()), type()) -> type(). +set_maps (Maps, Player) -> Player#player{ maps = Maps }. + +-spec set_characters (list(binary()), type()) -> type(). +set_characters (Characters, Player) -> Player#player{ characters = Characters }. + +-spec get_id_field () -> non_neg_integer(). +get_id_field () -> #player.id. + +-spec get_username_field () -> non_neg_integer(). +get_username_field () -> #player.username. + +-spec get_password_field () -> non_neg_integer(). +get_password_field () -> #player.password. + +-spec get_token_field () -> non_neg_integer(). +get_token_field () -> #player.token. + +-spec get_email_field () -> non_neg_integer(). +get_email_field () -> #player.email. + +-spec get_last_active_field () -> non_neg_integer(). +get_last_active_field () -> #player.last_active. + +-spec get_maps_field () -> non_neg_integer(). +get_maps_field () -> #player.maps. + +-spec get_characters_field () -> non_neg_integer(). +get_characters_field () -> #player.characters. + +-spec password_is (binary(), type()) -> boolean(). +password_is (Val, Player) -> + {Salt, HashedSaltedVal} = Player#player.password, + HashedSaltedCandidate = secure_value(Salt, Val), + + (HashedSaltedCandidate == HashedSaltedVal). -- cgit v1.2.3-70-g09d2