view release on metacpan or search on metacpan
- Fixed bugs related to improper dynamic routes names usage.
- $CODENAME changed to "ÐÐÐ" U+2C0A GLAGOLITIC CAPITAL LETTER INITIAL IZHE (â°).
0.921 2015-06-03
- Fixed query from i18n table to retrieve translated messages.
- Rearranged Plugin::MarkdounRender tests to avoid potential failures.
0.92 2015-06-01
- Ado::Control::list_for_json() accepts a new argument $meta for arbitrary
content, specific to the served resource.
- Removed a lot of debug messages.
- Added database storage for lexicons to Ado::I18n.
Now plugins can store their translated messages in i18n table.
See Ado::Plugin::Vest as example.
- Refactored and improved /articles section.
- Decided not to remove documents from public/doc. They will be used as
end-user documentation and written when time permits.
- $CODENAME changed to "иже" U+2C09 GLAGOLITIC CAPITAL LETTER IZHE (â°)
0.91 2015-05-10
- Upgraded to Mojolicious::Plugin::SemanticUI 0.17 to use only some of
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
: $app->ado_home->rel_file('etc/' . lc($CLASS) . '.conf');
$app->plugin('Config');
return $app;
}
sub load_plugins {
my ($app) = @_;
my $plugins = $app->config('plugins') || [];
foreach my $plugin (@$plugins) {
$app->log->debug('Loading Plugin ' . (ref $plugin ? $plugin->{name} : $plugin));
if (ref $plugin eq 'HASH') {
$app->plugin($plugin->{name} => $plugin->{config});
}
elsif ($plugin) {
$app->plugin($plugin);
}
}
return $app;
}
#load routes defined in ado.conf
sub load_routes {
my ($app, $config_routes) = @_;
$config_routes ||= $app->config('routes') || [];
my $routes = $app->routes;
# Hide Ado::Control methods and attributes from router.
$routes->hide(
qw(
debug config require_format list_for_json
validate_input
)
);
foreach my $route (@$config_routes) {
my ($pattern, $over, $to, $via, $params) =
($route->{route}, $route->{over}, $route->{to}, $route->{via}, $route->{params});
next unless $to;
my $r = $params ? $routes->route($pattern, %$params) : $routes->route($pattern);
lib/Ado/Command/adduser.pm view on Meta::CPAN
utf8::decode($args->{last_name})
if ($args->{last_name} && !utf8::is_utf8($args->{last_name}));
$args->{login_password} = Mojo::Util::sha1_hex($args->{login_name} . $args->{login_password});
unless ($args->{ingroup}) {
say($self->usage)
unless ($args->{first_name}
and $args->{last_name}
and $args->{login_name}
and $args->{email});
}
$self->app->log->debug('$self->args: ' . $self->app->dumper($self->args));
return $ret;
}
#default action
sub adduser {
my $self = shift;
my $args = $self->args;
my ($group, $user, $ingroup);
if (($group = Ado::Model::Groups->by_name($args->{login_name}))->id) {
$self->app->log->debug('$group:', $self->app->dumper($group));
#if we have such group, we have the user or we do not want to give a user
#the privileges of a shared group
say "'$args->{login_name}' is already taken!";
}
else {
$user = Ado::Model::Users->add($args) unless $group->id;
return unless $user;
}
if ($user) {
lib/Ado/Command/generate/crud.pm view on Meta::CPAN
allow => sub { $_[0] =~ /^\d+$/ ? 1 : defined($_[0] = 0); }
},
},
{ limit => $c->req->param('limit') || 20,
offset => $c->req->param('offset') || 0,
}
);
$c->res->headers->content_range(
"<%= $a->{t} %> $$args{offset}-${\($$args{limit} + $$args{offset})}/*");
$c->debug("rendering json and html only [$$args{limit}, $$args{offset}]");
#Used in template <%= $a->{t}%>/list.html.ep
$c->stash('table_class',$table_class);
#content negotiation
my $list = $c->list_for_json(
[$$args{limit}, $$args{offset}],
[$table_class->select_range($$args{limit}, $$args{offset})]
);
return $c->respond_to(
json => $list,
lib/Ado/Command/generate/crud.pm view on Meta::CPAN
eval {
$res = $table_class->create(
title => $v->param('title'),
body => $v->param('body'),
user_id => $c->user->id,
group_id => $c->user->group_id,
deleted => 0,
#permissions => '-rwxr-xr-x',
);
}||$c->stash(error=>$@);#very rude!!!
$c->debug('$error:'.$c->stash('error')) if $c->stash('error');
my $data = $res->data;
return $c->respond_to(
json => {data => $data},
html => {data => $data}
);
}
# Reads a resource from table <%= $a->{t} %>. A naive example.
sub read {
my $c = shift;
#This could be validated by a stricter route
my ($id) = $c->stash('id') =~/(\d+)/;
my $data = $table_class->find($id)->data;
$c->debug('$data:'.$c->dumper($data));
return $c->respond_to(
json => {article => $data},
html => {article => $data}
);
}
# Updates a resource in table <%= $a->{t} %>.
sub update {
my $c = shift;
my $v = $c->validation;
my ($id) = $c->stash('id') =~/(\d+)/;
my $res = $table_class->find($id);
$c->reply->not_found() unless $res->data;
$c->debug('$data:'.$c->dumper($res->data));
if($v->has_data && $res->data){
$v->optional('title')->size(3, 50);
$v->optional('body')->size(3, 1 * 1024 * 1024);#1MB
$res->title($v->param('title'))->body($v->param('body'))
->update() unless $v->has_error;
}
my $data = $res->data;
return $c->respond_to(
json => {article => $data},
lib/Ado/Control.pm view on Meta::CPAN
has keywords => 'SSOT, CRM, ERP, CMS, Perl, SQL';
sub generator { return 'Ado ' . $Ado::VERSION . ' - ' . $Ado::CODENAME }
sub config {
state $app = $_[0]->app;
return $app->config(ref $_[0])->{$_[1]} if $_[1]; #if key
return $app->config(ref $_[0]);
}
sub debug;
if ($DEV_MODE) {
sub debug {
my ($package, $filename, $line, $subroutine) = caller(0);
state $log = $_[0]->app->log;
return $log->debug(
@_[1 .. $#_] #, " at $filename:$line"
);
}
}
#Require a list of formats or render "415 - Unsupported Media Type"
#and return false.
sub require_formats {
my ($c, @formats) = @_;
unless ($c->accepts(@formats)) {
#propose urls with the accepted formats
my @locations = map { $c->url_for(format => $_)->to_abs } @formats;
$c->res->headers->add('Content-Location' => $locations[0]);
my $message =
"415 - Unsupported Media Type \""
. ($c->req->headers->accept // '')
. "\". Please try ${\ join(', ', @locations)}!";
$c->debug($c->url_for . " requires " . join(',', @formats) . ". Rendering: $message")
if $DEV_MODE;
$c->render(
text => $message,
status => 415
);
return;
}
return 1;
}
lib/Ado/Control.pm view on Meta::CPAN
#in Ado::Control::List or Ado::Control::Foo or...
my $myvalue = $c->config('mykey');
#a shortcut to
my $myvalue = $app->config(__PACKAGE__)->{mykey}
...
To access the application-wide configuration use
C<$c-E<gt>app-E<gt>config('key')>.
=head2 debug
A shortcut to:
$c->app->log->debug(@_);
=head2 list_for_json
Prepares a structure suitable for rendering as JSON for listing an ARRAYref
of HASHES or L<Ado::Model>* objects, returned by L<Ado::Model/select_range>
and returns it. Accepts two C<ARRAY> references and one arbitrary C<HASH>
reference as parameters:
my $res = $c->list_for_json([$limit, $offset], \@list_of_AMobjects_or_hashes, $meta);
lib/Ado/Control.pm view on Meta::CPAN
Checks for a list of accepted formats or renders "415 - Unsupported Media
Type" with a text/html type and links to the preferred formats, and returns
false. If the URL is in the required format, returns true. Adds a header C
<Content-Location> pointing to the first URL of the required formats.
#in an action serving only json
sub list {
my $c = shift;
$c->require_formats('json') || return;
$c->debug('rendering json only');
#your stuff here...
return;
}
This method exists only to show more descriptive message with available
formats to the end user and to give a chance to user agents to go to the
preferred resource URL.
=head2 validate_input
lib/Ado/Control/Test.pm view on Meta::CPAN
use Mojo::Base 'Ado::Control';
sub authenticateduser {
return $_[0]->render(text => 'hello authenticated '
. $_[0]->user->name
. (ref($_[0]->session->{adobar_links}) eq 'ARRAY' ? ' with adobar_links' : ''));
}
sub mark_down { return $_[0]->render(text => $_[0]->markdown('* some text')) }
sub l10n {
$_[0]->debug('already set language:' . $_[0]->language);
return $_[0]->render(text => $_[0]->l('hello', $_[0]->user->name));
}
sub bgl10n {
$_[0]->language('bg');
$_[0]->debug('set language inside action:' . $_[0]->language);
return $_[0]->render(text => $_[0]->l('hello', $_[0]->user->name));
}
*index = \&l10n;
#action to test language_menu
sub language_menu {
my ($c) = @_;
#small hack to use embedded template
state $renderer = scalar push @{$c->app->renderer->classes}, __PACKAGE__;
my $stash = $c->stash;
$c->debug('$$stash{language_from}:' . $$stash{language_from});
$$stash{language_from} ||= $c->param('from');
$c->debug('$$stash{language_from}:' . $$stash{language_from});
return $c->render();
}
# Test Ado::Model::Users->by_group_name
sub ingroup {
my $c = shift;
#get users from group with the same name as the user login_name
my @users = Ado::Model::Users->by_group_name($c->user->login_name, $c->param('offset'),
$c->param('limit'));
lib/Ado/Plugin/AdoHelpers.pm view on Meta::CPAN
use Mojo::Base 'Ado::Plugin';
use Mojo::Util qw(decode);
use List::Util qw(first);
use Mojo::File 'path';
# allow plugins to process SQL scripts while loading
sub do_sql_file {
my ($app, $sql_file) = @_;
my $dbh = $app->dbix->dbh;
#$app->log->debug('do_sql_file:' . $sql_file) if $Ado::Control::DEV_MODE;
my $SQL = decode('UTF-8', path($sql_file)->slurp());
#Remove multi-line comments
$SQL =~ s|/\*+.+?\*/\s+?||gsmx;
#$app->log->debug('$SQL:' . $SQL) if $Ado::Control::DEV_MODE;
local $dbh->{RaiseError} = 1;
my $last_statement = '';
return eval {
$dbh->begin_work;
for my $st (split /;/smx, $SQL) {
$last_statement = $st;
$dbh->do($st) if ($st =~ /\S+/smx);
}
$dbh->commit;
} || do {
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
#oauth2 links - helpers after 'ado'
$app->helper(login_google => \&_login_google)
if (List::Util::first { $_ eq 'google' } @auth_methods);
$app->helper(login_facebook => \&_login_facebook)
if (List::Util::first { $_ eq 'google' } @auth_methods);
# Add conditions
$app->routes->add_condition(authenticated => \&authenticated);
$app->routes->add_condition(
ingroup => sub {
$_[1]->debug("is user " . $_[1]->user->name . " in group $_[-1]?")
if $Ado::Control::DEV_MODE;
return $_[1]->user->ingroup($_[-1]);
}
);
$app->hook(
after_user_add => sub {
my ($c, $user, $raw_data) = @_;
$app->log->info($user->description . ' $user->id ' . $user->id . ' added!');
$c->debug('new user created with arguments:' . $c->dumper($user->data, $raw_data))
if $Ado::Control::DEV_MODE;
}
);
$app->hook(
after_login => sub {
my ($c) = @_;
$c->session(adobar_links => []);
# Store a friendly message for the next page in flash
$c->flash(login_message => $c->l('LoginThanks'));
}
);
return $self;
}
# general condition for authenticating users - redirects to /login
sub authenticated {
my ($route, $c) = @_;
$c->debug('in condition "authenticated"') if $Ado::Control::DEV_MODE;
if ($c->user->login_name eq 'guest') {
$c->session(over_route => $c->req->url);
$c->debug('session(over_route => $c->req->url):' . $c->session('over_route'))
if $Ado::Control::DEV_MODE;
$c->redirect_to('/login');
return;
}
return 1;
}
#expires the session.
sub logout {
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
my ($c) = @_;
#TODO: add json format
#prepare redirect url for after login
unless ($c->session('over_route')) {
my $base_url = $c->url_for('/')->base;
my $referrer = $c->req->headers->referrer // $base_url;
$referrer = $base_url unless $referrer =~ m|^$base_url|;
$c->session('over_route' => $referrer);
$c->debug('over_route is ' . $referrer) if $Ado::Control::DEV_MODE;
}
my $auth_method = Mojo::Util::trim($c->param('auth_method'));
return $c->render(status => 200, template => 'login')
if $c->req->method ne 'POST' && $auth_method eq 'ado';
#derive a helper name for login the user
my $login_helper = 'login_' . $auth_method;
$c->debug('Chosen $login_helper: ' . $login_helper) if $Ado::Control::DEV_MODE;
my $authnticated = 0;
if (eval { $authnticated = $c->$login_helper(); 1 }) {
if ($authnticated) {
$c->app->plugins->emit_hook(after_login => $c);
# Redirect to referrer page with a 302 response
$c->debug('redirecting to ' . $c->session('over_route'))
if $Ado::Control::DEV_MODE;
$c->redirect_to($c->session('over_route'));
return;
}
else {
unless ($c->res->code // '' eq '403') {
$c->stash(error_login => 'Wrong credentials! Please try again!');
$c->render(status => 401, template => 'login');
return;
}
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
#3. really authnticate the user
my $checksum = Mojo::Util::sha1_hex($c->session->{csrf_token} . $user->login_password);
if ($checksum eq $val->param('digest')) {
$c->session(login_name => $user->login_name);
$c->user($user);
$c->app->log->info('$user ' . $user->login_name . ' logged in!');
delete $c->session->{csrf_token};
return 1;
}
$c->debug('We should not be here! - wrong password') if $Ado::Control::DEV_MODE;
delete $c->session->{csrf_token};
return '';
}
#used as helper within login()
# this method is called as return_url after the user
# agrees or denies access for the application
sub _login_google {
my ($c) = @_;
state $app = $c->app;
my $provider = $c->param('auth_method');
my $providers = $app->config('Ado::Plugin::Auth')->{providers};
#second call should get the token it self
my $response = $c->oauth2->get_token($provider, $providers->{$provider});
do {
$c->debug("in _login_google \$response: " . $c->dumper($response));
$c->debug("in _login_google error from provider: " . ($c->param('error') || 'no error'));
} if $Ado::Control::DEV_MODE;
if ($response->{access_token}) { #Athenticate, create and login the user.
return _create_or_authenticate_google_user(
$c,
$response->{access_token},
$providers->{$provider}
);
}
else {
#Redirect to front-page and say sorry
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
# agrees or denies access for the application
sub _login_facebook {
my ($c) = @_;
state $app = $c->app;
my $provider = $c->param('auth_method');
my $providers = $app->config('Ado::Plugin::Auth')->{providers};
#second call should get the token it self
my $response = $c->oauth2->get_token($provider, $providers->{$provider});
do {
$c->debug("in _login_facebook \$response: " . $c->dumper($response));
$c->debug(
"in _login_facebook error from provider: " . ($c->param('error') || 'no error'));
} if $Ado::Control::DEV_MODE;
if ($response->{access_token}) { #Athenticate, create and login the user.
return _create_or_authenticate_facebook_user(
$c,
$response->{access_token},
$providers->{$provider}
);
}
else {
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
#(_create_or_authenticate_facebook_user and _create_or_authenticate_google_user)
# exist only because we pass different parameters in the form
# which are specific to the provider.
# TODO: think of a way to map the generation of the form arguments to the
# specific provider so we can dramatically reduce the number of provider
# specific subroutines
sub _create_or_authenticate_facebook_user {
my ($c, $access_token, $provider) = @_;
my $ua = Mojo::UserAgent->new;
my $appsecret_proof = Digest::SHA::hmac_sha256_hex($access_token, $provider->{secret});
$c->debug('$appsecret_proof:' . $appsecret_proof);
my $user_info =
$ua->get($provider->{info_url},
form => {access_token => $access_token, appsecret_proof => $appsecret_proof})->res->json;
$c->debug('Response from info_url:' . $c->dumper($user_info)) if $Ado::Control::DEV_MODE;
my $user = Ado::Model::Users->by_email($user_info->{email});
my $time = time;
if ($user->id) {
return _authenticate_oauth2_user($c, $user, $time);
}
#else create the user
return _create_oauth2_user($c, $user_info, $provider);
lib/Ado/Plugin/I18n.pm view on Meta::CPAN
my ($c, $language) = @_;
state $config = $c->app->config(__PACKAGE__);
state $l_param = $$config{language_param};
my $stash = $c->stash;
#language('fr') should be used in very
#rare cases since it is called in around_action
if ($language) {
$stash->{i18n} =
$$config{namespace}->get_handle($language, $c, $config);
$c->debug("explicitly set by developer.");
return $stash->{$l_param} = $language;
}
#already set from route or called in an action as: $c->language()
if ($stash->{$l_param}) {
$stash->{i18n}
||= $$config{namespace}->get_handle($stash->{$l_param}, $c, $config);
$c->debug("already set in \$stash->{$l_param}:");
return $stash->{$l_param};
}
#bg.example.com
if ($$config{language_from_host}
&& (my ($l) = $c->req->headers->host =~ /^(\w{2})\./))
{
$stash->{i18n} =
$$config{namespace}->get_handle($l, $c, $config);
$stash->{language_from} = 'host';
lib/Ado/Plugin/I18n.pm view on Meta::CPAN
#Accept-Language:"bg,fr;q=0.8,en-us;q=0.5,en;q=0.3"
elsif (!$stash->{$l_param} && $$config{language_from_headers}) {
my @languages =
I18N::LangTags::implicate_supers(
I18N::LangTags::Detect->http_accept_langs($c->req->headers->accept_language));
foreach my $l (@languages) {
$stash->{$l_param} = List::Util::first { $_ =~ /$l/ } @{$$config{languages}};
last if $stash->{$l_param};
}
$c->debug("language_from_headers:$stash->{$l_param}") if $stash->{$l_param};
}
#default
$stash->{$l_param} = $$config{default_language} unless $stash->{$l_param};
$stash->{i18n} =
$$config{namespace}->get_handle($stash->{$l_param}, $c, $config);
return $stash->{$l_param};
}
sub _maketext {
lib/Ado/Plugin/I18n.pm view on Meta::CPAN
@@ partials/language_menu.html.ep
%# This template is inflated from Ado::Plugin::I18n.
%# It Displays menu items with flags.
%# You can experiment and make it as one dropdown menu item.
%# See http://localhost:3000/perldoc/Ado/Plugin/I18n#partialslanguage_menuhtmlep
% my $stash = $self->stash;
% my $conf = config('Ado::Plugin::I18n');
% my @languages = @{$conf->{languages}};
% $language_from ||= 'route';
% #$c->debug('$language_from:' . $language_from);
% $language ||= $conf->{default_language};
<!-- language_menu start -->
<!-- language_from: <%=$language_from%> -->
<% head_css([$sui_path.'/menu.min.css', $sui_path.'/dropdown.min.css',
$sui_path.'/item.min.css',$sui_path.'/icon.min.css',
$sui_path.'/button.min.css']);
head_javascript($sui_path.'/dropdown.min.js'); %>
<div class="right compact menu" id="language_menu">
<div class="ui simple dropdown item">
lib/Ado/Plugin/MarkdownRenderer.pm view on Meta::CPAN
}
sub md_to_html {
my ($c, $config, $file_path) = @_;
$file_path ||= ($c->stash('md_file') || return '');
#remove anchors
$file_path =~ s{[^#]#.+}{};
unless ($file_path) { $c->reply->not_found() && return '' }
my $fullname = catfile($config->{md_root}, $file_path);
$c->debug("md_file: $file_path; \$fullname: $fullname");
my ($name, $path, $suffix) = fileparse($fullname, @{$config->{md_file_sufixes}});
my $html_filepath = catfile($path, "$name.html");
#Reuse previously produced html file if md_file is older than the html file.
if ( $config->{md_reuse_produced_html}
&& -s $html_filepath
&& (stat($fullname))[9] < (stat($html_filepath))[9])
{
$c->debug('Found ' . $html_filepath);
return b(path($html_filepath)->slurp)->decode;
}
#404 Not Found
my $md_filepath = catfile($path, "$name$suffix");
unless (-s $md_filepath) { $c->reply->not_found() && return '' }
my $markdown = path($md_filepath)->slurp;
my $self_url = $c->url_for()->to_string;
my %options = (%{$config->{md_options}}, self_url => $self_url);
my $html = $c->markdown($markdown, \%options);
$c->debug($c->dumper({'%options' => \%options, '$html_filepath' => $html_filepath}));
path($html_filepath)->spurt($html);
return b($html)->decode;
}
1;
=pod
=encoding utf8
lib/Ado/Plugin/Routes.pm view on Meta::CPAN
package Ado::Plugin::Routes;
use Mojo::Base 'Ado::Plugin';
sub register {
my ($self, $app, $conf) = shift->initialise(@_);
#Add some conditions: Someday
# $app->routes->add_condition(
# require_formats => sub {
# my ($route, $c, $captures, $formats) = @_;
# $c->debug('$route, $c, $captures, $formats:'
# . $c->dumper( $route, ref $c, $captures, $formats));
# #Carp::cluck(caller);
# return ($c->require_formats($formats) ? 1 : undef);
# }
# );
# Rewrite urls in case we are deployed under Apache and using mod_cgi or mod_fcgid.
# This way we have the same urls as if deployed standalone or with hypnotoad.
# See templates/partials/apache2htaccess.ep
$app->hook(
t/ado/lib/Ado/Plugin/Example.pm view on Meta::CPAN
package Ado::Plugin::Example;
use Mojo::Base 'Ado::Plugin';
sub register {
my ($self, $app, $config) = @_;
$self->app($app); #!Needed in $self->config!
# Merge passed configuration (usually from etc/ado.conf) with configuration
# from etc/plugins/example(.mode?).conf
$config = $self->{config} = {%{$self->config}, %{$config ? $config : {}}};
$app->log->debug('Plugin ' . $self->name . ' configuration:' . $app->dumper($config));
# Do plugin specific stuff
return $self;
}
1;
t/ado/lib/Ado/Plugin/Foo.pm view on Meta::CPAN
sub register {
my ($self, $app, $config) = @_;
$self->ext('dummy'); # Set explicitly the extension for the configuration file.
$self->app($app); #!Needed in $self->config!
# Merge passed configuration (usually from etc/ado.conf) with configuration
# from etc/plugins/example(.mode?).conf
$config = $self->{config} = {%{$self->config}, %{($config ? $config : {})}};
$app->log->debug('Plugin ' . $self->name . ' configuration:' . $app->dumper($config));
# Do plugin specific stuff
# here...
# ...
return $self;
}
1;
t/ado/lib/Ado/Plugin/Primer.pm view on Meta::CPAN
sub register {
my ($self, $app, $config) = @_;
# prefer Mojolicious::Plugin::JSONConfig.
$self->ext('json'); # Set the extension for the configuration file.
$self->app($app); #!Needed in $self->config!
# Merge passed configuration (usually from etc/ado.conf) with configuration
# from etc/plugins/example(.mode?).conf
$config = $self->{config} = {%{$self->config}, %{$config ? $config : {}}};
$app->log->debug('Plugin ' . $self->name . ' configuration:' . $app->dumper($config));
# Do plugin specific stuff
# here...
# ...
return $self;
}
1;
templates/partials/apache2vhost.ep view on Meta::CPAN
<IfModule mod_suexec.c>
# Make sure to set the proper user and group
SuexecUserGroup <%= $$args{user} %> <%= $$args{group} %>
</IfModule>
% }
ServerName <%=$$args{ServerName}%>
ServerAlias <%=$$args{ServerAlias}%>
ServerAdmin <%=$$args{ServerAdmin}%>
DocumentRoot <%=$$args{DocumentRoot}%>
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn rewrite:trace3
LogLevel debug
ErrorLog <%=$$args{DocumentRoot}%>/log/apache2_error.log
CustomLog <%=$$args{DocumentRoot}%>/log/apache2_access.log combined
# Use .htaccess files for overriding and never show them.
AccessFileName .htaccess
<FilesMatch "^\.ht">
#2.2 configuration:
<IfModule !mod_authz_core.c>
Order deny,allow