kvs.erl 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. -module(kvs).
  2. -author('Maxim Sokhatsky <maxim@synrc.com>').
  3. -include_lib("kvs/include/users.hrl").
  4. -include_lib("kvs/include/translations.hrl").
  5. -include_lib("kvs/include/groups.hrl").
  6. -include_lib("kvs/include/feeds.hrl").
  7. -include_lib("kvs/include/acls.hrl").
  8. -include_lib("kvs/include/meetings.hrl").
  9. -include_lib("kvs/include/invites.hrl").
  10. -include_lib("kvs/include/config.hrl").
  11. -include_lib("kvs/include/accounts.hrl").
  12. -include_lib("kvs/include/log.hrl").
  13. -include_lib("kvs/include/membership.hrl").
  14. -include_lib("kvs/include/payments.hrl").
  15. -include_lib("kvs/include/products.hrl").
  16. -include_lib("stdlib/include/qlc.hrl").
  17. -include_lib("kvs/include/feed_state.hrl").
  18. -compile(export_all).
  19. start() -> DBA = ?DBA, DBA:start().
  20. dir() -> DBA = ?DBA, DBA:dir().
  21. stop() -> DBA = ?DBA, DBA:stop().
  22. initialize() -> DBA = ?DBA, DBA:initialize().
  23. delete() -> DBA = ?DBA, DBA:delete().
  24. init_indexes() -> DBA = ?DBA, DBA:init_indexes().
  25. traversal( _, _, undefined, _) -> [];
  26. traversal(_, _, _, 0) -> [];
  27. traversal(RecordType, PrevPos, Next, Count)->
  28. case kvs:get(RecordType, Next) of
  29. {error,_} -> [];
  30. {ok, R} ->
  31. Prev = element(PrevPos, R),
  32. Count1 = case Count of C when is_integer(C) -> C - 1; _-> Count end,
  33. [R | traversal(RecordType, PrevPos, Prev, Count1)]
  34. end.
  35. init_db() ->
  36. case kvs:get(user,"joe") of
  37. {error,_} ->
  38. add_seq_ids(),
  39. kvs_account:create_account(system),
  40. add_sample_users(),
  41. add_sample_packages(),
  42. add_sample_payments(),
  43. add_translations();
  44. {ok,_} -> ignore end.
  45. add_sample_packages() -> kvs_membership:add_sample_data().
  46. add_sample_payments() ->
  47. {ok, Pkg1} = kvs:get(membership,1),
  48. {ok, Pkg2} = kvs:get(membership,2),
  49. {ok, Pkg3} = kvs:get(membership,3),
  50. {ok, Pkg4} = kvs:get(membership,4),
  51. PList = [{"doxtop", Pkg1},{"maxim", Pkg2},{"maxim",Pkg4}, {"kate", Pkg3} ],
  52. [ok = add_payment(U, P) || {U, P} <- PList],
  53. ok.
  54. add_payment(UserId, Package) ->
  55. {ok, MPId} = kvs_payment:add_payment(#payment{user_id=UserId, membership=Package}),
  56. kvs_payment:set_payment_state(MPId, ?MP_STATE_DONE, undefined).
  57. add_seq_ids() ->
  58. Init = fun(Key) ->
  59. case kvs:get(id_seq, Key) of
  60. {error, _} -> ok = kvs:put(#id_seq{thing = Key, id = 0});
  61. {ok, _} -> ignore
  62. end
  63. end,
  64. Init("meeting"),
  65. Init("user_transaction"),
  66. Init("user_product"),
  67. Init("user_payment"),
  68. Init("transaction"),
  69. Init("membership"),
  70. Init("payment"),
  71. Init("acl"),
  72. Init("acl_entry"),
  73. Init("feed"),
  74. Init("entry"),
  75. Init("like_entry"),
  76. Init("likes"),
  77. Init("one_like"),
  78. Init("comment").
  79. add_translations() ->
  80. lists:foreach(fun({English, Lang, Word}) ->
  81. kvs:put(#translation{english = English, lang = "en", word = English}),
  82. kvs:put(#translation{english = English, lang = Lang, word = Word}) end, ?URL_DICTIONARY).
  83. add_sample_users() ->
  84. Groups = [ #group{id="Clojure"},
  85. #group{id="Haskell"},
  86. #group{id="Erlang"} ],
  87. UserList = [
  88. #user{username = "maxim", password="pass", name = "Maxim", surname = "Sokhatsky",
  89. feed = kvs_feed:create(), type = admin, direct = kvs_feed:create(),
  90. sex=m, status=ok, team = kvs_meeting:create_team("tours"), email="maxim@synrc.com"},
  91. #user{username = "doxtop", password="pass", name = "Andrii", surname = "Zadorozhnii",
  92. feed = kvs_feed:create(), type = admin, direct = kvs_feed:create(),
  93. sex=m, status=ok, team = kvs_meeting:create_team("tours"), email="doxtop@synrc.com"},
  94. #user{username = "alice", password="pass", name = "Alice", surname = "Imagionary",
  95. feed = kvs_feed:create(), type = admin, direct = kvs_feed:create(),
  96. sex=f, status=ok, team = kvs_meeting:create_team("tours"), email="alice@synrc.com"},
  97. #user{username = "akalenuk", password="pass", name = "Alexander", surname = "Kalenuk",
  98. feed = kvs_feed:create(), type = admin, direct = kvs_feed:create(),
  99. sex=m, status=ok, team = kvs_meeting:create_team("tours"), email="akalenuk@gmail.com"}
  100. ],
  101. kvs:put(Groups),
  102. {ok, Quota} = kvs:get(config,"accounts/default_quota", 300),
  103. [ begin
  104. [ kvs_group:join(Me#user.username,G#group.id) || G <- Groups ],
  105. kvs_account:create_account(Me#user.username),
  106. kvs_account:transaction(Me#user.username, quota, Quota, #tx_default_assignment{}),
  107. kvs:put(Me#user{password = kvs:sha(Me#user.password), starred = kvs_feed:create(), pinned = kvs_feed:create()})
  108. end || Me <- UserList ],
  109. kvs_acl:define_access({user, "maxim"}, {feature, admin}, allow),
  110. kvs_acl:define_access({user_type, admin}, {feature, admin}, allow),
  111. [ kvs_user:subscribe(Me#user.username, Her#user.username) || Her <- UserList, Me <- UserList, Her /= Me ],
  112. [ kvs_user:init_mq(U) || U <- UserList ],
  113. ok.
  114. version() -> DBA=?DBA, DBA:version().
  115. add_configs() ->
  116. %% smtp
  117. kvs:put(#config{key="smtp/user", value="noreply@synrc.com"}),
  118. kvs:put(#config{key="smtp/password", value="maxim@synrc.com"}),
  119. kvs:put(#config{key="smtp/host", value="mail.synrc.com"}),
  120. kvs:put(#config{key="smtp/port", value=465}),
  121. kvs:put(#config{key="smtp/with_ssl", value=true}),
  122. kvs:put(#config{key="accounts/default_quota", value=2000}),
  123. kvs:put(#config{key="accounts/quota_limit/soft", value=-30}),
  124. kvs:put(#config{key="accounts/quota_limit/hard", value=-100}),
  125. kvs:put(#config{key="purchase/notifications/email", value=["maxim@synrc.com"]}),
  126. kvs:put(#config{key="delivery/notifications/email", value=["maxim@synrc.com"]}).
  127. put(Record) ->
  128. DBA=?DBA,
  129. DBA:put(Record).
  130. put_if_none_match(Record) ->
  131. DBA=?DBA,
  132. DBA:put_if_none_match(Record).
  133. update(Record, Meta) ->
  134. DBA=?DBA,
  135. DBA:update(Record, Meta).
  136. get(RecordName, Key) ->
  137. DBA=?DBA,
  138. DBA:get(RecordName, Key).
  139. get_for_update(RecordName, Key) ->
  140. DBA=?DBA,
  141. DBA:get_for_update(RecordName, Key).
  142. get(RecordName, Key, Default) ->
  143. DBA=?DBA,
  144. case DBA:get(RecordName, Key) of
  145. {ok,{RecordName,Key,Value}} ->
  146. ?INFO("db:get config value ~p,", [{RecordName, Key, Value}]),
  147. {ok,Value};
  148. {error, _B} ->
  149. ?INFO("db:get new config value ~p,", [{RecordName, Key, Default}]),
  150. DBA:put({RecordName,Key,Default}),
  151. {ok,Default} end.
  152. delete(Keys) -> DBA=?DBA, DBA:delete(Keys).
  153. delete(Tab, Key) -> ?INFO("db:delete ~p:~p",[Tab, Key]), DBA=?DBA,DBA:delete(Tab, Key).
  154. delete_by_index(Tab, IndexId, IndexVal) -> DBA=?DBA,DBA:delete_by_index(Tab, IndexId, IndexVal).
  155. multi_select(RecordName, Keys) -> DBA=?DBA,DBA:multi_select(RecordName, Keys).
  156. select(From, PredicateFunction) -> ?INFO("db:select ~p, ~p",[From,PredicateFunction]), DBA=?DBA, DBA:select(From, PredicateFunction).
  157. count(RecordName) -> DBA=?DBA,DBA:count(RecordName).
  158. all(RecordName) -> DBA=?DBA,DBA:all(RecordName).
  159. all_by_index(RecordName, Index, IndexValue) -> DBA=?DBA,DBA:all_by_index(RecordName, Index, IndexValue).
  160. next_id(RecordName) -> DBA=?DBA,DBA:next_id(RecordName).
  161. next_id(RecordName, Incr) -> DBA=?DBA,DBA:next_id(RecordName, Incr).
  162. next_id(RecordName, Default, Incr) -> DBA=?DBA,DBA:next_id(RecordName, Default, Incr).
  163. make_admin(User) ->
  164. {ok,U} = kvs:get(user, User),
  165. kvs:put(U#user{type = admin}),
  166. kvs_acl:define_access({user, U#user.username}, {feature, admin}, allow),
  167. kvs_acl:define_access({user_type, admin}, {feature, admin}, allow),
  168. ok.
  169. make_rich(User) ->
  170. Q = kvs:get_config("accounts/default_quota", 300),
  171. kvs_account:transaction(User, quota, Q * 100, #tx_default_assignment{}),
  172. kvs_account:transaction(User, internal, Q, #tx_default_assignment{}),
  173. kvs_account:transaction(User, currency, Q * 2, #tx_default_assignment{}).
  174. list_to_term(String) ->
  175. {ok, T, _} = erl_scan:string(String++"."),
  176. case erl_parse:parse_term(T) of
  177. {ok, Term} ->
  178. Term;
  179. {error, Error} ->
  180. Error
  181. end.
  182. save_db(Path) ->
  183. Data = lists:append([all(B) || B <- [list_to_term(B) || B <- store_riak:dir()] ]),
  184. kvs:save(Path, Data).
  185. load_db(Path) ->
  186. add_seq_ids(),
  187. AllEntries = kvs:load(Path),
  188. [{_,_,{_,Handler}}] = ets:lookup(config, "riak_client"),
  189. [case is_tuple(E) of
  190. false -> skip;
  191. true -> put(E)
  192. end || E <- AllEntries].
  193. make_paid_fake(UId) ->
  194. put(#payment{user_id=UId,info= "fake_purchase"}).
  195. save(Dir, Value) ->
  196. filelib:ensure_dir(Dir),
  197. file:write_file(Dir, term_to_binary(Value)).
  198. load(Key) ->
  199. {ok, Bin} = file:read_file(Key),
  200. binary_to_term(Bin).
  201. coalesce(undefined, B) -> B;
  202. coalesce(A, _) -> A.
  203. sha(Raw) ->
  204. lists:flatten([io_lib:format("~2.16.0b", [N]) || <<N>> <= crypto:sha(Raw)]).
  205. sha_upper(Raw) ->
  206. SHA = sha(Raw),
  207. string:to_upper(SHA).