Skip to content

Commit

Permalink
core: Add properties to acl insert to allow checks on content/collabo…
Browse files Browse the repository at this point in the history
…ration groups
  • Loading branch information
mmzeeman committed Mar 23, 2017
1 parent 583e7f1 commit 2731d34
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 14 deletions.
2 changes: 1 addition & 1 deletion include/zotonic.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@
-define(ACL_VIS_PUBLIC, 0).

%% ACL objects
-record(acl_rsc, {category, mime, size}).
-record(acl_rsc, {category, mime, size, props}).
-record(acl_edge, {
subject_id :: m_rsc:resource(),
predicate :: pos_integer() | atom(),
Expand Down
11 changes: 9 additions & 2 deletions modules/mod_acl_user_groups/support/acl_user_groups_checks.erl
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,15 @@ acl_is_allowed(#acl_is_allowed{action=view, object=Id}, Context) when is_integer
can_rsc(Id, view, Context);
acl_is_allowed(#acl_is_allowed{action=insert, object=#acl_media{mime=Mime, size=Size}}, Context) ->
can_media(Mime, Size, Context);
acl_is_allowed(#acl_is_allowed{action=insert, object=#acl_rsc{category=Cat}}, Context) ->
can_insert(Cat, Context);
acl_is_allowed(#acl_is_allowed{action=insert, object=#acl_rsc{category=Cat, props=Props}}, Context) ->
case proplists:lookup(content_group_id, Props) of
none ->
% No explicit content group given, the resource will end up in the default
% content group of the user.
can_insert(Cat, Context);
{content_group_id, CGId} ->
can_insert_category(CGId, Cat, Context)
end;
acl_is_allowed(#acl_is_allowed{action=insert, object=Cat}, Context) when is_atom(Cat) ->
can_insert(Cat, Context);
acl_is_allowed(#acl_is_allowed{action=update, object=Id}, Context) ->
Expand Down
37 changes: 37 additions & 0 deletions modules/mod_acl_user_groups/tests/mod_acl_user_groups_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,43 @@ person_can_edit_own_resource_test() ->
UserContext = z_acl:logon(Id, Context),
{ok, Id} = m_rsc:update(Id, [{title, "Test"}], UserContext).


person_can_insert_text_in_default_content_group_only_test() ->
Context = context(),

%% Person must be able to insert text into the default user group
m_acl_rule:replace_managed(
[
{rsc, [
{acl_user_group_id, acl_user_group_anonymous},
{content_group_id, default_content_group},
{actions, [insert]},
{is_owner, true},
{category_id, article}
]}
],
?MODULE,
z_acl:sudo(Context)),

%% Wait for ACL rules to be rebuilt
timer:sleep(100),

% Make a new user
{ok, Id} = m_rsc:insert([{category, person}], z_acl:sudo(Context)),
UserContext = z_acl:logon(Id, Context),

%% The user is able to insert a text into the default content group
DefaultContentGroupId = m_rsc:p(default_content_group, id, Context),
{ok, _TextId} = m_rsc:insert([{category, article}, {content_group_id, DefaultContentGroupId}], UserContext),

%% But not in the system content group
SystemContentGroupId = m_rsc:p(system_content_group, id, Context),
?assertThrow({{error, eacces}, _}, m_rsc:insert([{category, article}, {content_group_id, SystemContentGroupId}], UserContext)),

ok.



acl_is_allowed_accepts_rsc_name_object_test() ->
?assertEqual(false, acl_user_groups_checks:acl_is_allowed(#acl_is_allowed{action = insert, object = text}, context())).

Expand Down
15 changes: 9 additions & 6 deletions src/models/m_media.erl
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,8 @@ insert_file(File, Props, Options, Context) ->

insert_file(File, Props, PropsMedia, Options, Context) ->
Mime = proplists:get_value(mime, PropsMedia),
case z_acl:is_allowed(insert, #acl_rsc{category=mime_to_category(Mime)}, Context) andalso
z_acl:is_allowed(insert, #acl_media{mime=Mime, size=filelib:file_size(File)}, Context) of
case z_acl:is_allowed(insert, #acl_rsc{category = mime_to_category(Mime), props = Props}, Context) andalso
z_acl:is_allowed(insert, #acl_media{mime = Mime, size = filelib:file_size(File)}, Context) of
true ->
insert_file_mime_ok(File, Props, PropsMedia, Options, Context);
false ->
Expand All @@ -411,8 +411,11 @@ replace_medium(Medium, RscId, RscProps, Options, Context) ->

update_medium_1(RscId, Medium, RscProps, Options, Context) ->
{mime, Mime} = proplists:lookup(mime, Medium),
{category, Category} = proplists:lookup(category, RscProps),
case z_acl:is_allowed(insert, #acl_rsc{category=Category}, Context) andalso
Category = case proplists:get_value(category, RscProps) of
undefined -> tl(m_rsc:is_a(RscId, Context));
Cat -> Cat
end,
case z_acl:is_allowed(insert, #acl_rsc{category = Category, props = RscProps}, Context) andalso
z_acl:is_allowed(insert, #acl_media{mime=Mime, size=0}, Context) of
true ->
case replace_file_acl_ok(undefined, RscId, RscProps, Medium, Options, Context) of
Expand Down Expand Up @@ -491,8 +494,8 @@ replace_file(File, RscId, Props, MInfo, Opts, Context) ->

replace_file_mime_check(File, RscId, Props, PropsMedia, Opts, Context) ->
Mime = proplists:get_value(mime, PropsMedia),
case z_acl:is_allowed(insert, #acl_rsc{category=mime_to_category(Mime)}, Context) andalso
z_acl:is_allowed(insert, #acl_media{mime=Mime, size=filelib:file_size(File)}, Context) of
case z_acl:is_allowed(insert, #acl_rsc{category = mime_to_category(Mime), props = Props}, Context) andalso
z_acl:is_allowed(insert, #acl_media{mime = Mime, size = filelib:file_size(File)}, Context) of
true ->
replace_file_mime_ok(File, RscId, Props, PropsMedia, Opts, Context);
false ->
Expand Down
10 changes: 5 additions & 5 deletions src/models/m_rsc_update.erl
Original file line number Diff line number Diff line change
Expand Up @@ -616,22 +616,22 @@ throw_if_category_not_allowed(insert_rsc, SafeProps, _True, Context) ->
undefined ->
throw({error, nocategory});
CatId ->
throw_if_category_not_allowed_1(undefined, CatId, Context)
throw_if_category_not_allowed_1(undefined, SafeProps, CatId, Context)
end;
throw_if_category_not_allowed(Id, SafeProps, _True, Context) ->
case proplists:get_value(category_id, SafeProps) of
undefined ->
ok;
CatId ->
PrevCatId = z_db:q1("select category_id from rsc where id = $1", [Id], Context),
throw_if_category_not_allowed_1(PrevCatId, CatId, Context)
throw_if_category_not_allowed_1(PrevCatId, SafeProps, CatId, Context)
end.

throw_if_category_not_allowed_1(CatId, CatId, _Context) ->
throw_if_category_not_allowed_1(CatId, _SafeProps, CatId, _Context) ->
ok;
throw_if_category_not_allowed_1(_PrevCatId, CatId, Context) ->
throw_if_category_not_allowed_1(_PrevCatId, SafeProps, CatId, Context) ->
CategoryName = m_category:id_to_name(CatId, Context),
case z_acl:is_allowed(insert, #acl_rsc{category=CategoryName}, Context) of
case z_acl:is_allowed(insert, #acl_rsc{category = CategoryName, props = SafeProps}, Context) of
true -> ok;
_False -> throw({error, eacces})
end.
Expand Down

0 comments on commit 2731d34

Please sign in to comment.