Namdak Tonpa 9 лет назад
Родитель
Сommit
bc5598a114
14 измененных файлов с 77 добавлено и 99 удалено
  1. 2 1
      README.md
  2. 0 3
      priv/facebook_sdk.dtl
  3. 1 1
      priv/microsoft_sdk.dtl
  4. 3 2
      rebar.config
  5. 1 1
      src/avz.app.src
  6. 18 12
      src/avz.erl
  7. 1 3
      src/avz_sup.erl
  8. 0 21
      src/avz_userhelper.erl
  9. 4 4
      src/email.erl
  10. 11 12
      src/facebook.erl
  11. 11 11
      src/github.erl
  12. 8 8
      src/google.erl
  13. 7 10
      src/microsoft.erl
  14. 10 10
      src/twitter.erl

+ 2 - 1
README.md

@@ -23,7 +23,7 @@ API
     api_event/3          % Page Event for JavaScript based login methods
     callback/0           % Callback part of HTTP redirect based login methods
     registration_data/3  % Process Parameters
-    
+
 Usage
 -----
 
@@ -34,6 +34,7 @@ Credits
 -------
 
 * Andrii Zadorozhnii
+* Andrii Sergiienko
 * Maxim Sokhatsky
 
 OM A HUM

+ 0 - 3
priv/facebook_sdk.dtl

@@ -3,12 +3,9 @@ window.fbAsyncInit = function() {
   FB.init({ appId: '{{appid}}', channelUrl: ' {{channelUrl}}', status: true, cookie: true, xfbml: true, oauth: true });
 
   FB.getLoginStatus(function(response) {
-//    if(setFbIframe){
       var inIframe= top!=self;
-  //    setFbIframe(inIframe);
       if(inIframe && response.status == 'connected' && fbLogin)
         FB.api("/me?fields=id,first_name,last_name,email,birthday,cover", function(response){ fbLogin(response);});
-  //  }
   });
 };
 

+ 1 - 1
priv/microsoft_sdk.dtl

@@ -44,7 +44,7 @@ function onLogin() {
         console.log("{{event}}");
     }
 }
- 
+
 function onSessionChange() {
     var session = WL.getSession();
     if (session) {

+ 3 - 2
rebar.config

@@ -1,7 +1,8 @@
+{lib_dirs, ["deps",".."]}.
 {deps_dir, ["deps"]}.
 {deps, [
-    {n2o,           ".*", {git, "git://github.com/5HT/n2o", {tag,"2.1"}}},
-    {kvs,           ".*", {git, "git://github.com/synrc/kvs", {tag,"master"}}},
+    {n2o,           ".*", {git, "git://github.com/synrc/n2o", {tag,"2.8"}}},
+    {kvs,           ".*", {git, "git://github.com/synrc/kvs", {tag,"2.8"}}},
     {erlydtl,       ".*", {git, "git://github.com/evanmiller/erlydtl.git", {tag,"0.8.0"}}}
 ]}.
 {erlydtl_opts, [

+ 1 - 1
src/avz.app.src

@@ -1,7 +1,7 @@
 {application, avz,
  [
   {description, "AVZ VXZ Token System"},
-  {vsn, "1.5.0"},
+  {vsn, "2.8"},
   {registered, []},
   {applications, [kernel, stdlib]},
   {mod, { avz_app, []}},

+ 18 - 12
src/avz.erl

@@ -5,31 +5,35 @@
 -include_lib("n2o/include/wf.hrl").
 -include_lib("kvs/include/user.hrl").
 
-callbacks(Methods) -> [ M:callback() || M <- Methods].
-sdk(Methods) -> [ M:sdk() || M <- Methods].
-buttons(Methods) -> [ M:login_button() || M <- Methods].
+sha(Pass) -> crypto:hmac(wf:config(n2o,hmac,sha256),n2o_secret:secret(),wf:to_binary(Pass)).
+update({K,V},P) -> wf:setkey(K,1,case P of undefined -> []; _P -> _P end,{K,V}).
+
+coalesce(undefined,Y) -> Y;
+coalesce(X,        _) -> X.
+
+merge(A,B) -> list_to_tuple([ coalesce(X,Y) || {X,Y} <- lists:zip(tuple_to_list(A),tuple_to_list(B)) ]).
+
+callbacks(Methods) -> [ M:callback()     || M <- Methods].
+sdk(Methods)       -> [ M:sdk()          || M <- Methods].
+buttons(Methods)   -> [ M:login_button() || M <- Methods].
 
 event(init) -> [];
 event(logout) -> wf:user(undefined), wf:redirect(?LOGIN_PAGE);
 event(to_login) -> wf:redirect(?LOGIN_PAGE);
 event({register, #user{}=U}) -> kvs:add(U), login_user(U); % sample
-event({login, #user{}=U, N}) ->
-    Updated = avz_userhelper:updateUser(U,N),
-    kvs:put(Updated),
-    login_user(Updated);                % sample
+event({login, #user{}=U, N}) -> Updated = merge(U,N), kvs:put(Updated), login_user(Updated); % sample
 event({Method,Event}) -> Method:event({Method,Event});
-event(Ev) ->  error_logger:info_msg("Page Event ~p",[Ev]).
+event(Ev) ->  wf:info(?MODULE,"Page Event ~p",[Ev]).
 
 api_event(plusLogin, Args, Term) -> google:api_event(plusLogin, Args, Term);
 api_event(fbLogin, Args, Term)   -> facebook:api_event(fbLogin, Args, Term);
 api_event(winLogin, Args, Term)  -> microsoft:api_event(winLogin, Args, Term);
-api_event(Name, Args, Term)      -> error_logger:info_msg("Unknown API event: ~p ~p ~p",[Name, Args, Term]).
+api_event(Name, Args, Term)      -> wf:info(?MODULE,"Unknown API event: ~p ~p ~p",[Name, Args, Term]).
 
 login_user(User) -> wf:user(User), wf:redirect(?AFTER_LOGIN).
-login(_Key, [{error, E}|_Rest])-> error_logger:info_msg("oauth error: ~p", [E]);
+login(_Key, [{error, E}|_Rest])-> wf:info(?MODULE,"Auth Error: ~p", [E]);
 login(Key, Args) ->
     n2o_session:ensure_sid([],?CTX,[]),
-    wf:info("AVZ MODULE: ~p",[?CTX#cx.module]),
     case kvs:get(user,Key:email_prop(Args,Key)) of
         {ok,Existed} ->
             RegData = Key:registration_data(Args, Key, Existed),
@@ -37,4 +41,6 @@ login(Key, Args) ->
         {error,_} ->
             RegData = Key:registration_data(Args, Key, #user{}),
             (?CTX#cx.module):event({register, RegData});
-        U -> wf:info("avz:login unknown: ~p",[U]) end.
+        U -> wf:info(?MODULE,"Unknown Login: ~p",[U]) end.
+
+version() -> proplists:get_value(vsn,element(2,application:get_all_key(?MODULE))).

+ 1 - 3
src/avz_sup.erl

@@ -5,7 +5,5 @@
 -include_lib ("avz/include/avz.hrl").
 
 start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-
-init([]) ->
-    {ok, {{one_for_one, 5, 10}, []}}.
+init([]) -> {ok, {{one_for_one, 5, 10}, []}}.
 

+ 0 - 21
src/avz_userhelper.erl

@@ -1,21 +0,0 @@
--module(avz_userhelper).
--export([updateProplist/2,updateUser/2]).
-
--include_lib("kvs/include/user.hrl").
-
-updateProplist({K,V},P) ->
-    Prop = case P of undefined -> []; _P -> _P end,
-    case proplists:get_value(K,Prop) of
-        undefined -> [{K,V} | Prop];
-	        _ -> lists:keyreplace(K,1,Prop,{K,V})
-    end.
-
-updateUser(E,N) ->
-    Username = case E#user.username of undefined -> N#user.username; _ -> E#user.username end,
-    Tokens = N#user.tokens,
-    Images = N#user.images,
-    Names = case E#user.names of undefined -> N#user.names; _ -> E#user.names end,
-    Surnames = case E#user.surnames of undefined -> N#user.surnames; _ -> E#user.surnames end,
-    Birth = case E#user.birth of undefined -> N#user.birth; _ -> E#user.birth end,
-    Sex = case E#user.sex of undefined -> N#user.sex; _ -> E#user.sex end,
-    E#user{username=Username,tokens=Tokens,images=Images,names=Names,surnames=Surnames,birth=Birth,sex=Sex}.

+ 4 - 4
src/email.erl

@@ -11,14 +11,14 @@ registration_data(Props, email, Ori)->
   Ori#user{ id = Email,
             display_name = Email,
             email = Email,
-            register_date = now(),
-            tokens = avz_userhelper:updateProplist({email,Email},Ori#user.tokens),
+            register_date = os:timestamp(),
+            tokens = avz:update({email,Email},Ori#user.tokens),
             status = ok,
-            password = kvs:sha(proplists:get_value(<<"password">>,Props))}.
+            password = avz:sha(proplists:get_value(<<"password">>,Props))}.
 
 email_prop(Props, _) -> binary_to_list(proplists:get_value(<<"email">>, Props)).
 
-login_button() -> #button{id=login, class=[btn, "btn-info", "btn-large", "btn-lg"], body= <<"Sign in">>, postback={email, loginemail}, source=[user,pass]}.
+login_button() -> application:get_env(avz,email_button,#button{id=login, class=[btn, "btn-info", "btn-large", "btn-lg"], body= <<"Sign in">>, postback={email, loginemail}, source=[user,pass]}).
 event({email,loginemail}) -> avz:login(email, [{<<"email">>, list_to_binary(wf:q(user))}, {<<"password">>, wf:q(pass)}]);
 event(_) -> ok.
 api_event(_,_,_) -> ok.

+ 11 - 12
src/facebook.erl

@@ -8,41 +8,40 @@
 -compile(export_all).
 -export(?API).
 
--define(HTTP_ADDRESS, case application:get_env(web, http_address) of {ok, A} -> A; _ -> "" end).
--define(FB_APP_ID, case application:get_env(web, fb_id) of {ok, Id} -> Id; _-> "" end).
--define(FB_BTN_CLASS, case application:get_env(web, fb_btn_class) of {ok, C} -> C; _ -> "btn-primary btn-large btn-lg" end).
--define(FB_BTN_BODY, case application:get_env(web,fb_btn_body) of {ok, _FBBTNBODY} -> _FBBTNBODY; _ -> [#i{class=[fa,"fa-facebook","fa-lg","icon-facebook","icon-large"]}, <<"Facebook">>] end).
+-define(HTTP_ADDRESS, application:get_env(web, http_address, [])).
+-define(FB_APP_ID,    application:get_env(web, fb_id,        [])).
 
 callback() -> ok.
 event({facebook,_Event}) -> wf:wire("fb_login();"), ok.
-api_event(fbLogin, Args, _Term)-> JSArgs = n2o_json:decode(Args), avz:login(facebook, JSArgs#struct.lst).
+api_event(fbLogin, Args, _Term) -> JSArgs = n2o_json:decode(Args), avz:login(facebook, JSArgs#struct.lst).
 
 registration_data(Props, facebook, Ori)->
     Id = proplists:get_value(<<"id">>, Props),
     BirthDay = case proplists:get_value(<<"birthday">>, Props) of
         undefined -> {1, 1, 1970};
         BD -> list_to_tuple([list_to_integer(X) || X <- string:tokens(binary_to_list(BD), "/")]) end,
-%    error_logger:info_msg("User Ori: ~p",[Ori]),
-%    error_logger:info_msg("Props: ~p",[Props]),
     Email = email_prop(Props, facebook),
     [UserName|_] = string:tokens(binary_to_list(Email),"@"),
     Cover = case proplists:get_value(<<"cover">>,Props) of undefined -> ""; P -> case proplists:get_value(<<"source">>,P#struct.lst) of undefined -> ""; C -> binary_to_list(C) end end,
     Ori#user{   id = Email,
                 display_name = UserName,
-                images = avz_userhelper:updateProplist({fb_cover,Cover},avz_userhelper:updateProplist({fb_avatar,"https://graph.facebook.com/" ++ binary_to_list(Id) ++ "/picture?type=large"},Ori#user.images)),
+                images = avz:update({fb_cover,Cover},avz:update({fb_avatar,"https://graph.facebook.com/" ++ binary_to_list(Id) ++ "/picture?type=large"},Ori#user.images)),
                 email = Email,
                 names = proplists:get_value(<<"first_name">>, Props),
                 surnames = proplists:get_value(<<"last_name">>, Props),
-                tokens = avz_userhelper:updateProplist({facebook,Id},Ori#user.tokens),
+                tokens = avz:merge({facebook,Id},Ori#user.tokens),
                 birth = {element(3, BirthDay), element(1, BirthDay), element(2, BirthDay)},
-                register_date = erlang:now(),
+                register_date = os:timestamp(),
                 status = ok }.
 
 email_prop(Props, _) ->
     proplists:get_value(<<"email">>, Props).
 
-login_button() ->
-    #panel{class=["btn-group"], body=#link{id=loginfb, class=[?FB_BTN_CLASS],body=?FB_BTN_BODY, postback={facebook,loginClick} }}.
+login_button() -> application:get_env(avz,facebook_button,
+    #panel{class=["btn-group"], body=#link{id=loginfb,
+                  class=["btn-primary btn-large btn-lg"],
+                  body=[#i{class=[fa,"fa-facebook","fa-lg","icon-facebook","icon-large"]},
+                        <<"Facebook">>], postback={facebook,loginClick} }}).
 
 sdk() ->
     wf:wire(#api{name=setFbIframe, tag=fb}),

+ 11 - 11
src/github.erl

@@ -6,13 +6,13 @@
 -compile(export_all).
 -export(?API).
 
--define(CLIENT_ID, case application:get_env(web, github_client_id) of {ok, K} -> K;_-> "" end).
--define(CLIENT_SECRET, case application:get_env(web, github_client_secret) of {ok, S} -> S; _-> "" end).
--define(OAUTH_URI, "https://github.com/login/oauth").
--define(AUTHORIZE_URI, ?OAUTH_URI ++ "/authorize").
+-define(CLIENT_ID,        application:get_env(web, github_client_id,     [])).
+-define(CLIENT_SECRET,    application:get_env(web, github_client_secret, [])).
+-define(OAUTH_URI,        "https://github.com/login/oauth").
+-define(AUTHORIZE_URI,    ?OAUTH_URI ++ "/authorize").
 -define(ACCESS_TOKEN_URI, ?OAUTH_URI ++ "/access_token").
--define(API_URI, "https://api.github.com").
--define(REQ_HEADER, [{"User-Agent", "Erlang PaaS"}]).
+-define(API_URI,          "https://api.github.com").
+-define(REQ_HEADER,       [{"User-Agent", "Erlang PaaS"}]).
 
 user(Props) -> api_call("/user", Props).
 
@@ -54,12 +54,12 @@ registration_data(Props, github, Ori) ->
     Ori#user{   id= Email,
                 username = binary_to_list(proplists:get_value(<<"login">>, Props)),
                 display_name = Name,
-                images = avz_userhelper:updateProplist({gh_avatar,proplists:get_value(<<"avatar_url">>, Props)},Ori#user.images),
+                images = avz:update({gh_avatar,proplists:get_value(<<"avatar_url">>, Props)},Ori#user.images),
                 email = Email,
                 names  = Name,
                 surnames = [],
-                tokens = avz_userhelper:updateProplist({github,Id},Ori#user.tokens),
-                register_date = erlang:now(),
+                tokens = avz:update({github,Id},Ori#user.tokens),
+                register_date = os:timestamp(),
                 status = ok }.
 
 email_prop(Props, github) ->
@@ -70,9 +70,9 @@ email_prop(Props, github) ->
         false -> binary_to_list(proplists:get_value(<<"login">>, Props)) ++ "@github"
     end.
 
-login_button() -> #panel{ class=["btn-group"], body=
+login_button() -> application:get_env(avz,github_button,#panel{ class=["btn-group"], body=
     #link{id=github_btn, class=[btn, "btn-large"], 
-        body=[#i{class=["icon-github", "icon-large"]}, <<"Github">>], postback={github,logingithub} }}.
+        body=[#i{class=["icon-github", "icon-large"]}, <<"Github">>], postback={github,logingithub} }}).
 
 api_event(_,_,_) -> ok.
 event({github,logingithub}) -> wf:redirect(github:authorize_url()).

+ 8 - 8
src/google.erl

@@ -5,34 +5,34 @@
 -include_lib("kvs/include/user.hrl").
 -compile(export_all).
 -export(?API).
--define(GPLUS_CLIENT_ID, case application:get_env(web, gplus_client_id) of {ok, Id} -> Id; _-> "" end).
--define(GPLUS_COOKIE_POLICY, case application:get_env(web, gplus_cookiepolicy) of {ok, P} -> P; _-> "" end).
+-define(GPLUS_CLIENT_ID,     application:get_env(web, gplus_client_id,    [])).
+-define(GPLUS_COOKIE_POLICY, application:get_env(web, gplus_cookiepolicy, [])).
 
 api_event(plusLogin, Args, _)-> JSArgs = n2o_json:decode(Args), avz:login(google, JSArgs#struct.lst).
 
 registration_data(Props, google, Ori)->
     Id = proplists:get_value(<<"id">>, Props),
-    Name = proplists:get_value(<<"name">>, Props),
+    _Name = proplists:get_value(<<"name">>, Props),
     Image = proplists:get_value(<<"picture">>, Props),
     GivenName = proplists:get_value(<<"given_name">>, Props),
     FamilyName = proplists:get_value(<<"family_name">>, Props),
     Email = email_prop(Props,google),
     Ori#user{   id = Email,
                 display_name = proplists:get_value(<<"displayName">>, Props),
-                images = avz_userhelper:updateProplist({google_avatar,Image},Ori#user.images),
+                images = avz:update({google_avatar,Image},Ori#user.images),
                 email = Email,
                 names = GivenName,
                 surnames = FamilyName,
-                tokens = avz_userhelper:updateProplist({google,Id},Ori#user.tokens),
-                register_date = erlang:now(),
+                tokens = avz:update({google,Id},Ori#user.tokens),
+                register_date = os:timestamp(),
                 sex = proplists:get_value(<<"gender">>, Props),
                 status = ok }.
 
 email_prop(Props, _) -> proplists:get_value(<<"email">>, Props).
 
-login_button()-> #panel{id=plusloginbtn, class=["btn-group"], body=
+login_button()-> application:get_env(avz,google_button,#panel{id=plusloginbtn, class=["btn-group"], body=
     #link{class=[btn, "btn-google-plus", "btn-large","btn-lg"],
-        body=[#i{class=[fa,"fa-google-plus","fa-lg","icon-google-plus", "icon-large"]}, <<"Google">>] }}.
+        body=[#i{class=[fa,"fa-google-plus","fa-lg","icon-google-plus", "icon-large"]}, <<"Google">>] }}).
 
 event(_) -> ok.
 callback() -> ok.

+ 7 - 10
src/microsoft.erl

@@ -5,23 +5,20 @@
 -include_lib("kvs/include/user.hrl").
 -compile(export_all).
 -export(?API).
--define(CLIENT_ID, "000000004C0FEEB0").
+-define(CLIENT_ID,    "000000004C0FEEB0").
 -define(REDIRECT_URI, "http://skyline.synrc.com:8000").
 
-api_event(_, Args, _)-> 
-    error_logger:info_msg("Args: ~p",[Args]),
+api_event(_, Args, _)->
     JSArgs = string:tokens(Args,"\\\\"),
     J = string:join(JSArgs,""),
-    error_logger:info_msg("J: ~p",[J]),
     [_|K1] = J,
     [_|K2] = lists:reverse(K1),
     K = lists:reverse(K2),
-    error_logger:info_msg("K: ~p",[K]),
     Struct = n2o_json:decode(K),
     avz:login(microsoft, Struct#struct.lst).
 
 registration_data(Props, microsoft, Ori)->
-    error_logger:info_msg("Microsoft Login: ~p",[Props]),
+    wf:info(?MODULE,"Microsoft Login: ~p",[Props]),
     Id = proplists:get_value(<<"id">>, Props),
     GivenName = proplists:get_value(<<"first_name">>, Props),
     FamilyName = proplists:get_value(<<"last_name">>, Props),
@@ -31,17 +28,17 @@ registration_data(Props, microsoft, Ori)->
                 email = Email,
                 names = GivenName,
                 surnames = FamilyName,
-                tokens = avz_userhelper:updateProplist({microsoft,Id},Ori#user.tokens),
-                register_date = erlang:now(),
+                tokens = avz:update({microsoft,Id},Ori#user.tokens),
+                register_date = os:timestamp(),
                 sex = proplists:get_value(<<"gender">>, Props),
                 status = ok }.
 
 email_prop(Props, _) -> proplists:get_value(<<"id">>, Props).
 
-login_button()-> #panel{class=["btn-group"], body=
+login_button()-> application:get_env(avz,microsoft_button,#panel{class=["btn-group"], body=
     #link{id=microsoftbtn, class=[btn, "btn-microsoft", "btn-large"], 
         body=[#i{class=["icon-microsoft", "icon-large"]}, <<"Microsoft">>],
-              actions= "$('#microsoftbtn').on('click', microsoft_login);" }}.
+              actions= "$('#microsoftbtn').on('click', microsoft_login);" }}).
 
 event(_) -> ok.
 callback() -> ok.

+ 10 - 10
src/twitter.erl

@@ -5,9 +5,9 @@
 -include_lib("kvs/include/user.hrl").
 -compile(export_all).
 -export(?API).
--define(CONSUMER_KEY, case application:get_env(web, tw_consumer_key) of {ok, K} -> K;_-> "" end).
--define(CONSUMER_SECRET, case application:get_env(web, tw_consumer_secret) of {ok, S} -> S; _-> "" end).
--define(CONSUMER, {?CONSUMER_KEY, ?CONSUMER_SECRET, hmac_sha1}).
+-define(CONSUMER_KEY,    application:get_env(web, tw_consumer_key,    [])).
+-define(CONSUMER_SECRET, application:get_env(web, tw_consumer_secret, [])).
+-define(CONSUMER,        {?CONSUMER_KEY, ?CONSUMER_SECRET, hmac_sha1}).
 
 registration_data(Props, twitter, Ori)->
     Id = proplists:get_value(<<"id_str">>, Props),
@@ -16,19 +16,19 @@ registration_data(Props, twitter, Ori)->
     Ori#user{   id = Email,
                 username = re:replace(UserName, "\\.", "_", [{return, list}]),
                 display_name = proplists:get_value(<<"screen_name">>, Props),
-                images = avz_userhelper:updateProplist({tw_avatar,proplists:get_value(<<"profile_image_url">>, Props)},Ori#user.images),
+                images = avz:update({tw_avatar,proplists:get_value(<<"profile_image_url">>, Props)},Ori#user.images),
                 names = proplists:get_value(<<"name">>, Props),
                 email = Email,
                 surnames = [],
-                tokens = avz_userhelper:updateProplist({twitter,Id},Ori#user.tokens),
-                register_date = erlang:now(),
+                tokens = avz:update({twitter,Id},Ori#user.tokens),
+                register_date = os:timestamp(),
                 status = ok }.
 
 email_prop(Props, twitter) -> proplists:get_value(<<"screen_name">>, Props).
 
 callback() ->
     Token = wf:q(<<"oauth_token">>),
-    Verifier =wf:q(<<"oauth_verifier">>),
+    Verifier = wf:q(<<"oauth_verifier">>),
     case wf:user() of
          undefined ->
              if (Token /= undefined) andalso ( Verifier/= undefined) ->
@@ -38,17 +38,17 @@ callback() ->
                  true -> skip  end;
          _ -> skip end.
 
-login_button() -> #panel{class=["btn-group"], body=
+login_button() -> application:get_env(avz,twitter_button,#panel{class=["btn-group"], body=
     #link{id=twlogin, class=[btn, "btn-info", "btn-large", "btn-lg"],
         body=[#i{class=[fa,"fa-twitter","fa-lg","icon-twitter", "icon-large"]}, <<"Twitter">>],
-        postback={twitter,logintwitter}}}.
+        postback={twitter,logintwitter}}}).
 
 sdk() -> [].
 api_event(_,_,_) -> ok.
 event({twitter,logintwitter}) ->
     case get_request_token() of
          {RequestToken, _, _} -> wf:redirect(authenticate_url(RequestToken));
-         {error, R} -> error_logger:info_msg("Twitter request failed:", [R]), [] end.
+         {error, R} -> wf:info(?MODULE, "Twitter request failed:", [R]), [] end.
 
 get_request_token()->
   URL = "https://api.twitter.com/oauth/request_token",