123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- -module(kvs_group).
- -compile(export_all).
- -include_lib("kvs/include/kvs.hrl").
- -include_lib("kvs/include/user.hrl").
- -include_lib("kvs/include/groups.hrl").
- -include_lib("kvs/include/feeds.hrl").
- -include_lib("kvs/include/accounts.hrl").
- -include_lib("kvs/include/feed_state.hrl").
- -include_lib("kvs/include/config.hrl").
- init(Backend) ->
- ?CREATE_TAB(group_subscription),
- ?CREATE_TAB(group),
- Backend:add_table_index(group_subscription, who),
- Backend:add_table_index(group_subscription, where),
- ok.
- retrieve_groups(User) ->
- case participate(User) of
- [] -> [];
- Gs -> UC_GId = lists:reverse(lists:sort([{members_count(GId), GId} || GId <- Gs])),
- Result = [begin case kvs:get(group,GId) of
- {ok, Group} -> {Group#group.name,GId,UC};
- _ -> undefined end end || {UC, GId} <- UC_GId],
- [X||X<-Result,X/=undefined] end.
- delete(GroupName) ->
- case kvs:get(group,GroupName) of
- {error,_} -> ok;
- {ok, Group} ->
- % mqs:notify([feed, delete, GroupName], empty),
- kvs:delete_by_index(group_subscription, <<"where_bin">>, GroupName),
- [kvs:delete(Feed, Fid) || {Feed, Fid} <- Group#group.feeds],
- kvs:delete(group, GroupName),
- case mqs:open([]) of
- {ok, Channel} ->
- Routes = kvs_users:rk_group_feed(GroupName),
- kvs_users:unbind_group_exchange(Channel, GroupName, Routes),
- mqs_channel:close(Channel);
- {error,Reason} -> error_logger:info_msg("delete group failed: ~p",[Reason]) end end.
- participate(UserName) -> DBA=?DBA,DBA:participate(UserName).
- members(GroupName) -> DBA=?DBA,DBA:members(GroupName).
- owner(UserName, GroupName) ->
- case kvs:get(group, GroupName) of
- {ok,Group} -> case Group#group.owner of UserName -> true; _ -> false end;
- _ -> false end.
- member(UserName, GroupName) ->
- case kvs:get(group_subscription, {UserName, GroupName}) of
- {error, _} -> false;
- {ok,_} -> true end.
- member_type(UserName, GroupName) ->
- case kvs:get(group_subs, {UserName, GroupName}) of
- {error, _} -> not_in_group;
- {ok, #group_subscription{type=Type}} -> Type end.
- add(UserName, GroupName, Type) ->
- kvs:put(#group_subscription{key={UserName,GroupName},who=UserName, where=GroupName, type=Type}),
- {ok, Group} = kvs:get(group, GroupName),
- Users = Group#group.users_count,
- kvs:put(Group#group{users_count = Users + 1}).
- join(UserName,GroupName) ->
- case kvs:get(group,GroupName) of
- {ok, #group{id = GroupName, scope = public}} ->
- add(UserName, GroupName, member),
- {ok, joined};
- {ok, #group{id = GroupName}} ->
- case member_type(UserName, GroupName) of
- member -> {ok, joined};
- req -> {error, already_sent};
- req_rejected -> {error, request_rejected};
- not_in_group -> add(UserName, GroupName, req), {ok, requested};
- _ -> {error, unknown_type} end;
- Error -> Error end.
- leave(UserName,GroupName) ->
- kvs:delete(group_subscription, {UserName, GroupName}),
- case kvs:get(group, GroupName) of
- {error,_} -> error_logger:info_msg("Remove ~p from group failed reading group ~p", [UserName, GroupName]);
- {ok,Group} -> kvs:put(Group#group{users_count = Group#group.users_count - 1}) end.
- approve_request(UserName, GroupName) -> add(UserName, GroupName, member).
- reject_request(UserName, GroupName) -> add(UserName, GroupName, req_rejected).
- member_type(UserName, GroupName, Type) -> msg:notify(["subscription", "user", GroupName, "add_to_group"], {GroupName, UserName, Type}).
- exists(GroupName) -> case kvs:get(group,GroupName) of {ok,_} -> true; _ -> false end.
- coalesce(undefined, B) -> B;
- coalesce(A, _) -> A.
- publicity(GroupName) ->
- case kvs:get(group,GroupName) of
- {error,_} -> no_such_group;
- {ok,Group} -> Group#group.scope end.
- members_count(GroupName) ->
- case kvs:get(group,GroupName) of
- {error,_} -> no_such_group;
- {ok,Group} -> Group#group.users_count end.
- user_has_access(UserName, GroupName) ->
- Type = member_type(UserName, GroupName),
- case kvs:get(group, GroupName) of
- {error,_} -> false;
- {ok,Group} ->
- Publicity = Group#group.scope,
- case {Publicity, Type} of
- {public, _} -> true;
- {private, member} -> true;
- _ -> false end end.
- handle_notice([kvs_group, Owner, add],
- [#group{}=Group],
- #state{owner=Owner}=State) ->
- error_logger:info_msg("[kvs_group] Create group ~p", [Owner]),
- Created = case kvs:add(Group) of {error, E} -> {error, E};
- {ok, #group{id=Id} = G} ->
- Params = [{id, Id}, {type, group}, {feeds, element(#iterator.feeds, G)}],
- case workers_sup:start_child(Params) of {error, E} -> {error, E}; _ -> G end end,
- msg:notify([kvs_group, group, Group#group.id, added], [Created]),
- {noreply, State};
- handle_notice(["kvs_group", "update", GroupName] = Route,
- Message, #state{owner=ThisGroupOwner, type=Type} = State) ->
- error_logger:info_msg("queue_action(~p): update_group: Owner=~p, Route=~p, Message=~p", [self(), {Type, ThisGroupOwner}, Route, Message]),
- {_UId, _GroupUsername, Name, Description, Owner, Publicity} = Message,
- case kvs:get(group, GroupName) of
- {ok, Group} ->
- NewGroup = Group#group{name = coalesce(Name,Group#group.name),
- description = coalesce(Description,Group#group.description),
- scope = coalesce(Publicity,Group#group.scope),
- owner = coalesce(Owner,Group#group.owner)},
- kvs:put(NewGroup);
- {error,Reason} -> error_logger:info_msg("Cannot update group ~p",[Reason]) end,
- {noreply, State};
- handle_notice([kvs_group, Owner, delete],
- [#group{}=P],
- #state{owner=Owner, feeds=Feeds}=State) ->
- error_logger:info_msg("[kvs_group] Delete group ~p ~p", [P#group.id, Owner]),
- Removed = case kvs:remove(P) of {error,E} -> {error,E};
- ok ->
- % todo: handle group feeds?
- supervisor:terminate_child(workers_sup, {group, P#group.id}),
- supervisor:delete_child(workers_sup, {group, P#group.id}),
- P
- end,
- msg:notify([kvs_product, group, P#group.id, deleted], [Removed]),
- {noreply, State};
- handle_notice([kvs_group, join, Owner],
- [{FeedName, Who}, Entry],
- #state{owner = Owner, feeds=Feeds} = State) ->
- error_logger:info_msg("[kvs_group] ~p Join group: ~p", [Who, Owner]),
- join(Who, Owner),
- case lists:keyfind(FeedName, 1, Feeds) of false -> skip;
- {_,Fid} -> msg:notify([kvs_feed, group, Owner, entry, Who, add],
- [Entry#entry{id={Who, Fid},feed_id=Fid,to={group, Owner}}]) end,
- % subscription_mq(group, add, UserName, GroupName),
- {noreply, State};
- handle_notice([kvs_group, leave, Owner],
- [{FeedName, Who}],
- #state{owner = Owner, feeds=Feeds} = State) ->
- error_logger:info_msg("[kvs_group] ~p leave group ~p", [Who, Owner]),
- leave(Who, Owner),
- case lists:keyfind(FeedName, 1, Feeds) of false -> skip;
- {_,Fid} -> msg:notify([kvs_feed, group, Owner, entry, delete], [#entry{id={Who,Fid}, feed_id=Fid}]) end,
- % subscription_mq(group, remove, UserName, GroupName),
- {noreply, State};
- handle_notice(_Route, _Message, State) ->
- % error_logger:info_msg("Unknown GROUP notice"),
- {noreply, State}.
- build_group_relations(Group) -> [
- mqs:key( [kvs_group, create] ),
- mqs:key( [kvs_group, update, Group] ),
- mqs:key( [kvs_group, remove, Group] ),
- mqs:key( [kvs_group, join, Group] ),
- mqs:key( [kvs_group, leave, Group] ),
- mqs:key( [kvs_group, like, Group]), % for comet mostly
- mqs:key( [kvs_feed, delete, Group] ),
- mqs:key( [kvs_feed, group, Group, '*', '*', '*'] )
- ].
- rk_group_feed(Group) -> mqs_lib:list_to_key([kvs_feed, group, Group, '*', '*', '*']).
|