view release on metacpan or search on metacpan
- Improved documentation.
- Cleanups.
- Moved Ado::Control::Ado::Users and
Ado::Control::Ado::Default to Ado::Plugin::Admin distribution.
- Moved generic routes to be always defined last.
0.77 2015-01-24
- Happy Christmass and New Year!
- Applied for Grant from TPF:
http://news.perlfoundation.org/2015/01/grant-proposal-ado---a-rapid-a.html
This proposal will be used as roadmap.
- Fixed typo in Ado::Build SYNOPSIS. Thanks RSAVAGE, WEBY.
- Do not use deprecated in Mojolicious 5.73 $c->render_exception()
and $c->render_not_found(). Use $c->reply->not_found() and
$c->reply->exception() instead.
- Started cleanups:
Removed templates/добÑе/ок.html.ep just to reduce
http://cpants.cpanauthors.org/dist/Ado/errors
- Noted in etc/ado.conf that arbitrary Perl code can be executed
when connecting to the database.
- POD improvements and cleanups.
lib/Ado/Build.pm view on Meta::CPAN
use ExtUtils::Installed;
use ExtUtils::Install;
use parent 'Module::Build';
use Exporter qw( import ); #export functionality to Ado::BuildPlugin etc..
our @EXPORT_OK = qw(
create_build_script process_etc_files do_create_readme
process_public_files process_templates_files
ACTION_perltidy ACTION_submit PERL_DIRS);
sub PERL_DIRS {
state $dirs = [map { catdir($_[0]->base_dir, $_) } qw(bin lib etc t)];
return @$dirs;
}
sub create_build_script {
my $self = shift;
#Deciding where to install
my $prefix = $self->install_base || $self->config('siteprefix');
for my $be (qw(etc public log templates)) {
lib/Ado/Command/generate/apache2htaccess.pm view on Meta::CPAN
has description => "Generates Apache2 .htaccess file.\n";
has usage => sub { shift->extract_usage };
# The next two are more or less stollen from File::Which.
my $IS_DOS = ($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'os2');
sub _which {
my ($self, $basename) = @_;
return $self->{$basename} if $self->{$basename};
my @pathext = ('');
push @pathext, map {lc} split /;/, $ENV{PATHEXT} if $ENV{PATHEXT} && $IS_DOS;
foreach my $path (File::Spec->path($ENV{PATH})) {
foreach my $ext (@pathext) {
my $exe = File::Spec->catfile($path, ($ext ? "$basename.$ext" : $basename));
$exe =~ s|\\|/|g;
return $self->{$basename} = $exe if -e $exe;
}
}
return '';
}
lib/Ado/Control.pm view on Meta::CPAN
}
}
#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,
lib/Ado/Control.pm view on Meta::CPAN
sub list_for_json {
my ($c, $range, $dsc_objects, $meta) = @_;
my $url = $c->url_with(format => $c->stash->{format})->query('limit' => $$range[0]);
my $prev = $$range[1] - $$range[0];
$prev = $prev > 0 ? $prev : 0;
#arrayref of hashes or DSC objects?
my $data =
ref($dsc_objects->[0]) eq 'HASH'
? $dsc_objects
: [map { $_->data } @$dsc_objects];
return {
json => {
#TODO: Strive to implement linking using this reference:
# http://www.iana.org/assignments/link-relations/link-relations.xhtml
query => {offset => $$range[1], limit => $$range[0]},
links => [
{ rel => 'self',
href => "" . $url->query([offset => $$range[1]])
},
lib/Ado/I18n.pm view on Meta::CPAN
ELSE cl.msgstr
END) AS msgstr
-- default language
FROM (SELECT msgid, msgstr FROM i18n WHERE lang=?) d
-- current language
LEFT JOIN (SELECT msgid, msgstr FROM i18n WHERE lang=?) cl
ON (cl.msgid=d.msgid)
SQL
#get messages from database
my %lex = $dbix->query($SQL, $default, $self->language_tag)->map;
{
no strict 'refs'; ## no critic (ProhibitNoStrict)
my $class_lex = ref($self) . '::Lexicon';
%{$class_lex} = (%{$class_lex}, %lex);
};
return;
}
1;
lib/Ado/Model/Users.pm view on Meta::CPAN
#Selects users belonging to a group only.
#returns a list of hashes
sub by_group_name {
my ($class, $group, $limit, $offset) = @_;
state $SQL = $class->SQL('by_group_name') . $CLASS->SQL_LIMIT('?', '?');
$limit //= 500;
$offset //= 0;
my $time = time;
my @a = $class->query($SQL, $group, $time, $time, $limit, $offset);
return map { +{%{$_->data}, name => $_->name} } @a;
}
1;
=pod
=encoding utf8
=head1 NAME
lib/Ado/Model/Users.pm view on Meta::CPAN
#in a template
<h1>Hello, <%=user->name%>!</h1>
#Create a new user.
my $user = Ado::Model::Users->add(login_name=>'petko'...);
#Add the user to a group
$user->add_to_group('cool');
=head1 DESCRIPTION
This class maps to rows in table C<users>.
=head1 ATTRIBUTES
Ado::Model::Users inherits all attributes from Ado::Model
and provides the following.
=head2 name
Readonly. Returns concatenated L</first_name> and L</last_name> of the user
or the username (in case the first two are not available).
lib/Ado/Plugin.pm view on Meta::CPAN
my $config_dir = $self->config_dir;
$self->config_dir($app->home->rel_dir('etc/plugins'));
Defaults to C<etc/plugins> relative to the plugin base directory, see L</home_dir>.
This works both while developing a plugin and after installing the plugin.
=head2 config_classes
Returns a hash reference containing C<file-extension =E<gt> class> pairs.
Used to detect which configuration plugin to use depending on the file extension.
The default mapping is:
{ conf => 'Mojolicious::Plugin::Config',
json => 'Mojolicious::Plugin::JSONConfig',
pl => 'Mojolicious::Plugin::Config'
};
This attribute allows you to use your own configuration plugin as far as it
supports the L<Mojolicious::Plugin::Config> API.
=head2 ext
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
return 1;
}
$app->log->error($@);
return;
}
#next two methods
#(_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;
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
my %args;
if (index($provider->{info_url}, 'google') > -1) {
$args{first_name} = $ui->{given_name};
$args{last_name} = $ui->{family_name};
}
elsif (index($provider->{info_url}, 'facebook') > -1) {
$args{first_name} = $ui->{first_name};
$args{last_name} = $ui->{last_name};
}
#Add another elsif to map different %args to $ui from a new provider
else {
Carp::croak('Unknown provider info_url:' . $provider->{info_url});
}
$args{email} = $ui->{email};
$args{login_name} = $ui->{email};
$args{login_name} =~ s/[\@\.]+//g;
$args{login_password} =
Mojo::Util::sha1_hex($args{login_name} . Ado::Sessions->generate_id());
$args{description} = "Registered via $provider->{info_url}!";
$args{created_by} = $args{changed_by} = 1;
lib/Ado/Plugin/I18n.pm view on Meta::CPAN
% }
% }
% elsif($language_from eq 'cookie'){
% my $language_param = $conf->{language_param};
% foreach my $l(@languages){
% my $active = $l eq $language ? 'active ' : '';
<a class="<%="$l $active" %>button item"
href="<%= url_for; %>" data-content="<%= l($l) %>"
data-language="<%= $l %>"><%=l($l)%></a>
% }
% my $languages_css_selectors = join(', ', map("#language_menu a.$_", @languages));
<script src="/js/jquery.cookie.js"></script>
<script>
$('<%=$languages_css_selectors%>').click(function(){
$.removeCookie('<%=$language_param%>', { path: '/' });
$.cookie('<%=$language_param%>',$(this).data('language'),{
expires: 30, path: '/' });
});
</script>
% }
</div><!-- end div class="dropdown menu" -->
public/doc/en/intro.md view on Meta::CPAN
##Built-in features
Ado is a typical Mojo application. It comes with a configuration file and a model[^2] layer - Mojolicious::Plugin::DSC. An SQLite database is bundled in the distribution at etc/ado.sqlite to get started quickly. All plugins can be disabled and re-ena...
Ado has the following:
1. Configuration file with most of the sensible settings in place, such as controller_class, name-spaces for routes (urls), name-spaces for plugins and commands, session settings, default routes...
2. Ado plugins work the same way as Mojolicious::Plugins and share the same common base trough Ado::Plugin. But they have one small additional feature. They can load their own configuration from `$ENV{MOJO_HOME}/etc/plugins/plugin_name.conf`. Busines...
By default the following plugins are enabled:
1. All Mojolicious plugins which are otherwise enabled by default.
2. Mojolicious::Plugin::Charset â UTF-8.
3. Mojolicious::Plugin::DSC â a plugin which integrates DBIx::Simple::Class in the application. DBIx::Simple::Class is a very lightweight object-relational mapper based on DBIx::Simple. It abstracts the SQL from the programmer still allowing to...
4. Ado::Plugin::Auth is a plugin that authenticates users to an Ado system. Users can be authenticated locally or using (TODO!) Facebook, Google, Twitter and other authentication service-providers. A pre-made login form can be used directly or as a...
5. Ado::Plugin::MarkdownRenderer - Render static files in markdown format. One can create a personal blog or enterprise wiki using static files in markdown format.
3. The following libraries for user-interface development are used:
1. Semantic UI â a CSS and JS framework for development of mobile-ready layouts. Its usage also results in more clean HTML than other popular frameworks.
2. PageDown is the version of Attacklab's Showdown and WMD as used on Stack Overflow and the other Stack Exchange sites. It includes a converter that turns Markdown into HTML, a Markdown editor with realtime preview of the generated HTML, and a few...
4. The following Ado specific commands are available:
1. Ado::Command::adduser allows adding users to an Ado application via a terminal. It also allows adding users to existing or not existing groups. The new group is automatically created.
2. Ado::Command::version shows version information for installed core and optional modules.
1. Last but not least, Ado code is well covered with tests. Special care is taken to avoid accumulating technical debt by having Test::Perl::Critic tests set to level âharshâ. This way the coding style is forced to be consistent across the framew...
public/doc/en/intro.md view on Meta::CPAN
ActivePerl or perlbrew are both fine.
All deployment scenarios described at [Mojolicious/Guides/Cookbook#DEPLOYMENT](http://mojolicio.us/perldoc/Mojolicious/Guides/Cookbook#DEPLOYMENT)
are possible and specific custom deployments can be done.
Ado is not actively tested under Windows, but there is an [Ado PPM package](http://code.activestate.com/ppm/Ado/) for Mac OSX, Linux and Windows maintained by Active State.
##REST API[^rest]
Ado strives for strict separation of concerns (MVC[^2]). The best way to achieve this is to fully separate the client code from the server code. Ado is ideally suited for the purpose thanks to Mojolicious. Every resource is accessible via the REST AP...
##Roadmap
Below are the main activities considered mandatory for implementation to reach version 1.00.
1. Implement Ado::Plugin::I18N with messages loaded from the database (bundled with Ado).
2. Implement Ado::Plugin::Vest â a chat application.
3. Implement Ado::Plugin::CORS â allow Ado UI pieces to be embedded into other sites.
4. Implement Ado::Plugin::Site â end-users front-end.
1. Implement Ado::Plugin::Signup â user registration.
2. Implement Ado::Plugin::Profile â managing users' own profiles.
5. Implement Ado::Plugin::Admin â a web application for managing an Ado system -âControl Panelâ.
1. Implement Ado::Plugin::Domains â controllers for managing a multi-domain site in Control Panel.
t/ado-build.t view on Meta::CPAN
'create_build_script() output ok'
);
my $build_elements = [qw(etc public log templates)];
subtest 'install_paths and build elements' => sub {
my $c = $build->{config};
my $prefix = $c->get('siteprefixexp');
is_deeply(
$build->install_path,
{map { $_ => catdir($prefix, $_) } @$build_elements},
'ok - install paths'
);
my $all_elems = join('', @{$build->build_elements()});
for my $be (@$build_elements) {
like($all_elems, qr/$be/, " build_element $be is present");
}
done_testing();
};
t/ado-build.t view on Meta::CPAN
ok($R->size > 12, 'README.md has size ok');
stdout_is(sub { $build->dispatch('distmeta') }, "Created META.yml and META.json\n",
"distmeta ok");
my $dist_out = qr/
Creating\sAdo-\d+\.\d{2,}\n
Creating\sAdo-\d+\.\d{2,}\.tar.gz\n/x;
stdout_like(sub { $build->dispatch('dist') }, $dist_out, 'ACTION_dist output ok');
my $directories_rx = join $/, map { $_ . '.+?' } $build->PERL_DIRS;
stdout_like(
sub { $build->dispatch('perltidy', verbose => 1) },
qr/$directories_rx\d+\sfiles\.\.\.\nperltidy-ed\sdistribution.\n/msx,
"perltidy --verbose ok"
);
ok(!(grep { $_ =~ /\.bak$/ } @{$build->rscan_dir($build->base_dir)}), 'no .bak files ok');
$build->install_base($tempdir);
templates/partials/apache2htaccess.ep view on Meta::CPAN
#2.2 configuration:
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
#2.4 configuration:
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
# Don't show directory listings for URLs which map to a directory.
Options -Indexes
# Follow symbolic links in this directory.
Options +FollowSymLinks
# Requires mod_expires to be enabled.
<IfModule mod_expires.c>
# Enable expirations.
ExpiresActive On