Permalink
Browse files

import

  • Loading branch information...
0 parents commit c359662aefc1164ab01db9e58e4af0b0eb3945a1 @Joony committed May 13, 2009
Showing with 2,047 additions and 0 deletions.
  1. +17 −0 Emakefile
  2. +5 −0 Makefile
  3. +8 −0 include/config.inc
  4. 0 include/wf.inc
  5. +175 −0 src/db_users.erl
  6. +62 −0 src/db_utils.erl
  7. +13 −0 src/pages/web_index.erl
  8. +51 −0 src/pages/web_users_dashboard.erl
  9. +55 −0 src/pages/web_users_login.erl
  10. +94 −0 src/pages/web_users_register.erl
  11. +26 −0 src/string_utils.erl
  12. +39 −0 src/user_login_app.erl
  13. +11 −0 start.sh
  14. +82 −0 wwwroot/nitrogen/basic.css
  15. BIN wwwroot/nitrogen/black_bl.png
  16. BIN wwwroot/nitrogen/black_br.png
  17. BIN wwwroot/nitrogen/black_tl.png
  18. BIN wwwroot/nitrogen/black_tr.png
  19. BIN wwwroot/nitrogen/checkmark.png
  20. +143 −0 wwwroot/nitrogen/elements.css
  21. BIN wwwroot/nitrogen/flash_bg.png
  22. BIN wwwroot/nitrogen/gray_bl.png
  23. BIN wwwroot/nitrogen/gray_br.png
  24. BIN wwwroot/nitrogen/gray_tl.png
  25. BIN wwwroot/nitrogen/gray_tr.png
  26. +273 −0 wwwroot/nitrogen/jquery-ui.js
  27. BIN wwwroot/nitrogen/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png
  28. BIN wwwroot/nitrogen/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png
  29. BIN wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png
  30. BIN wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png
  31. BIN wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png
  32. BIN wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png
  33. BIN wwwroot/nitrogen/jquery-ui/images/ui-bg_glass_95_fef1ec_1x400.png
  34. BIN wwwroot/nitrogen/jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png
  35. BIN wwwroot/nitrogen/jquery-ui/images/ui-icons_222222_256x240.png
  36. BIN wwwroot/nitrogen/jquery-ui/images/ui-icons_2e83ff_256x240.png
  37. BIN wwwroot/nitrogen/jquery-ui/images/ui-icons_454545_256x240.png
  38. BIN wwwroot/nitrogen/jquery-ui/images/ui-icons_888888_256x240.png
  39. BIN wwwroot/nitrogen/jquery-ui/images/ui-icons_cd0a0a_256x240.png
  40. +405 −0 wwwroot/nitrogen/jquery-ui/jquery-ui.css
  41. +19 −0 wwwroot/nitrogen/jquery.js
  42. +4 −0 wwwroot/nitrogen/livevalidation.js
  43. +3 −0 wwwroot/nitrogen/nitrogen.css
  44. +460 −0 wwwroot/nitrogen/nitrogen.js
  45. +52 −0 wwwroot/nitrogen/reset.css
  46. BIN wwwroot/nitrogen/spinner.gif
  47. BIN wwwroot/nitrogen/spinner2.gif
  48. BIN wwwroot/nitrogen/white_bl.png
  49. BIN wwwroot/nitrogen/white_br.png
  50. BIN wwwroot/nitrogen/white_tl.png
  51. BIN wwwroot/nitrogen/white_tr.png
  52. +25 −0 wwwroot/productTemplate.html
  53. +25 −0 wwwroot/template.html
@@ -0,0 +1,17 @@
+{ './src/*', [
+ { i, "./include" },
+ { outdir, "./ebin" },
+ debug_info
+]}.
+
+{ './src/*/*', [
+ { i, "./include" },
+ { outdir, "./ebin" },
+ debug_info
+]}.
+
+{ './src/*/*/*', [
+ { i, "./include" },
+ { outdir, "./ebin" },
+ debug_info
+]}.
@@ -0,0 +1,5 @@
+compile:
+ erl -make
+
+clean:
+ rm -rf ./ebin/*.beam
@@ -0,0 +1,8 @@
+-ifndef(config_inc).
+-define(config_inc, ok).
+
+
+-record(users, { username, email_address, password, date_joined, last_logged_in, verified=false }).
+-record(verification_codes, { email_address, verification_code }).
+
+-endif.
No changes.
@@ -0,0 +1,175 @@
+%% Copyright 2009 Joony (jonathan.mcallister@gmail.com)
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% db_users.erl
+%%
+%% This module provides all the functions for dealing with users.
+%%
+
+-module(db_users).
+-include("wf.inc").
+-include("config.inc").
+-export([init/0, add_user/3, validate_user/2, delete_user/1, is_username_used/1, is_email_used/1, get_email_address/1, verify_email/2, update_verification_code/2, delete_verification_code/1]).
+
+-include_lib("stdlib/include/qlc.hrl").
+
+%%% initialize the database and tables
+init() ->
+ mnesia:start(),
+ mnesia:delete_table(verification_codes),
+ mnesia:create_table(verification_codes, [{attributes, record_info (fields, verification_codes)}, {disc_copies, [node()]}]),
+ mnesia:delete_table(users),
+ mnesia:create_table(users, [{attributes, record_info (fields, users)}, {disc_copies, [node()]}]),
+ mnesia:stop().
+
+%%% add the user to the users database
+add_user(Username, EmailAddress, Password) ->
+ <<PasswordDigest:160>> = crypto:sha(Password),
+ Code = string_utils:generate_random_string(32),
+ UsersRow = #users { username=Username, email_address=EmailAddress, password=PasswordDigest, date_joined=erlang:universaltime() },
+ VerificationCodeRow = #verification_codes { email_address=EmailAddress, verification_code=Code },
+ F = fun() ->
+ mnesia:write(UsersRow),
+ mnesia:write(VerificationCodeRow)
+ end,
+ case mnesia:transaction(F) of
+ {atomic, Val} ->
+ case validate_user(Username, Password) of
+ {valid, _ID} ->
+ ok;
+ {aborted, Reason} ->
+ io:format("Failed to login after registration. Reason: ~s~n", [Reason]),
+ {aborted, Reason}
+ end;
+ {aborted, Reason} ->
+ io:format ("Added user failed!~nReason: ~s~n", [Reason]),
+ {aborted, Reason}
+ end.
+
+validate_user(Username, Password) ->
+ <<PasswordDigest:160>> = crypto:sha(Password),
+ case db_utils:do (qlc:q ([X#users.username || X <- mnesia:table(users), check(X#users.username, X#users.email_address, Username), X#users.password == PasswordDigest])) of
+ fail ->
+ {aborted, "Not valid"};
+ Results ->
+ if length (Results) == 1 ->
+ %% update the last logged in time
+ case update_last_logged_in(Username) of
+ {atomic, ok} ->
+ {valid, hd(Results)};
+ {aborted, Val} ->
+ io:format("Error: Unable to update last_logged_in for user ~s~n", [Username]),
+ {aborted, "Not valid"}
+ end;
+ true ->
+ {aborted, "Not valid"}
+ end
+ end.
+
+update_last_logged_in(Username) ->
+ F = fun() ->
+ [E] = mnesia:read(users, Username, write),
+ Update = E#users{last_logged_in=erlang:universaltime()},
+ mnesia:write(Update)
+ end,
+ mnesia:transaction(F).
+
+delete_verification_code(EmailAddress) ->
+ F = fun() ->
+ mnesia:delete(verification_codes, EmailAddress, write)
+ end,
+ mnesia:transaction(F).
+
+delete_user(Username) ->
+ F = fun() ->
+ mnesia:delete(users, Username, write)
+ end,
+ mnesia:transaction(F).
+
+%% not implemented yet, but will be used for the forgot password process if the user has already requested a code.
+update_verification_code(EmailAddress) ->
+ update_verification_code(EmailAddress, "").
+
+update_verification_code(EmailAddress, Code) ->
+ F = fun() ->
+ [E] = mnesia:read(verification_codes, EmailAddress, write),
+ Update = E#verification_codes{verification_code=Code},
+ mnesia:write(Update)
+ end,
+ mnesia:transaction(F).
+
+%% result seems backwards compared to the name
+is_username_used(Username) ->
+ case db_utils:do(qlc:q ([X#users.username || X <- mnesia:table(users), string:equal(X#users.username, Username)])) of
+ aborted ->
+ false;
+ Results ->
+ if
+ length(Results) == 1 ->
+ false;
+ true ->
+ true
+ end
+ end.
+
+%%% result seems backwards compared to the name
+is_email_used(EmailAddress) ->
+ case db_utils:do(qlc:q ([X#users.email_address || X <- mnesia:table(users), string:equal(X#users.email_address, EmailAddress)])) of
+ aborted ->
+ false;
+ Results ->
+ if
+ length(Results) == 1 ->
+ false;
+ true ->
+ true
+ end
+ end.
+
+check(Username, EmailAddress, Input) ->
+ if
+ Username == Input ; EmailAddress == Input ->
+ true;
+ true ->
+ false
+ end.
+
+%%% Used to get the email address for Gravatar
+get_email_address(Username) ->
+ db_utils:do(qlc:q([X#users.email_address || X <- mnesia:table(users), X#users.username =:= Username])).
+
+
+verify_email(EmailAddress, Code) ->
+ F = fun() ->
+ Result = qlc:e(qlc:q([X#verification_codes.email_address || X <- mnesia:table(verification_codes), X#verification_codes.email_address =:= EmailAddress, X#verification_codes.verification_code =:= Code])),
+ io:format("Result: ~s, ~w~n", [Result, length(Result)]),
+ if
+ length(Result) == 1 ->
+ io:format("Found one result~n"),
+ mnesia:delete(verification_codes, EmailAddress, write),
+ [User] = qlc:e(qlc:q([X || X <- mnesia:table(users), X#users.email_address =:= EmailAddress])),
+ io:format("User: ~w~n", [User]),
+ UserUpdate = User#users{verified=true},
+ mnesia:write(UserUpdate);
+ true ->
+ {aborted, "Error: problem with the validation code"}
+ end
+ end,
+ case mnesia:transaction (F) of
+ {atomic, Val} ->
+ Val;
+ {aborted, Reason} ->
+ io:format ("Query: ~w aborted.~nReason: ~w~n", [F, Reason]),
+ aborted
+ end.
@@ -0,0 +1,62 @@
+%% Copyright 2009 Joony (jonathan.mcallister@gmail.com)
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% db_utils.erl
+%%
+%% This module provides basic functions for interacting with the database.
+%%
+
+-module(db_utils).
+-include("wf.inc").
+-include("config.inc").
+-export([init/0, start/0, stop/0, write/1, do/1, get_all_rows/1]).
+
+-include_lib("stdlib/include/qlc.hrl").
+
+%%% initialize the database and tables. Only run once!
+init() ->
+ mnesia:create_schema([node()]),
+ mnesia:start(),
+ db_users:init(),
+ mnesia:stop().
+
+%%% start the database
+start() ->
+ crypto:start(),
+ mnesia:start().
+
+%%% stop the database
+stop() ->
+ crypto:stop(),
+ mnesia:stop().
+
+write(Row) ->
+ F = fun() ->
+ mnesia:write(Row)
+ end,
+ mnesia:transaction(F).
+
+do(Q) ->
+ F = fun() -> qlc:e(Q) end,
+ case mnesia:transaction (F) of
+ {atomic, Val} ->
+ Val;
+ {aborted, Reason} ->
+ io:format("Query: ~w aborted.~nReason: ~w~n", [Q, Reason]),
+ aborted
+ end.
+
+get_all_rows(Table) ->
+ mnesia:transaction(fun() -> qlc:eval(qlc:q([X || X <- mnesia:table(Table)])) end).
+
@@ -0,0 +1,13 @@
+-module (web_index).
+-include_lib ("nitrogen/include/wf.inc").
+-compile(export_all).
+
+main() ->
+ #template { file="./wwwroot/template.html"}.
+
+title() ->
+ "web_index".
+
+body() ->
+ #label{text="web_index body."}.
+event(_) -> ok.
@@ -0,0 +1,51 @@
+%% Copyright 2009 Joony (jonathan.mcallister@gmail.com)
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% web_users_dashboard.erl
+%%
+%% A users homepage. Users will be directed here after logging in.
+%%
+
+-module (web_users_dashboard).
+-include_lib ("nitrogen/include/wf.inc").
+-compile(export_all).
+
+main() ->
+ case wf:user() of
+ undefined ->
+ wf:redirect("login");
+ _ ->
+ ok
+ end,
+ #template { file="./wwwroot/template.html"}.
+
+title() ->
+ "web_users_dashboard".
+
+body() ->
+ Username = wf:user(),
+ Body = [
+ #label { text="web_users_dashboard body." },
+ #gravatar { email=db_users:get_email_address(Username), size="60" },
+ #br {},
+ #link { text="Logout", postback=logout },
+ #br {}
+ ],
+ wf:render(Body).
+
+event(logout) ->
+ wf:clear_user(),
+ wf:redirect ("login");
+event(_) ->
+ ok.
@@ -0,0 +1,55 @@
+%% Copyright 2009 Joony (jonathan.mcallister@gmail.com)
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% web_users_login.erl
+%%
+%% The login screen.
+%%
+
+-module (web_users_login).
+-include_lib ("nitrogen/include/wf.inc").
+-compile(export_all).
+
+main() ->
+ #template { file="./wwwroot/template.html"}.
+
+title() ->
+ "web_users_login".
+
+body() ->
+
+ Body = [
+ #label { text="Login:" },
+ #textbox { id=username, postback=login, next=password },
+ #br {},
+ #label { text="Password:" },
+ #password { id=password, postback=login, next=submit },
+ #br {},
+ #button { id=submit, text="Login", postback=login }
+ ],
+ wf:wire(submit, username, #validate { validators = [ #is_required { text="Required" }]}),
+ wf:render(Body).
+
+event(login) ->
+ case db_users:validate_user(hd(wf:q(username)), hd(wf:q(password))) of
+ { valid, _ID } ->
+ io:format("User: ~s has logged in~n", [wf:q(username)]),
+ wf:flash("Correct"),
+ wf:user(hd(wf:q(username))),
+ wf:redirect("dashboard");
+ _ ->
+ wf:flash("Incorrect")
+ end;
+
+event(_) -> ok.
Oops, something went wrong.

0 comments on commit c359662

Please sign in to comment.