Maxim Sokhatsky 12 лет назад
Родитель
Сommit
d60cbe0a07
11 измененных файлов с 478 добавлено и 576 удалено
  1. 0 15
      src/comments.erl
  2. 35 28
      src/kvs.erl
  3. 60 1
      src/kvs_account.erl
  4. 70 2
      src/kvs_acl.erl
  5. 84 0
      src/kvs_comment.erl
  6. 120 17
      src/kvs_feed.erl
  7. 2 2
      src/kvs_group.erl
  8. 46 8
      src/kvs_meeting.erl
  9. 8 8
      src/kvs_membership.erl
  10. 39 19
      src/kvs_user.erl
  11. 14 476
      src/store_riak.erl

+ 0 - 15
src/comments.erl

@@ -1,15 +0,0 @@
--module(comments).
--include("feeds.hrl").
--compile(export_all).
-
-add(EId, User, Value) ->  add(EId, User, Value, []).
-add(EId, User, Value, Medias) ->
-    CId = kvs:next_id("comment"),
-    R = #comment{id = {CId, EId}, comment_id = CId, entry_id = EId,
-                 content = Value, author_id = User, media = Medias, create_time = now() },
-    case kvs:put(R) of
-        ok -> {ok, R};
-        A -> A end.
-
-select_by_entry_id(EntryId) ->
-    kvs:comments_by_entry(EntryId).

+ 35 - 28
src/kvs.erl

@@ -26,14 +26,26 @@ initialize() -> DBA = ?DBA, DBA:initialize().
 delete() -> DBA = ?DBA, DBA:delete().
 init_indexes() -> DBA = ?DBA, DBA:init_indexes().
 
+traversal( _, _, undefined, _) -> [];
+traversal(_, _, _, 0) -> [];
+traversal(RecordType, PrevPos, Next, Count)->
+    case kvs:get(RecordType, Next) of
+        {error,_} -> [];
+        {ok, R} ->
+            Prev = element(PrevPos, R),
+            Count1 = case Count of C when is_integer(C) -> C - 1; _-> Count end,
+            [R | traversal(RecordType, PrevPos, Prev, Count1)]
+    end.
+
+
 init_db() ->
     case kvs:get(user,"alice") of
        {error,_} ->
 %            DBA = ?DBA,
 %            DBA:init_db(),
-%            membership_packages:add_sample_data(),
+%            kvs_membership:add_sample_data(),
             add_seq_ids(),
-            accounts:create_account(system),
+            kvs_account:create_account(system),
             add_sample_users(),
             add_sample_packages(),
             add_translations();
@@ -53,20 +65,17 @@ is_production() ->
     end.
 
 add_purchases() ->
-    {ok, Pkg1} = membership_packages:get_package(1),
-    {ok, Pkg2} = membership_packages:get_package(2),
-    {ok, Pkg3} = membership_packages:get_package(3),
-    {ok, Pkg4} = membership_packages:get_package(4),
+    {ok, Pkg1} = kvs_membership:get_package(1),
+    {ok, Pkg2} = kvs_membership:get_package(2),
+    {ok, Pkg3} = kvs_membership:get_package(3),
+    {ok, Pkg4} = kvs_membership:get_package(4),
     PList = [{"doxtop", Pkg1},{"maxim", Pkg2},{"maxim",Pkg4}, {"kate", Pkg3} ],
     [ok = add_purchase(U, P) || {U, P} <- PList],
     ok.
 
 add_purchase(UserId, Package) ->
-    {ok, MPId} = membership_packages:add_purchase(
-                         #membership_purchase{user_id=UserId, membership_package=Package }),
-    membership_packages:set_purchase_state(MPId, ?MP_STATE_DONE, undefined).
-
-
+    {ok, MPId} = kvs_membership:add_purchase(#membership_purchase{user_id=UserId, membership_package=Package}),
+    kvs_membership:set_purchase_state(MPId, ?MP_STATE_DONE, undefined).
 
 add_seq_ids() ->
     Init = fun(Key) ->
@@ -120,13 +129,13 @@ add_sample_users() ->
 
     ?INFO("creating groups"),
 
-%    GId1  = groups:create_group_directly_to_db("maxim", "kakaranet", "Kakaranet", "Kakaranet'e Hoşgeldiniz", public),
-%    GId2  = groups:create_group_directly_to_db("maxim", "yeniler", "Yeniler", "So, you must be new here.", public),
+%    GId1  = kvs_group:create_group_directly_to_db("maxim", "kakaranet", "Kakaranet", "Kakaranet'e Hoşgeldiniz", public),
+%    GId2  = kvs_group:create_group_directly_to_db("maxim", "yeniler", "Yeniler", "So, you must be new here.", public),
 
     ?INFO("adding users accounts"),
     [ begin
-          accounts:create_account(Me#user.username),
-          accounts:transaction(Me#user.username, quota, kvs:get_config("accounts/default_quota", 300), #tx_default_assignment{}),
+          kvs_account:create_account(Me#user.username),
+          kvs_account:transaction(Me#user.username, quota, kvs:get_config("accounts/default_quota", 300), #tx_default_assignment{}),
           kvs:put(Me#user{password = kvs:sha(Me#user.password),
                                 starred = feed_create(),
                                 pinned = feed_create()})
@@ -135,18 +144,18 @@ add_sample_users() ->
     [ begin
         ok
 %          kvs_users:init_mq(Me#user.username, [GId1, GId2]),
-%          groups:add_to_group_directly_to_db(Me#user.username, GId1, member),
-%          groups:add_to_group_directly_to_db(Me#user.username, GId2, member)
+%          kvs_group:add_to_group_directly_to_db(Me#user.username, GId1, member),
+%          kvs_group:add_to_group_directly_to_db(Me#user.username, GId2, member)
       end || Me <- UserList ],
-    acls:define_access({user, "maxim"},    {feature, admin}, allow),
-    acls:define_access({user_type, admin}, {feature, admin}, allow),
+    kvs_acl:define_access({user, "maxim"},    {feature, admin}, allow),
+    kvs_acl:define_access({user_type, admin}, {feature, admin}, allow),
     ?INFO("making all users each other friends").
 %    [[case Me == Her of
 %        true -> ok;
 %        false -> kvs_users:subscribe(Me#user.username, Her#user.username)
 %    end || Her <- UserList] || Me <- UserList].
 
-add_sample_packages() -> membership_packages:add_sample_data().
+add_sample_packages() -> kvs_membership:add_sample_data().
 version() -> ?INFO("version: ~p", [1]).
 
 % blocking
@@ -186,9 +195,7 @@ update(Record, Meta) ->
 
 get(RecordName, Key) ->
     DBA=?DBA,
-    case C = DBA:get(RecordName, Key) of
-        {ok,_R} -> C;
-        A -> A end.
+    DBA:get(RecordName, Key).
 
 get_for_update(RecordName, Key) ->
     DBA=?DBA,
@@ -280,15 +287,15 @@ get_purchases_by_user(User, StartFromPurchase, Count, States) -> DBA=?DBA, DBA:g
 make_admin(User) ->
     {ok,U} = kvs:get(user, User),
     kvs:put(U#user{type = admin}),
-    acls:define_access({user, U#user.username}, {feature, admin}, allow),
-    acls:define_access({user_type, admin}, {feature, admin}, allow),
+    kvs_acl:define_access({user, U#user.username}, {feature, admin}, allow),
+    kvs_acl:define_access({user_type, admin}, {feature, admin}, allow),
     ok.
 
 make_rich(User) -> 
     Q = kvs:get_config("accounts/default_quota",  300),
-    accounts:transaction(User, quota, Q * 100, #tx_default_assignment{}),
-    accounts:transaction(User, internal, Q, #tx_default_assignment{}),
-    accounts:transaction(User, currency, Q * 2, #tx_default_assignment{}).
+    kvs_account:transaction(User, quota, Q * 100, #tx_default_assignment{}),
+    kvs_account:transaction(User, internal, Q, #tx_default_assignment{}),
+    kvs_account:transaction(User, currency, Q * 2, #tx_default_assignment{}).
 
 feed_create() ->
     FId = kvs:next_id("feed", 1),

+ 60 - 1
src/accounts.erl → src/kvs_account.erl

@@ -1,4 +1,4 @@
--module(accounts).
+-module(kvs_account).
 -include_lib("kvs/include/accounts.hrl").
 -include_lib("kvs/include/membership_packages.hrl").
 -include_lib("kvs/include/log.hrl").
@@ -165,6 +165,18 @@ user_paid(UId) ->
         #user_purchase{top = undefined} -> false;
         _ -> true
     end.
+
+transactions(UserId) -> tx_list(UserId, undefined, 10000).
+
+tx_list(UserId, undefined, PageAmount) ->
+    case kvs:get(user_transaction, UserId) of
+        {ok, O} when O#user_transaction.top =/= undefined -> tx_list(UserId, O#user_transaction.top, PageAmount);
+        {error, notfound} -> [] end;
+tx_list(UserId, StartFrom, Limit) ->
+    case kvs:get(transaction,StartFrom) of
+        {ok, #transaction{next = N}=P} -> [ P | kvs:traversal(transaction, #transaction.next, N, Limit)];
+        X -> [] end.
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 handle_notice(["transaction", "user", User, "add_transaction"] = Route,
@@ -175,3 +187,50 @@ handle_notice(["transaction", "user", User, "add_transaction"] = Route,
     {noreply, State};
 
 handle_notice(Route, Message, State) -> error_logger:info_msg("Unknown ACCOUNTS notice").
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+add_transaction_to_user(UserId,Purchase) ->
+    {ok,Team} = case kvs:get(user_transaction, UserId) of
+                     {ok,T} -> {ok,T};
+                     _ -> ?INFO("user_transaction not found"),
+                          Head = #user_transaction{ user = UserId, top = undefined},
+                          {kvs:put(Head),Head}
+                end,
+
+    EntryId = Purchase#transaction.id, %kvs:next_id("membership_purchase",1),
+    Prev = undefined,
+    case Team#user_transaction.top of
+        undefined -> Next = undefined;
+        X -> case kvs:get(transaction, X) of
+                 {ok, TopEntry} ->
+                     Next = TopEntry#transaction.id,
+                     EditedEntry = #transaction {
+                           commit_time = TopEntry#transaction.commit_time,
+                           amount = TopEntry#transaction.amount,
+                           remitter = TopEntry#transaction.remitter,
+                           acceptor = TopEntry#transaction.acceptor,
+                           currency = TopEntry#transaction.currency,
+                           info = TopEntry#transaction.info,
+                           id = TopEntry#transaction.id,
+                           next = TopEntry#transaction.next,
+                           prev = EntryId },
+                    kvs:put(EditedEntry); % update prev entry
+                 {error,notfound} -> Next = undefined
+             end
+    end,
+
+    Entry  = #transaction{id = EntryId,
+                           commit_time = Purchase#transaction.commit_time,
+                           amount = Purchase#transaction.amount,
+                           remitter = Purchase#transaction.remitter,
+                           acceptor = Purchase#transaction.acceptor,
+                           currency = Purchase#transaction.currency,
+                           info = Purchase#transaction.info,
+                           next = Next,
+                           prev = Prev},
+
+    case kvs:put(Entry) of ok -> kvs:put(#user_transaction{ user = UserId, top = EntryId}), {ok, EntryId};
+                              Error -> ?INFO("Cant write transaction"), {failure,Error} end.

+ 70 - 2
src/acls.erl → src/kvs_acl.erl

@@ -1,5 +1,5 @@
--module(acls).
--author('Vladimir Baranov <baranoff.vladimir@gmail.com>').
+-module(kvs_acl).
+-copyright('Synrc Research Center s.r.o.').
 -compile(export_all).
 
 -include_lib("kvs/include/acls.hrl").
@@ -72,3 +72,71 @@ select_type({user, UId}) -> {user, UId};
 select_type({group, name = GId}) -> {group, GId};
 select_type({feed, FId}) -> {feed, FId};
 select_type({feature, Feature}) ->  {feature, Feature}.
+
+acl_entries(AclId) ->
+    [AclStr] = io_lib:format("~p",[AclId]),
+    RA = kvs:get(acl, erlang:list_to_binary(AclStr)),
+    case RA of
+        {ok,RO} -> riak_read_acl_entries(RO#acl.top, []);
+        {error, notfound} -> [] end.
+
+riak_read_acl_entries(undefined, Result) -> Result;
+riak_read_acl_entries(Next, Result) ->
+    NextStr = io_lib:format("~p",[Next]),
+    RA = kvs:get(acl_entry,erlang:list_to_binary(NextStr)),
+    case RA of
+         {ok,RO} -> riak_read_acl_entries(RO#acl_entry.prev, Result ++ [RO]);
+         {error,notfound} -> Result end.
+
+acl_add_entry(Resource, Accessor, Action) ->
+    Acl = case kvs:get(acl, Resource) of
+              {ok, A} ->
+                  A;
+              %% if acl record wasn't created already
+              {error, notfound} ->
+                  A = #acl{id = Resource, resource=Resource},
+                  kvs:put(A),
+                  A
+          end,
+
+    EntryId = {Accessor, Resource},
+
+    case kvs:get(acl_entry, EntryId) of
+        %% there is no entries for specified Acl and Accessor, we have to add it
+        {error, notfound} ->
+            Next = undefined,
+            Prev = case Acl#acl.top of
+                       undefined ->
+                           undefined;
+
+                       Top ->
+                           case kvs:get(acl_entry, Top) of
+                               {ok, TopEntry} ->
+                                   EditedEntry = TopEntry#acl_entry{next = EntryId},
+                                   kvs:put(EditedEntry), % update prev entry
+                                   TopEntry#acl_entry.id;
+
+                               {error, notfound} ->
+                                   undefined
+                           end
+                   end,
+
+            %% update acl with top of acl entries list
+            kvs:put(Acl#acl{top = EntryId}),
+
+            Entry  = #acl_entry{id = EntryId,
+                                entry_id = EntryId,
+                                accessor = Accessor,
+                                action = Action,
+                                next = Next,
+                                prev = Prev},
+
+            ok = kvs:put(Entry),
+            Entry;
+
+        %% if acl entry for Accessor and Acl is defined - just change action
+        {ok, AclEntry} ->
+            kvs:put(AclEntry#acl_entry{action = Action}),
+            AclEntry
+    end.
+

+ 84 - 0
src/kvs_comment.erl

@@ -0,0 +1,84 @@
+-module(kvs_comment).
+-include("feeds.hrl").
+-compile(export_all).
+
+add(EId, User, Value) ->  add(EId, User, Value, []).
+add(EId, User, Value, Medias) ->
+    CId = kvs:next_id("comment"),
+    R = #comment{id = {CId, EId}, comment_id = CId, entry_id = EId,
+                 content = Value, author_id = User, media = Medias, create_time = now() },
+    case kvs:put(R) of
+        ok -> {ok, R};
+        A -> A end.
+
+select_by_entry_id(EntryId) ->
+    kvs:comments_by_entry(EntryId).
+
+read_comments(undefined) -> [];
+read_comments([#comment{comments = C} | Rest]) -> [read_comments(C) | read_comments(Rest)];
+read_comments(C) -> kvs:traversal(comment, #comment.prev, C, all).
+
+read_comments_rev(undefined) -> [];
+read_comments_rev([#comment{comments = C} | Rest]) -> [read_comments_rev(C) | read_comments_rev(Rest)];
+read_comments_rev(C) -> kvs:traversal(comment, #comment.next, C, all).
+
+% @spec comment_by_id({{EntryId::term(), FeedId::term()}, CommentId::term()}) -> {ok, #comment{}}.
+comment_by_id(CommentId) -> kvs:get(CommentId).
+
+% @spec comments_by_entry(EId::{string(), term()}) -> [#comment{}].
+comments_by_entry({EId, FId}) ->
+    case kvs:entry_by_id({EId, FId}) of
+        {ok, #entry{comments_rear = undefined}} ->
+            [];
+        {ok, #entry{comments_rear = First}} ->
+            lists:flatten(read_comments_rev(First));
+        _ ->
+            []
+    end.
+
+
+feed_add_comment(FId, User, EntryId, ParentComment, CommentId, Content, Medias) ->
+    FullId = {CommentId, {EntryId, FId}},
+
+    Prev = case ParentComment of
+        undefined ->
+            {ok, Entry} = kvs:entry_by_id({EntryId, FId}),
+            {PrevC, E} = case Entry#entry.comments of
+                        undefined ->
+                            {undefined, Entry#entry{comments_rear = FullId}};
+                        Id ->
+                            {ok, PrevTop} = kvs:get(comment, Id),
+                            kvs:put(PrevTop#comment{next = FullId}),
+                            {Id, Entry}
+                   end,
+
+            kvs:put(E#entry{comments=FullId}),
+            PrevC;
+
+        _ ->
+            {ok, Parent} = kvs:get(comment, {{EntryId, FId}, ParentComment}),
+            {PrevC, CC} = case Parent#comment.comments of
+                        undefined ->
+                            {undefined, Parent#comment{comments_rear = FullId}};
+                        Id ->
+                            {ok, PrevTop} = kvs:get(comment, Id),
+                            kvs:put(PrevTop#comment{next = FullId}),
+                            {Id, Parent}
+                    end,
+            kvs:put(CC#comment{comments = FullId}),
+            PrevC
+    end,
+    Comment = #comment{id = FullId,
+                       author_id = User,
+                       comment_id = CommentId,
+                       entry_id = EntryId,
+                       raw_content = Content,
+                       content = Content,
+                       media = Medias,
+                       create_time = now(),
+                       prev = Prev,
+                       next = undefined
+                      },
+    kvs:put(Comment),
+    {ok, Comment}.
+

+ 120 - 17
src/feeds.erl → src/kvs_feed.erl

@@ -1,4 +1,4 @@
--module(feeds).
+-module(kvs_feed).
 -compile(export_all).
 -include_lib("kvs/include/feeds.hrl").
 -include_lib("kvs/include/users.hrl").
@@ -67,19 +67,13 @@ add_like(Fid, Eid, Uid) ->
 
 get_entries_count(Uid) ->
     case kvs:get(user_etries_count, Uid) of
-        {ok, UEC} -> 
-            UEC#user_etries_count.entries;
-        {error, notfound} ->
-            0
-    end.
+        {ok, UEC} -> UEC#user_etries_count.entries;
+        {error, notfound} -> 0 end.
 
 get_comments_count(Uid) ->
     case kvs:get(user_etries_count, Uid) of
-        {ok, UEC} -> 
-            UEC#user_etries_count.comments;
-        {error, notfound} ->
-            0
-    end.
+        {ok, UEC} -> UEC#user_etries_count.comments;
+        {error, notfound} -> 0 end.
 
 get_feed(FId) -> kvs:get(feed, FId).
 get_entries_in_feed(FId) -> kvs:entries_in_feed(FId).
@@ -348,14 +342,14 @@ handle_notice(["feed", _Type, EntryOwner, "entry", EntryId, "delete"] = Route,
         {_, [EntryOwner|_]} ->
             ?INFO("feed(~p): remove entry: Owner=~p, Route=~p, Message=~p",
                   [self(), Owner, Route, Message]),
-            feeds:remove_entry(Feed, EntryId),
-            feeds:remove_entry(Direct, EntryId);
+            kvs_feed:remove_entry(Feed, EntryId),
+            kvs_feed:remove_entry(Direct, EntryId);
         %% we are owner of the entry - delete it
         {Owner, _} ->
             ?INFO("feed(~p): remove entry: Owner=~p, Route=~p, Message=~p",
                   [self(), Owner, Route, Message]),
-            feeds:remove_entry(Feed, EntryId),
-            feeds:remove_entry(Direct, EntryId);
+            kvs_feed:remove_entry(Feed, EntryId),
+            kvs_feed:remove_entry(Direct, EntryId);
         %% one of the friends has deleted some entry from his feed. Ignore
         _ ->
             ok
@@ -371,7 +365,7 @@ handle_notice(["feed", _Type, _EntryOwner, "entry", EntryId, "edit"] = Route,
           [self(), Owner, Route, Message]),
 
     %% edit entry in all feeds
-    feeds:edit_entry(Feed, EntryId, NewDescription),
+    kvs_feed:edit_entry(Feed, EntryId, NewDescription),
 
     {noreply, State};
 
@@ -382,7 +376,7 @@ handle_notice(["feed", _Type, _EntryOwner, "comment", CommentId, "add"] = Route,
 
     ?INFO("feed(~p): add comment: Owner=~p, Route=~p, Message=~p",
           [self(), Owner, Route, Message]),
-    feeds:entry_add_comment(Feed, From, EntryId, ParentComment, CommentId, Content, Medias),
+    kvs_feed:entry_add_comment(Feed, From, EntryId, ParentComment, CommentId, Content, Medias),
     {noreply, State};
 
 handle_notice(["feed", "user", UId, "count_entry_in_statistics"] = Route, 
@@ -428,3 +422,112 @@ handle_notice(["likes", _, _, "add_like"] = Route,  % _, _ is here beacause of t
     {noreply, State};
 
 handle_notice(Route, Message, State) -> error_logger:info_msg("Unknown FEEDS notice").
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+feed_add_direct_message(FId,User,To,EntryId,Desc,Medias) -> feed_add_entry(FId,User,To,EntryId,Desc,Medias,{user,direct},"").
+feed_add_entry(FId,From,EntryId,Desc,Medias) -> feed_add_entry(FId,From,undefined,EntryId,Desc,Medias,{user,normal},"").
+feed_add_entry(FId, User, To, EntryId,Desc,Medias,Type,SharedBy) ->
+    %% prevent adding of duplicate records to feed
+    case kvs:entry_by_id({EntryId, FId}) of
+        {ok, _} -> ok;
+        _ -> do_feed_add_entry(FId, User, To, EntryId, Desc, Medias, Type, SharedBy)
+    end.
+
+do_feed_add_entry(FId, User, To, EntryId, Desc, Medias, Type, SharedBy) ->
+    {ok,Feed} = kvs:get(feed,erlang:integer_to_list(FId)),
+    Id = {EntryId, FId},
+    Next = undefined,
+    Prev = case Feed#feed.top of
+               undefined ->
+                   undefined;
+               X ->
+                   case kvs:get(entry, X) of
+                       {ok, TopEntry} ->
+                           EditedEntry = TopEntry#entry{next = Id},
+                           % update prev entry
+                           kvs:put(EditedEntry),
+                           TopEntry#entry.id;
+                       {error,notfound} ->
+                           undefined
+                   end
+           end,
+
+    kvs:put(#feed{id = FId, top = {EntryId, FId}}), % update feed top with current
+
+    Entry  = #entry{id = {EntryId, FId},
+                    entry_id = EntryId,
+                    feed_id = FId,
+                    from = User,
+                    to = To,
+                    type = Type,
+                    media = Medias,
+                    created_time = now(),
+                    description = Desc,
+                    raw_description = Desc,
+                    shared = SharedBy,
+                    next = Next,
+                    prev = Prev},
+
+    ModEntry = case catch feedformat:format(Entry) of
+                   {_, Reason} ->
+                       ?ERROR("feedformat error: ~p", [Reason]),
+                       Entry;
+                   #entry{} = ME ->
+                       ME
+               end,
+
+    kvs:put(ModEntry),
+    {ok, ModEntry}.
+
+
+
+
+
+% @spec entry_by_id(term()) -> {ok, #entry{}} | {error, not_found}.
+entry_by_id(EntryId) -> kvs:get(entry, EntryId).
+
+
+purge_feed(FeedId) ->
+    {ok,Feed} = kvs:get(feed,FeedId),
+    Removal = riak_entry_traversal(Feed#feed.top, -1),
+    [kvs:delete(entry,Id)||#entry{id=Id}<-Removal],
+    kvs:put(Feed#feed{top=undefined}).
+
+purge_unverified_feeds() ->
+    [purge_feed(FeedId) || #user{feed=FeedId,status=S,email=E} <- kvs:all(user),E==undefined].
+
+riak_entry_traversal(undefined, _) -> [];
+riak_entry_traversal(_, 0) -> [];
+riak_entry_traversal(Next, Count)->
+    case store_riak:get(entry, Next) of
+        {error,notfound} -> [];
+        {ok, R} ->
+            Prev = element(#entry.prev, R),
+            Count1 = case Count of 
+                C when is_integer(C) -> case R#entry.type of
+                    {_, system} -> C;   % temporal entries are entries too, but they shouldn't be counted
+                    {_, system_note} -> C;
+                    _ -> C - 1
+                end;
+                _-> Count 
+            end,
+            [R | riak_entry_traversal(Prev, Count1)]
+    end.
+
+entries_in_feed(FeedId, undefined, PageAmount) ->
+    case kvs:get(feed, FeedId) of
+        {ok, O} -> riak_entry_traversal(O#feed.top, PageAmount);
+        {error, notfound} -> []
+    end;
+entries_in_feed(FeedId, StartFrom, PageAmount) ->
+    %% construct entry unic id
+    case kvs:get(entry,{StartFrom, FeedId}) of
+        {ok, #entry{prev = Prev}} -> riak_entry_traversal(Prev, PageAmount);
+        _ -> []
+    end.
+
+feed_direct_messages(_FId, Page, PageAmount, CurrentUser, CurrentFId) ->
+    Page, PageAmount, CurrentUser, CurrentFId,
+    [].
+

+ 2 - 2
src/groups.erl → src/kvs_group.erl

@@ -1,4 +1,4 @@
--module(groups).
+-module(kvs_group).
 -compile(export_all).
 -include_lib("kvs/include/users.hrl").
 -include_lib("kvs/include/groups.hrl").
@@ -6,7 +6,7 @@
 -include_lib("kvs/include/log.hrl").
 
 retrieve_groups(User) ->
-    ?INFO("retrieve_groups: ~p",[User]),
+    ?INFO("retrieve group for user: ~p",[User]),
     case participate(User) of
          [] -> [];
          Gs -> UC_GId = lists:sublist(lists:reverse(

+ 46 - 8
src/meetings.erl → src/kvs_meeting.erl

@@ -1,4 +1,4 @@
--module(meetings).
+-module(kvs_meeting).
 -include_lib("kvs/include/users.hrl").
 -include_lib("kvs/include/meetings.hrl").
 -include_lib("kvs/include/feed_state.hrl").
@@ -48,7 +48,6 @@ join(UID, TID) -> kvs:join_tournament(UID, TID).
 remove(UID, TID) -> kvs:leave_tournament(UID, TID).
 waiting_player(TID) -> kvs:tournament_pop_waiting_player(TID).
 joined_users(TID) -> kvs:tournament_waiting_queue(TID).
-user_tournaments(UID) -> kvs:user_tournaments(UID).
 user_joined(TID, UID) -> 
     AllJoined = [UId || #play_record{who = UId} <- joined_users(TID)],
     lists:member(UID, AllJoined).
@@ -59,7 +58,7 @@ destroy(TID) -> kvs:delete_by_index(play_record, <<"play_record_tournament_bin">
                           kvs:delete(tournament,TID).
 clear() -> [destroy(T#meeting.id) || T <- kvs:all(meeting)].
 lost() -> lists:usort([erlang:element(3, I) || I <- kvs:all(play_record)]).
-fake_join(TID) -> [meetings:join(auth:ima_gio2(X),TID)||X<-lists:seq(1,30)].
+fake_join(TID) -> [kvs_meeting:join(auth:ima_gio2(X),TID)||X<-lists:seq(1,30)].
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -67,7 +66,7 @@ handle_notice(["tournaments", "user", UId, "create"] = Route,
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): create: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
     {TourName, TourDesc, {Y,M,D}, Time, MaxPlayers, Quota, Award, TourType, GameType} = Message,
-    case meetings:create(UId, TourName, TourDesc, {Y,M,D}, Time, MaxPlayers, Quota, Award, TourType, GameType) of
+    case kvs_meeting:create(UId, TourName, TourDesc, {Y,M,D}, Time, MaxPlayers, Quota, Award, TourType, GameType) of
         {error,X} -> 
             ?ERROR("Error creating tournament: ~p", X);
         TId -> skip
@@ -78,11 +77,11 @@ handle_notice(["tournaments", "user", UId, "create_and_join"] = Route,
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): create_and_join: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
     {TourName, TourDesc, {Y,M,D}, Time, MaxPlayers, Quota, Award, TourType, GameType} = Message,
-    case meetings:create(UId, TourName, TourDesc, {Y,M,D}, Time, MaxPlayers, Quota, Award, TourType, GameType) of
+    case kvs_meeting:create(UId, TourName, TourDesc, {Y,M,D}, Time, MaxPlayers, Quota, Award, TourType, GameType) of
         {error,X} -> 
             ?ERROR("Error creating tournament: ~p", X);
         TId -> 
-            meetings:join(UId, TId)
+            kvs_meeting:join(UId, TId)
     end,
     {noreply, State};
 
@@ -90,15 +89,54 @@ handle_notice(["system", "tournament_join"] = Route,
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): tournament_join: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
     {UId, TId} = Message,
-    meetings:join(UId, TId),
+    kvs_meeting:join(UId, TId),
     {noreply, State};
 
 handle_notice(["system", "tournament_remove"] = Route,
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): tournament_remove: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
     {UId, TId} = Message,
-    meetings:remove(UId, TId),
+    kvs_meeting:remove(UId, TId),
     {noreply, State};
 
 handle_notice(Route, Message, State) -> error_logger:info_msg("Unknown MEETINGS notice").
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+join_tournament(UserId, TournamentId) ->
+    case kvs:get(user, UserId) of
+        {ok, User} ->
+            GP = case kvs_account:balance(UserId, points) of
+                     {ok, AS1} -> AS1;
+                     {error, _} -> 0 end,
+            Q = case kvs_account:balance(UserId,  quota) of
+                     {ok, AS4} -> AS4;
+                     {error, _} -> 0 end,
+            RN = kvs_users:user_realname(UserId),
+            kvs:put(#play_record{
+                 who = UserId,
+                 tournament = TournamentId,
+                 team = User#user.team,
+                 game_id = undefined, 
+		 other = now(),
+                 realname = RN,
+                 points = GP,
+                 quota = Q});
+        _ ->
+            ?INFO(" User ~p not found for joining tournament ~p", [UserId, TournamentId])
+    end.
+
+leave_tournament(UserId, TournamentId) ->
+    case kvs:get(play_record, {UserId, TournamentId}) of
+        {ok, _} -> 
+            kvs:delete(play_record, {UserId, TournamentId}),
+            leave_tournament(UserId, TournamentId); % due to WTF error with old records
+        _ -> ok
+    end.
+
+user_tournaments(UId) -> 
+    kvs:all_by_index(play_record, <<"play_record_who_bin">>, list_to_binary(UId)).
+
+tournament_waiting_queue(TId) ->
+    kvs:all_by_index(play_record, <<"play_record_tournament_bin">>, list_to_binary(integer_to_list(TId))).

+ 8 - 8
src/membership_packages.erl → src/kvs_membership.erl

@@ -1,4 +1,4 @@
--module(membership_packages).
+-module(kvs_membership).
 -author('Vladimir Baranov <baranoff.vladimir@gmail.com>').
 -include_lib("kvs/include/membership_packages.hrl").
 -include_lib("kvs/include/log.hrl").
@@ -168,8 +168,8 @@ charge_user_account(MP) ->
         ?INFO("charge user account. OrderId: ~p, User: ~p, Kakush:~p, Quota:~p",
               [OrderId, UserId, Kakush, Quota]),
 
-        accounts:transaction(UserId, internal, Kakush, PaymentTransactionInfo),
-        accounts:transaction(UserId, quota, Quota, PaymentTransactionInfo)
+        kvs_account:transaction(UserId, internal, Kakush, PaymentTransactionInfo),
+        kvs_account:transaction(UserId, quota, Quota, PaymentTransactionInfo)
     catch
         _:E ->
             ?ERROR("unable to charge user account. User=~p, OrderId=~p. Error: ~p",
@@ -204,7 +204,7 @@ handle_notice(["system", "add_package"] = Route,
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): add_package: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
     {MP} = Message,
-    case membership_packages:add_package(MP) of
+    case kvs_membership:add_package(MP) of
         {ok, _} ->
             ok;
         {error, Reason} ->
@@ -216,28 +216,28 @@ handle_notice(["purchase", "user", _, "set_purchase_state"] = Route,
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): set_purchase_state: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),  
     {MPId, NewState, Info} = Message,
-    membership_packages:set_purchase_state(MPId, NewState, Info),
+    kvs_membership:set_purchase_state(MPId, NewState, Info),
     {noreply, State};
 
 handle_notice(["purchase", "user", _, "add_purchase"] = Route,
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): add_purchase: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),    
     {MP} = Message,
-    membership_packages:add_purchase(MP),
+    kvs_membership:add_purchase(MP),
     {noreply, State};
 
 handle_notice(["purchase", "user", _, "set_purchase_external_id"] = Route,
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): set_purchase_external_id: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
     {PurchaseId, TxnId} = Message,
-    membership_packages:set_purchase_external_id(PurchaseId, TxnId),
+    kvs_membership:set_purchase_external_id(PurchaseId, TxnId),
     {noreply, State};
 
 handle_notice(["purchase", "user", _, "set_purchase_info"] = Route,
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): set_purchase_info: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
     {OrderId, Info} = Message,
-    membership_packages:set_purchase_info(OrderId, Info),
+    kvs_membership:set_purchase_info(OrderId, Info),
     {noreply, State};
 
 handle_notice(Route, Message, State) -> error_logger:info_msg("Unknown PAYMENTS notice").

+ 39 - 19
src/kvs_users.erl → src/kvs_user.erl

@@ -1,4 +1,4 @@
--module(kvs_users).
+-module(kvs_user).
 -include_lib("kvs/include/users.hrl").
 -include_lib("kvs/include/groups.hrl").
 -include_lib("kvs/include/accounts.hrl").
@@ -15,7 +15,7 @@ register(#user{username=U, email=Email, facebook_id = FbId} = RegisterData0) ->
             {ok, _} -> {error, email_taken} end end,
 
     FindUser2 = case FindUser of
-        {ok, UserName} -> case groups:get(UserName) of
+        {ok, UserName} -> case kvs_group:get(UserName) of
             {error, _} -> {ok, UserName};
             _ -> {error, username_taken} end;
         A -> A end,
@@ -37,9 +37,9 @@ process_register(#user{username=U} = RegisterData0) ->
         password = HashedPassword },
 
     kvs:put(RegisterData),
-    accounts:create_account(U),
+    kvs_account:create_account(U),
     {ok, DefaultQuota} = kvs:get(config, "accounts/default_quota",  300),
-    accounts:transaction(U, quota, DefaultQuota, #tx_default_assignment{}),
+    kvs_account:transaction(U, quota, DefaultQuota, #tx_default_assignment{}),
     init_mq(U),
     {ok, U}.
 
@@ -51,7 +51,7 @@ check_username(Name, FbId) ->
 
 delete(UserName) ->
     case kvs_users:get(UserName) of
-        {ok, User} -> GIds = groups:list_groups_per_user(UserName),
+        {ok, User} -> GIds = kvs_group:list_groups_per_user(UserName),
                       [mqs:notify(["subscription", "user", UserName, "remove_from_group"], {GId}) || GId <- GIds],
                       F2U = [ {MeId, FrId} || #subscription{who = MeId, whom = FrId} <- subscriptions(User) ],
                       [ unsubscribe(MeId, FrId) || {MeId, FrId} <- F2U ],
@@ -110,7 +110,7 @@ subscription_mq(Type, Action, MeId, ToId) ->
     mqs_channel:close(Channel).
 
 init_mq(User=#user{}) ->
-    Groups = groups:list_groups_per_user(User),
+    Groups = kvs_group:list_groups_per_user(User),
     ?INFO("~p init mq. users: ~p", [User, Groups]),
     UserExchange = ?USER_EXCHANGE(User#user.username),
     ExchangeOptions = [{type, <<"fanout">>}, durable, {auto_delete, false}],
@@ -185,7 +185,7 @@ rk(List) -> mqs_lib:list_to_key(List).
 retrieve_connections(Id,Type) ->
     Friends = case Type of 
                   user -> kvs_users:list_subscr_usernames(Id);
-                     _ -> groups:list_group_members(Id) end,
+                     _ -> kvs_group:list_group_members(Id) end,
     case Friends of
 	[] -> [];
 	Full -> Sub = lists:sublist(Full, 10),
@@ -193,7 +193,7 @@ retrieve_connections(Id,Type) ->
                      [] -> [];
                       _ -> Data = [begin case kvs:get(user,Who) of
                                        {ok,User} -> RealName = kvs_users:user_realname_user(User),
-                                                    Paid = accounts:user_paid(Who),
+                                                    Paid = kvs_account:user_paid(Who),
                                                     {Who,Paid,RealName};
 				               _ -> undefined end end || Who <- Sub],
 			   [X||X<-Data, X/=undefined] end end.
@@ -225,7 +225,7 @@ handle_notice(["system", "create_group"] = Route,
 handle_notice(["db", "group", GId, "remove_group"] = Route, 
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): remove_group: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
-    {_, Group} = groups:get_group(GId),
+    {_, Group} = kvs_group:get_group(GId),
     case Group of 
         notfound -> ok;
         _ ->
@@ -294,7 +294,7 @@ handle_notice(["subscription", "user", UId, "leave_group"] = Route,
         ok ->
             case Group#group.owner of
                 UId -> % User is owner, transfer ownership to someone else
-                    Members = groups:list_group_members(GId),
+                    Members = kvs_group:list_group_members(GId),
                     case Members of
                         [ FirstOne | _ ] ->
                             ok = kvs:put(Group#group{owner = FirstOne}),
@@ -356,15 +356,35 @@ handle_notice(["gifts", "user", UId, "mark_gift_as_deliving"] = Route,
 handle_notice(["login", "user", UId, "update_after_login"] = Route,
     Message, #state{owner = Owner, type =Type} = State) ->
     ?INFO("queue_action(~p): update_after_login: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),    
-    Update =
-        case kvs_users:user_status(UId) of
-            {error, status_info_not_found} ->
-                #user_status{username = UId,
-                             last_login = erlang:now()};
-            {ok, UserStatus} ->
-                UserStatus#user_status{last_login = erlang:now()}
-        end,
+    Update = case kvs_users:user_status(UId) of
+        {error, status_info_not_found} -> #user_status{username = UId, last_login = erlang:now()};
+        {ok, UserStatus} -> UserStatus#user_status{last_login = erlang:now()} end,
     kvs:put(Update),
     {noreply, State};
 
-handle_notice(Route, Message, State) -> error_logger:info_msg("Unknown USERS notice").
+handle_notice(Route, Message, State) -> error_logger:info_msg("Unknown USERS notice").
+
+
+%%%%%%%%%%%%%%%%%%%%%%
+
+% user backlinks
+
+user_by_verification_code(Code) ->
+    case kvs:get(code,Code) of
+        {ok,{_,User,_}} -> kvs:get(user,User);
+        Else -> Else end.
+
+user_by_facebook_id(FBId) ->
+    case kvs:get(facebook,FBId) of
+        {ok,{_,User,_}} -> kvs:get(user,User);
+        Else -> Else end.
+
+user_by_email(Email) ->
+    case kvs:get(email,Email) of
+        {ok,{_,User,_}} -> kvs:get(user,User);
+        Else -> Else end.
+
+user_by_username(Name) ->
+    case X = kvs:get(user,Name) of
+        {ok,_Res} -> X;
+        Else -> Else end.

+ 14 - 476
src/store_riak.erl

@@ -1,5 +1,6 @@
 -module(store_riak).
 -author('Maxim Sokhatsky <maxim@synrc.com>').
+-copyright('Synrc Research Center s.r.o.').
 -include_lib("kvs/include/config.hrl").
 -include_lib("kvs/include/users.hrl").
 -include_lib("kvs/include/groups.hrl").
@@ -90,7 +91,6 @@ put_if_none_match(Record) ->
             Error
     end.
 
-%% update(Record, Meta) -> ok | {error, Reason}
 update(Record, Object) ->
     NewObject = make_object(Record),
     NewKey = riak_object:key(NewObject),
@@ -144,8 +144,6 @@ get_for_update(Tab, Key) ->
 get_word(Word) -> store_riak:get(ut_word,Word).
 get_translation({Lang, Word}) -> store_riak:get(ut_translation, Lang ++ "_" ++ Word).
 
-% delete
-
 delete(Keys) when is_list(Keys) -> lists:foreach(fun mnesia:delete_object/1, Keys); % TODO
 delete(Keys) -> delete([Keys]).
 
@@ -153,8 +151,7 @@ delete(Tab, Key) ->
     C = riak_client(),
     Bucket = key_to_bin(Tab),
     IntKey = key_to_bin(Key),
-    C:delete(Bucket, IntKey),
-    ok.
+    C:delete(Bucket, IntKey).
 
 delete_by_index(Tab, IndexId, IndexVal) ->
     Riak = riak_client(),
@@ -172,27 +169,18 @@ key_to_bin(Key) ->
     end.
 
 select(RecordName, Pred) when is_function(Pred) ->
-	%% FIXME: bruteforce select
-	All = all(RecordName),
-	lists:filter(Pred, All);
+    All = all(RecordName),
+    lists:filter(Pred, All);
 
 select(RecordName, Select) when is_list(Select) ->
-	%% FIXME: dummy select!
-	Where = proplists:get_value(where, Select, fun(_)->true end),
-	{Position, _Order} = proplists:get_value(order, Select, {1, descending}),
-
-	Limit = proplists:get_value(limit, Select, all),
-
-	Selected = select(RecordName, Where),
-	Sorted = lists:keysort(Position, Selected),
-
-	case Limit of
-		all ->
-			Sorted;
-		{Offset, Amoumt} ->
-			lists:sublist(Sorted, Offset, Amoumt)
-	end.
-
+    Where = proplists:get_value(where, Select, fun(_)->true end),
+    {Position, _Order} = proplists:get_value(order, Select, {1, descending}),
+    Limit = proplists:get_value(limit, Select, all),
+    Selected = select(RecordName, Where),
+    Sorted = lists:keysort(Position, Selected),
+    case Limit of
+        all -> Sorted;
+        {Offset, Amoumt} -> lists:sublist(Sorted, Offset, Amoumt) end.
 
 count(_RecordName) -> erlang:length(all(_RecordName)).
 
@@ -204,8 +192,6 @@ all(RecordName) ->
     Results = [ get_record_from_table({RecordBin, Key, Riak}) || Key <- Keys ],
     [ Object || Object <- Results, Object =/= failure ].
 
-%% get by index
-
 all_by_index(Tab, IndexId, IndexVal) ->
     Riak = riak_client(),
     Bucket = key_to_bin(Tab),
@@ -213,18 +199,13 @@ all_by_index(Tab, IndexId, IndexVal) ->
     F = fun(Key, Acc) ->
                 case Riak:get(Bucket, Key, []) of
                     {ok, O} -> [riak_object:get_value(O) | Acc];
-                    {error, notfound} -> Acc
-                end
-        end,
+                    {error, notfound} -> Acc end end,
     lists:foldl(F, [], Keys).
 
 get_record_from_table({RecordBin, Key, Riak}) ->
     case Riak:get(RecordBin, Key) of
         {ok,O} -> riak_object:get_value(O);
-        X -> failure
-    end.
-
-% id generator
+        X -> failure end.
 
 next_id(CounterId) -> next_id(CounterId, 1).
 next_id(CounterId, Incr) -> next_id(CounterId, 0, Incr).
@@ -245,446 +226,3 @@ next_id(CounterId, Default, Incr) ->
     case Riak:put(Object, Options) of
         ok -> Value;
         {error, _} -> next_id(CounterId, Incr) end.
-
-% user backlinks
-
-user_by_verification_code(Code) ->
-    case kvs:get(code,Code) of
-        {ok,{_,User,_}} -> kvs:get(user,User);
-        Else -> Else end.
-
-user_by_facebook_id(FBId) ->
-    case kvs:get(facebook,FBId) of
-        {ok,{_,User,_}} -> kvs:get(user,User);
-        Else -> Else end.
-
-user_by_email(Email) ->
-    case kvs:get(email,Email) of
-        {ok,{_,User,_}} -> kvs:get(user,User);
-        Else -> Else end.
-
-user_by_username(Name) ->
-    case X = kvs:get(user,Name) of
-        {ok,_Res} -> X;
-        Else -> Else end.
-
-% feeds
-
-feed_add_direct_message(FId,User,To,EntryId,Desc,Medias) -> feed_add_entry(FId,User,To,EntryId,Desc,Medias,{user,direct},"").
-feed_add_entry(FId,From,EntryId,Desc,Medias) -> feed_add_entry(FId,From,undefined,EntryId,Desc,Medias,{user,normal},"").
-feed_add_entry(FId, User, To, EntryId,Desc,Medias,Type,SharedBy) ->
-    %% prevent adding of duplicate records to feed
-    case kvs:entry_by_id({EntryId, FId}) of
-        {ok, _} -> ok;
-        _ -> do_feed_add_entry(FId, User, To, EntryId, Desc, Medias, Type, SharedBy)
-    end.
-
-do_feed_add_entry(FId, User, To, EntryId, Desc, Medias, Type, SharedBy) ->
-    {ok,Feed} = kvs:get(feed,erlang:integer_to_list(FId)),
-    Id = {EntryId, FId},
-    Next = undefined,
-    Prev = case Feed#feed.top of
-               undefined ->
-                   undefined;
-               X ->
-                   case kvs:get(entry, X) of
-                       {ok, TopEntry} ->
-                           EditedEntry = TopEntry#entry{next = Id},
-                           % update prev entry
-                           kvs:put(EditedEntry),
-                           TopEntry#entry.id;
-                       {error,notfound} ->
-                           undefined
-                   end
-           end,
-
-    kvs:put(#feed{id = FId, top = {EntryId, FId}}), % update feed top with current
-
-    Entry  = #entry{id = {EntryId, FId},
-                    entry_id = EntryId,
-                    feed_id = FId,
-                    from = User,
-                    to = To,
-                    type = Type,
-                    media = Medias,
-                    created_time = now(),
-                    description = Desc,
-                    raw_description = Desc,
-                    shared = SharedBy,
-                    next = Next,
-                    prev = Prev},
-
-    ModEntry = case catch feedformat:format(Entry) of
-                   {_, Reason} ->
-                       ?ERROR("feedformat error: ~p", [Reason]),
-                       Entry;
-                   #entry{} = ME ->
-                       ME
-               end,
-
-    kvs:put(ModEntry),
-    {ok, ModEntry}.
-
-feed_add_comment(FId, User, EntryId, ParentComment, CommentId, Content, Medias) ->
-    FullId = {CommentId, {EntryId, FId}},
-
-    Prev = case ParentComment of
-        undefined ->
-            {ok, Entry} = kvs:entry_by_id({EntryId, FId}),
-            {PrevC, E} = case Entry#entry.comments of
-                        undefined ->
-                            {undefined, Entry#entry{comments_rear = FullId}};
-                        Id ->
-                            {ok, PrevTop} = kvs:get(comment, Id),
-                            kvs:put(PrevTop#comment{next = FullId}),
-                            {Id, Entry}
-                   end,
-
-            kvs:put(E#entry{comments=FullId}),
-            PrevC;
-
-        _ ->
-            {ok, Parent} = kvs:get(comment, {{EntryId, FId}, ParentComment}),
-            {PrevC, CC} = case Parent#comment.comments of
-                        undefined ->
-                            {undefined, Parent#comment{comments_rear = FullId}};
-                        Id ->
-                            {ok, PrevTop} = kvs:get(comment, Id),
-                            kvs:put(PrevTop#comment{next = FullId}),
-                            {Id, Parent}
-                    end,
-            kvs:put(CC#comment{comments = FullId}),
-            PrevC
-    end,
-    Comment = #comment{id = FullId,
-                       author_id = User,
-                       comment_id = CommentId,
-                       entry_id = EntryId,
-                       raw_content = Content,
-                       content = Content,
-                       media = Medias,
-                       create_time = now(),
-                       prev = Prev,
-                       next = undefined
-                      },
-    kvs:put(Comment),
-    {ok, Comment}.
-
-add_transaction_to_user(UserId,Purchase) ->
-    {ok,Team} = case kvs:get(user_transaction, UserId) of
-                     {ok,T} -> {ok,T};
-                     _ -> ?INFO("user_transaction not found"),
-                          Head = #user_transaction{ user = UserId, top = undefined},
-                          {kvs:put(Head),Head}
-                end,
-
-    EntryId = Purchase#transaction.id, %kvs:next_id("membership_purchase",1),
-    Prev = undefined,
-    case Team#user_transaction.top of
-        undefined -> Next = undefined;
-        X -> case kvs:get(transaction, X) of
-                 {ok, TopEntry} ->
-                     Next = TopEntry#transaction.id,
-                     EditedEntry = #transaction {
-                           commit_time = TopEntry#transaction.commit_time,
-                           amount = TopEntry#transaction.amount,
-                           remitter = TopEntry#transaction.remitter,
-                           acceptor = TopEntry#transaction.acceptor,
-                           currency = TopEntry#transaction.currency,
-                           info = TopEntry#transaction.info,
-                           id = TopEntry#transaction.id,
-                           next = TopEntry#transaction.next,
-                           prev = EntryId },
-                    kvs:put(EditedEntry); % update prev entry
-                 {error,notfound} -> Next = undefined
-             end
-    end,
-
-    Entry  = #transaction{id = EntryId,
-                           commit_time = Purchase#transaction.commit_time,
-                           amount = Purchase#transaction.amount,
-                           remitter = Purchase#transaction.remitter,
-                           acceptor = Purchase#transaction.acceptor,
-                           currency = Purchase#transaction.currency,
-                           info = Purchase#transaction.info,
-                           next = Next,
-                           prev = Prev},
-
-    case kvs:put(Entry) of ok -> kvs:put(#user_transaction{ user = UserId, top = EntryId}), {ok, EntryId};
-                              Error -> ?INFO("Cant write transaction"), {failure,Error} end.
-
-add_purchase_to_user(UserId,Purchase) ->
-    {ok,Team} = case kvs:get(user_purchase, UserId) of
-                     {ok,T} -> ?INFO("user_purchase found"), {ok,T};
-                     _ -> ?INFO("user_purchase not found"),
-                          Head = #user_purchase{ user = UserId, top = undefined},
-                          {kvs:put(Head),Head}
-                end,
-
-    EntryId = Purchase#membership_purchase.id, %kvs:next_id("membership_purchase",1),
-    Prev = undefined,
-    case Team#user_purchase.top of
-        undefined -> Next = undefined;
-        X -> case kvs:get(membership_purchase, X) of
-                 {ok, TopEntry} ->
-                     Next = TopEntry#membership_purchase.id,
-                     EditedEntry = #membership_purchase{
-                           external_id = TopEntry#membership_purchase.external_id,
-                           user_id = TopEntry#membership_purchase.user_id,
-                           state = TopEntry#membership_purchase.state,
-                           membership_package = TopEntry#membership_purchase.membership_package,
-                           start_time = TopEntry#membership_purchase.start_time,
-                           end_time = TopEntry#membership_purchase.end_time,
-                           state_log = TopEntry#membership_purchase.state_log,
-                           info = TopEntry#membership_purchase.info,
-                           id = TopEntry#membership_purchase.id,
-                           next = TopEntry#membership_purchase.next,
-                           prev = EntryId},
-                    kvs:put(EditedEntry); % update prev entry
-                 {error,notfound} -> Next = undefined
-             end
-    end,
-
-    kvs:put(#user_purchase{ user = UserId, top = EntryId}), % update team top with current
-
-    Entry  = #membership_purchase{id = EntryId,
-                                  user_id = UserId,
-                                  external_id = Purchase#membership_purchase.external_id,
-                                  state = Purchase#membership_purchase.state,
-                                  membership_package = Purchase#membership_purchase.membership_package,
-                                  start_time = Purchase#membership_purchase.start_time,
-                                  end_time = Purchase#membership_purchase.end_time,
-                                  state_log = Purchase#membership_purchase.state_log,
-                                  info = Purchase#membership_purchase.info,
-                                  next = Next,
-                                  prev = Prev},
-
-    case kvs:put(Entry) of ok -> {ok, EntryId};
-                           Error -> ?INFO("Cant write purchase"), {failure,Error} end.
-
-acl_add_entry(Resource, Accessor, Action) ->
-    Acl = case kvs:get(acl, Resource) of
-              {ok, A} ->
-                  A;
-              %% if acl record wasn't created already
-              {error, notfound} ->
-                  A = #acl{id = Resource, resource=Resource},
-                  kvs:put(A),
-                  A
-          end,
-
-    EntryId = {Accessor, Resource},
-
-    case kvs:get(acl_entry, EntryId) of
-        %% there is no entries for specified Acl and Accessor, we have to add it
-        {error, notfound} ->
-            Next = undefined,
-            Prev = case Acl#acl.top of
-                       undefined ->
-                           undefined;
-
-                       Top ->
-                           case kvs:get(acl_entry, Top) of
-                               {ok, TopEntry} ->
-                                   EditedEntry = TopEntry#acl_entry{next = EntryId},
-                                   kvs:put(EditedEntry), % update prev entry
-                                   TopEntry#acl_entry.id;
-
-                               {error, notfound} ->
-                                   undefined
-                           end
-                   end,
-
-            %% update acl with top of acl entries list
-            kvs:put(Acl#acl{top = EntryId}),
-
-            Entry  = #acl_entry{id = EntryId,
-                                entry_id = EntryId,
-                                accessor = Accessor,
-                                action = Action,
-                                next = Next,
-                                prev = Prev},
-
-            ok = kvs:put(Entry),
-            Entry;
-
-        %% if acl entry for Accessor and Acl is defined - just change action
-        {ok, AclEntry} ->
-            kvs:put(AclEntry#acl_entry{action = Action}),
-            AclEntry
-    end.
-
-
-join_tournament(UserId, TournamentId) ->
-    case kvs:get(user, UserId) of
-        {ok, User} ->
-            GP = case accounts:balance(UserId, points) of
-                     {ok, AS1} -> AS1;
-                     {error, _} -> 0 end,
-            Q = case accounts:balance(UserId,  quota) of
-                     {ok, AS4} -> AS4;
-                     {error, _} -> 0 end,
-            RN = kvs_users:user_realname(UserId),
-            kvs:put(#play_record{
-                 who = UserId,
-                 tournament = TournamentId,
-                 team = User#user.team,
-                 game_id = undefined, 
-		 other = now(),
-                 realname = RN,
-                 points = GP,
-                 quota = Q});
-        _ ->
-            ?INFO(" User ~p not found for joining tournament ~p", [UserId, TournamentId])
-    end.
-
-leave_tournament(UserId, TournamentId) ->
-    case kvs:get(play_record, {UserId, TournamentId}) of
-        {ok, _} -> 
-            kvs:delete(play_record, {UserId, TournamentId}),
-            leave_tournament(UserId, TournamentId); % due to WTF error with old records
-        _ -> ok
-    end.
-
-user_tournaments(UId) -> 
-    kvs:all_by_index(play_record, <<"play_record_who_bin">>, list_to_binary(UId)).
-
-tournament_waiting_queue(TId) ->
-    kvs:all_by_index(play_record, <<"play_record_tournament_bin">>, list_to_binary(integer_to_list(TId))).
-
-
--spec entry_by_id(term()) -> {ok, #entry{}} | {error, not_found}.
-entry_by_id(EntryId) -> kvs:get(entry, EntryId).
-
--spec comment_by_id({{EntryId::term(), FeedId::term()}, CommentId::term()}) -> {ok, #comment{}}.
-comment_by_id(CommentId) -> kvs:get(CommentId).
-
--spec comments_by_entry(EId::{string(), term()}) -> [#comment{}].
-comments_by_entry({EId, FId}) ->
-    case kvs:entry_by_id({EId, FId}) of
-        {ok, #entry{comments_rear = undefined}} ->
-            [];
-        {ok, #entry{comments_rear = First}} ->
-            lists:flatten(read_comments_rev(First));
-        _ ->
-            []
-    end.
-
-purchases(UserId) -> purchases_in_basket(UserId, undefined, 1000).
-
-get_purchases_by_user(UserId, Count, States) -> get_purchases_by_user(UserId, undefined, Count, States).
-get_purchases_by_user(UserId, Start, Count, States) ->
-    List = purchases_in_basket(UserId, Start, Count),
-    case States == all of
-        true -> List;
-        false -> [P||P<-List, lists:member(P#membership_purchase.state, States)]
-    end.
-
-purchases_in_basket(UserId, undefined, PageAmount) ->
-    case kvs:get(user_purchase, UserId) of
-        {ok, O} when O#user_purchase.top =/= undefined -> 
-                                     purchases_in_basket(UserId, O#user_purchase.top, PageAmount);
-        {error, notfound} -> []
-    end;
-purchases_in_basket(UserId, StartFrom, Limit) ->
-    case kvs:get(membership_purchase,StartFrom) of
-        {ok, #membership_purchase{next = N}=P} -> [ P | riak_traversal(membership_purchase, #membership_purchase.next, N, Limit)];
-        X -> []
-    end.
-
-transactions(UserId) -> tx_list(UserId, undefined, 10000).
-
-tx_list(UserId, undefined, PageAmount) ->
-    case kvs:get(user_transaction, UserId) of
-        {ok, O} when O#user_transaction.top =/= undefined -> tx_list(UserId, O#user_transaction.top, PageAmount);
-        {error, notfound} -> []
-    end;
-tx_list(UserId, StartFrom, Limit) ->
-    case kvs:get(transaction,StartFrom) of
-        {ok, #transaction{next = N}=P} -> [ P | riak_traversal(transaction, #transaction.next, N, Limit)];
-        X -> []
-    end.
-
-read_comments(undefined) -> [];
-read_comments([#comment{comments = C} | Rest]) -> [read_comments(C) | read_comments(Rest)];
-read_comments(C) -> riak_traversal(comment, #comment.prev, C, all).
-
-read_comments_rev(undefined) -> [];
-read_comments_rev([#comment{comments = C} | Rest]) -> [read_comments_rev(C) | read_comments_rev(Rest)];
-read_comments_rev(C) -> riak_traversal(comment, #comment.next, C, all).
-
-riak_traversal( _, _, undefined, _) -> [];
-riak_traversal(_, _, _, 0) -> [];
-riak_traversal(RecordType, PrevPos, Next, Count)->
-    case srore_riak:get(RecordType, Next) of
-        {error,notfound} -> [];
-        {ok, R} ->
-            Prev = element(PrevPos, R),
-            Count1 = case Count of C when is_integer(C) -> C - 1; _-> Count end,
-            [R | riak_traversal(RecordType, PrevPos, Prev, Count1)]
-    end.
-
-riak_read_acl_entries(_, undefined, Result) -> Result;
-riak_read_acl_entries(C, Next, Result) ->
-    NextStr = io_lib:format("~p",[Next]),
-    RA = C:get(<<"acl_entry">>,erlang:list_to_binary(NextStr)),
-    case RA of
-         {ok,RO} -> O = riak_object:get_value(RO), riak_read_acl_entries(C, O#acl_entry.prev, Result ++ [O]);
-         {error,notfound} -> Result
-    end.
-
-purge_feed(FeedId) ->
-    {ok,Feed} = kvs:get(feed,FeedId),
-    Removal = riak_entry_traversal(Feed#feed.top, -1),
-    [kvs:delete(entry,Id)||#entry{id=Id}<-Removal],
-    kvs:put(Feed#feed{top=undefined}).
-
-purge_unverified_feeds() ->
-    [purge_feed(FeedId) || #user{feed=FeedId,status=S,email=E} <- kvs:all(user),E==undefined].
-
-riak_entry_traversal(undefined, _) -> [];
-riak_entry_traversal(_, 0) -> [];
-riak_entry_traversal(Next, Count)->
-    case store_riak:get(entry, Next) of
-        {error,notfound} -> [];
-        {ok, R} ->
-            Prev = element(#entry.prev, R),
-            Count1 = case Count of 
-                C when is_integer(C) -> case R#entry.type of
-                    {_, system} -> C;   % temporal entries are entries too, but they shouldn't be counted
-                    {_, system_note} -> C;
-                    _ -> C - 1
-                end;
-                _-> Count 
-            end,
-            [R | riak_entry_traversal(Prev, Count1)]
-    end.
-
-entries_in_feed(FeedId, undefined, PageAmount) ->
-    case kvs:get(feed, FeedId) of
-        {ok, O} -> riak_entry_traversal(O#feed.top, PageAmount);
-        {error, notfound} -> []
-    end;
-entries_in_feed(FeedId, StartFrom, PageAmount) ->
-    %% construct entry unic id
-    case kvs:get(entry,{StartFrom, FeedId}) of
-        {ok, #entry{prev = Prev}} -> riak_entry_traversal(Prev, PageAmount);
-        _ -> []
-    end.
-
-acl_entries(AclId) ->
-    C = riak_client(),
-    [AclStr] = io_lib:format("~p",[AclId]),
-    RA = C:get(<<"acl">>, erlang:list_to_binary(AclStr)),
-    case RA of
-        {ok,RO} ->
-            O = riak_object:get_value(RO),
-            riak_read_acl_entries(C, O#acl.top, []);
-        {error, notfound} -> []
-    end.
-
-
-feed_direct_messages(_FId, Page, PageAmount, CurrentUser, CurrentFId) ->
-    Page, PageAmount, CurrentUser, CurrentFId,
-    [].
-