-
Notifications
You must be signed in to change notification settings - Fork 9
Dev053 - Template render controller #678
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
1cfbbce
1485c11
52ccb92
30c9830
a8e2840
dfa6e93
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,7 +24,10 @@ to_rdf(Id, Context) -> | |
%% - media. | ||
-spec to_rdf(m_rsc:resource(), [module()], z:context()) -> m_rdf:rdf_resource(). | ||
to_rdf(Id, Ontologies, Context) -> | ||
Properties = m_rsc:get_visible(Id, Context), | ||
Properties = case m_rsc:get_visible(Id, Context) of | ||
undefined -> []; | ||
Props -> Props | ||
end, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just for the record, from our slack conversation: This rdf change was sneaked in, unrelated to template render controller. Maybe we need to apply this in a separate pull request; maybe it has been lying around for too long because it potentially fixes bugs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It potentially fixes bugs. Ideally it should have been a separate merge request. |
||
Edges = m_edge:get_edges(Id, Context), | ||
Types = types(proplists:get_value(category_id, Properties), Context), | ||
Triples = lists:flatten( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,42 @@ | ||
mod_ginger_spa | ||
======================== | ||
============== | ||
|
||
Default template and dispatch rules for a single page app. | ||
|
||
_Only routes for which a Ginger resource with the same path exists will be served by the `page.tpl` template. | ||
Other routes should be manually added to the sites dispatch rules._ | ||
|
||
|
||
Template rendering | ||
------------------ | ||
|
||
The `controller_ginger_spa_template` renders templates and returns the result as plain text. | ||
|
||
Pass the template name in the path, example: | ||
|
||
https://example.com/render-template/public/test.tpl | ||
|
||
This renders the template `"public/test.tpl"`. | ||
|
||
Pass arguments via the query string: | ||
|
||
https://example.com/render-template/public/test.tpl?id=1 | ||
|
||
Or in a POST body as `application/x-www-form-urlencoded` or `multipart/form-data`. | ||
|
||
Use the argument `catinclude=1` to render the template using a *catinclude*. | ||
Any `id` argument is always added as `id` to the template arguments (after mapping using `m_rsc:rid/2`), in | ||
this way the `id` is always available and usable for the optional catinclude. | ||
|
||
Security | ||
........ | ||
|
||
As in Zotonic 0.x template models are not access checked there is a security using the name of the template. | ||
|
||
Templates starting with `public/...` can be rendered by anonymous users. | ||
|
||
Templates starting with `member/...` can be rendered by authenticated users. | ||
|
||
Administrators are allowed to render all templates. | ||
robvandenbogaard marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
%% @copyright Driebit BV 2021 | ||
%% @doc Controller to render templates. Post arguments via the query arguments. | ||
|
||
-module(controller_ginger_spa_template). | ||
|
||
-export([init/1, service_available/2, charsets_provided/2, content_types_provided/2]). | ||
-export([allowed_methods/2, resource_exists/2]). | ||
-export([process_post/2, provide_content/2]). | ||
|
||
-include_lib("controller_webmachine_helper.hrl"). | ||
-include_lib("include/zotonic.hrl"). | ||
|
||
init(DispatchArgs) -> {ok, DispatchArgs}. | ||
|
||
service_available(ReqData, DispatchArgs) when is_list(DispatchArgs) -> | ||
Context1 = z_context:new_request(ReqData, DispatchArgs, ?MODULE), | ||
?WM_REPLY(true, Context1). | ||
|
||
allowed_methods(ReqData, Context) -> | ||
{[ 'POST', 'GET', 'HEAD' ], ReqData, Context}. | ||
|
||
charsets_provided(ReqData, Context) -> | ||
{[{"utf-8", fun(X) -> X end}], ReqData, Context}. | ||
|
||
content_types_provided(ReqData, Context) -> | ||
{[{"text/plain", provide_content}], ReqData, Context}. | ||
|
||
resource_exists(ReqData, Context) -> | ||
Context1 = ?WM_REQ(ReqData, Context), | ||
Context2 = z_context:ensure_all(Context1), | ||
?WM_REPLY(true, Context2). | ||
|
||
process_post(ReqData, Context) -> | ||
Context1 = ?WM_REQ(ReqData, Context), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this strictly necessary? Would returning Context2 in resource_exists (which is visited before process_post) not already have the ReqData WM_REQ'ed in? |
||
Result = render(Context1), | ||
ReqData1 = wrq:set_resp_body(Result, ReqData), | ||
{{halt, 200}, ReqData1, Context}. | ||
|
||
provide_content(ReqData, Context) -> | ||
Context1 = ?WM_REQ(ReqData, Context), | ||
Result = render(Context1), | ||
?WM_REPLY(Result, Context1). | ||
|
||
render(Context) -> | ||
case template(Context) of | ||
{ok, Template} -> | ||
Vars = [ | ||
{is_spa_render, true}, | ||
{id, m_rsc:rid(z_context:get_q("id", Context), Context)} | ||
], | ||
Template1 = case is_catinclude(Context) of | ||
true -> {cat, Template}; | ||
false -> Template | ||
end, | ||
{Data, _} = z_template:render_to_iolist(Template1, Vars, Context), | ||
iolist_to_binary(Data); | ||
{error, _} -> | ||
lager:info("[~p] Denied render of template \"~s\"", [ z_context:site(Context), m_req:get(path, Context) ]), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is denied the right wording? If the template is in the url, any raised error would be caused by that there is no matching dispatch rule. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be anything, but I think this is good enough. |
||
<<>> | ||
end. | ||
|
||
is_catinclude(Context) -> | ||
z_convert:to_bool(z_context:get_q("catinclude", Context)). | ||
|
||
template(Context) -> | ||
case z_context:get(template, Context) of | ||
undefined -> | ||
case path(Context) of | ||
"api/render-template/" ++ Template -> | ||
{ok, drop_slash(Template)}; | ||
_ -> | ||
{error, enoent} | ||
end; | ||
Template -> | ||
{ok, Template} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't do the dispatch check when the template path is in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, then it is hard coded in the dispatch rule, so the responsibility of the person programming that dispatch rule. |
||
end. | ||
|
||
drop_slash("/" ++ Path) -> drop_slash(Path); | ||
drop_slash(Path) -> Path. | ||
|
||
path(Context) -> | ||
DispatchPath = z_context:get_q("zotonic_dispatch_path", Context), | ||
lists:flatten( z_utils:combine($/, DispatchPath) ). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
[{home, [], controller_template, [ {template, "page.tpl"}, {id, home} ]}, | ||
{search, ["search"], controller_template, [ {template, "page.tpl"} ]} | ||
{search, ["search"], controller_template, [ {template, "page.tpl"} ]}, | ||
|
||
% Render a template the path is the template, pass arguments via the query post or get | ||
{spa_render, ["api", "render-template", "public", '*' ], controller_ginger_spa_template, []} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. She earlier comment on public/test.tpl, maybe we should make the default spa_render rule specific, for discoverability of the default test template. |
||
]. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
{% debug %} | ||
{% print q.v %} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this should be less dangerous (-looking) default content, without There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The debug just echos what is passed, and afaik all data is escaped. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this change extra or needed for the template render controller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This smuggled in - for compatibility between the Ginger environment and the Zotonic environment.