Skip to content

Instantly share code, notes, and snippets.

@m-2k m-2k/join.erl Secret
Last active Sep 13, 2015

Embed
What would you like to do?
%% {gen_smtp,".*", {git, "git://github.com/Vagabond/gen_smtp", {tag, "master"} }},
-define(UNDEF,undefined).
-define(M,?MODULE).
-define(USER_ACTIVATION,activation).
render() ->
#button{body= <<"Send me invite">>,postback=#render_event{event=join},source=[email]}.
event(#render_event{event=join}) ->
Email=wf:q(email),
case email_validation(Email) of
{true,Email2} ->
case wf:cache({?USER_ACTIVATION,Email}) of
?UNDEF ->
case kvs:get(user3,Email2) of
{ok,#user3{}} ->
wf:warning(?M,"User already joined ~p",[Email2]);
_ ->
wf:info(?M,"Sending mail to: ~p",[Email2]),
try
{ok,Unique,PasswordHash,Salt}=gen_pass_and_send_email(Email2),
Till=n2o_session:till(calendar:local_time(),86400),
wf:cache({?USER_ACTIVATION,Unique},{Email2,PasswordHash,Salt},Till),
wf:cache({?USER_ACTIVATION,Email2},Unique,Till),
wf:info(?M,"Sending mail to: ~p [OK]",[Email2])
catch
T:E ->
wf:error(?M,"Sending mail to: ~p FAIL, ~p:~p",[Email2,T,E])
end
end;
_ ->
wf:warning(?M,"Wait for activation from: ~p",[Email2])
end;
{false,Email2} ->
wf:warning(?M,"Wrong mail for register: ~p",[Email2])
end, ok;
gen_pass_and_send_email(Email) ->
Password=password(),
Salt=salt(),
PasswordHash=password_hash(Password,Salt),
Subject= <<>>,
From=smtp_gmail_login(),
To=Email,
Unique=random_bin(join_auth_key_length()),
Key=wf:hex_encode(Unique),
Link= <<"http://",(domain())/binary,"/",(urn())/binary,"/",Key/binary>>,
Body= <<"<h1>Thanks you for registering</h1>
<p>You login: ",(wf:html_encode(Email))/binary,"</p>
<p>You password: ",(wf:html_encode(Password))/binary,"</p>
<p>Click this link to activate your account: <a href=\"",Link/binary,"\">Link</a></p><p></p>">>,
Mail={<<"text">>,<<"html">>,[{<<"From">>,From},{<<"To">>,To},{<<"Subject">>,Subject}],[],Body},
gen_smtp_client:send({smtp_gmail_login(), [Email], mimemail:encode(Mail)},
[{relay, "smtp.gmail.com"},{tls, always},
{username, smtp_gmail_login()},
{password, smtp_gmail_password()}]),
{ok,Unique,PasswordHash,Salt}.
re(mail) -> {ok,Re}=re:compile(<<"^[a-z0-9._%+-]{1,24}@[a-z0-9-]{2,16}\\.[a-z]{2,4}$">>),Re.
re_compiled(mail) ->
{re_pattern,0,0,0,
<<69,82,67,80,191,0,0,0,16,0,0,0,65,0,0,0,255,255,255,
255,255,255,255,255,0,0,46,0,0,0,0,0,0,0,64,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,0,
123,25,106,0,0,0,0,32,104,255,3,0,0,0,128,254,255,255,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,104,0,1,0,24,29,64,
106,0,0,0,0,0,32,255,3,0,0,0,0,254,255,255,7,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,104,0,2,0,16,29,46,106,0,0,0,0,0,
0,0,0,0,0,0,0,254,255,255,7,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,104,0,2,0,4,27,114,0,123,0>>}.
email_validation(Email) when is_binary(Email) ->
Email2=list_to_binary(string:to_lower(binary_to_list(strip(Email)))),
case re:run(Email2,re_compiled(mail)) of
{match,_} -> {true,Email2};
_ -> {false,Email2}
end.
verify_activation_link(Key) -> % joining from emai link
Unique=wf:hex_decode(Key),
case wf:cache({?USER_ACTIVATION,Unique}) of
?UNDEF -> {error,expire_or_not_exist};
{Email,PasswordHash,Salt} ->
{ok,#user3{id=Uid}}=kvs:add(#user3{id=Email,email=Email,
name=hd(binary:split(Email,<<"@">>)),password=PasswordHash,salt=Salt}),
wf:cache({?USER_ACTIVATION,Unique},?UNDEF), % clear
wf:cache({?USER_ACTIVATION,Email},?UNDEF), % clear
{ok,Uid}
end.
%%% Utils
strip(Bin) -> re:replace(Bin, <<"(^\\s+)|(\\s+$)">>, <<>>, [global,{return,binary}]).
password_hash(Pass,Salt) ->
SaltLocal=salt_local(),
case hash_delay() of D when is_integer(D) andalso D > 0 -> timer:sleep(D); _ -> ok end,
crypto:hash(hash_algorithm(),<<Pass/binary,Salt/binary,SaltLocal/binary>>).
randomize() -> {A1,A2,A3}=now(), random:seed(A1,A2,A3).
salt() -> randomize(), crypto:strong_rand_bytes(salt_length()).
password() ->
randomize(),
Allowed=password_chars_allowed(),Count=size(Allowed)-1,
<< << (binary:at(Allowed,random:uniform(Count))) >> || _ <- lists:seq(1,password_length()) >>.
random_hex(Length) -> randomize(), wf_convert:hex(crypto:strong_rand_bytes(Length)).
random_bin(Length) -> randomize(), crypto:strong_rand_bytes(Length).
%%% Config
smtp_gmail_login() -> <<>>.
smtp_gmail_password() -> <<>>.
domain() -> <<"localhost:8000">>.
password_length() -> 16.
password_chars_allowed() -> <<"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789">>.
hash_algorithm() -> sha512.
hash_delay() -> 10.
salt_length() -> 4.
salt_local() -> <<0,1,2,3>>.
join_auth_key_length() -> 24.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.