view release on metacpan or search on metacpan
- Upgraded to DBD::SQLite 1.44.
- Dramatic performance improvement with 'PRAGMA synchronous = OFF' and
'PRAGMA journal_mode=WAL'.
- Improved Ado::Command::adduser documentation.
0.67 2014-10-10
- Fixed failing tests for Ado::Plugin::I18n after upgrade and improved it.
- Added universal exception.html.ep.
- Upgraded to Mojolicious 5.48.
- Added helper to_json to Ado::Plugin::AdoHelpers, same as
Mojo::JSON::to_json.
- Assuming stupidly an UTF-8 terminal for command 'adduser'.
- Defined defaults - stash variables $language and $language_from
in Ado::Plugin::I18n.
0.66 2014-09-30
- Improved Ado::Control::list_for_json() to accept an arrayref of simple hashes.
- Upgraded to Mojolicious 5.47.
- Fixed failing test with Mojolicious 5.47.
- Fixed detection of Ado::Plugin home directory under Windows.
- Upgraded to Mojolicious::Plugin::SemanticUI 0.06.
0.54 2014-07-25
- Implemented experimental Ado::Command::generate::adoplugin.
This command should boost Ado expansion.
- Implemented Ado::Plugin::initialise() to reduce boilerplate code
and improved Ado::Plugin::config().
- Refactored all Ado plugins accordingly.
- Upgraded to Mojolicious 5.17.
0.53 2014-07-20
- Improved Ado::Plugin. Added support for Mojolicious::Plugin::JSONConfig
and arbitrary configuration format per plugin.
- Removed monkey-patched Text::MultiMarkdown code from
Ado::Plugin::MarkdownRenderer. My patch was accepted. Thanks BOBTFISH.
- Upgraded to Text::MultiMarkdown 1.000035.
- Upgraded to Mojolicious 5.15.
0.52 2014-07-13
- Added new MIME type .manifest to apache2htaccess.ep.
Removed rule for external 302 redirects for static files.
Let mod_rewrite just internally rewrite the path.
"release_status" : "stable",
"resources" : {
"bugtracker" : {
"web" : "https://github.com/kberov/Ado/issues"
},
"repository" : {
"url" : "https://github.com/kberov/Ado"
}
},
"version" : "0.935",
"x_serialization_backend" : "JSON::PP version 2.27300"
}
are familiar with Mojolicious.
To ease discussions on Ado further development, a forum was created.
<https://groups.google.com/d/forum/ado-dev>.
REST API
Ado strives for strict separation of concerns. 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(route) is accessible via a browser as "/path/to/resourse" an
returns HTML or using "/path/to/resourse.json" and returns JSON. We follow
closely and elaborate on the recommendations in "RESTful Service Best
Practices" at <http://www.RestApiTutorial.com>. See Ado::Manual::RESTAPI.
PLUGINS
Business-specific applications for an Ado-based system are usually
implemented as plugins. One way to contribute to Ado is by writing
plugins.
Ado plugins work the same way as Mojolicious::Plugins and share the same
common base trough Ado::Plugin which ISA Mojolicious::Plugins. Ado plugins
To ease discussions on Ado further development, a forum was created.
[https://groups.google.com/d/forum/ado-dev](https://groups.google.com/d/forum/ado-dev).
# REST API
Ado strives for strict separation of concerns. 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](https://metacpan.org/pod/Mojolicious). Every resource(route) is
accessible via a browser as `/path/to/resourse` an returns HTML or using
`/path/to/resourse.json` and returns JSON. We follow closely and elaborate
on the recommendations in "RESTful Service Best Practices" at
[http://www.RestApiTutorial.com](http://www.RestApiTutorial.com). See [Ado::Manual::RESTAPI](https://metacpan.org/pod/Ado::Manual::RESTAPI).
# PLUGINS
Business-specific applications for an Ado-based system are usually implemented
as plugins. One way to contribute to [Ado](https://metacpan.org/pod/Ado) is by writing plugins.
Ado plugins work the same way as [Mojolicious::Plugins](https://metacpan.org/pod/Mojolicious::Plugins) and share the same
common base trough [Ado::Plugin](https://metacpan.org/pod/Ado::Plugin) which ISA [Mojolicious::Plugins](https://metacpan.org/pod/Mojolicious::Plugins). Ado
etc/ado-sqlite-schema.sql view on Meta::CPAN
Records older than a week will be be moved every day
from this table to table sessions_old and will be kept
for statistical purposes only.
*/
DROP TABLE IF EXISTS sessions;
CREATE TABLE IF NOT EXISTS sessions (
-- 'Mojo::Util::sha1_hex(id)',
id CHAR(40) PRIMARY KEY,
-- 'Last modification time - last HTTP request. Only for statistics',
tstamp INT(11) NOT NULL DEFAULT 0,
-- 'Session data serialized in JSON and packed with Base64',
sessiondata BLOB NOT NULL
);
DROP TABLE IF EXISTS sessions_old;
CREATE TABLE IF NOT EXISTS sessions_old (
-- 'Mojo::Util::sha1_hex(id)',
id CHAR(40) PRIMARY KEY,
-- 'Last modification time - last HTTP request. Only for statistics',
tstamp INT(11) NOT NULL DEFAULT 0,
-- 'Session data serialized in JSON and packed with Base64',
sessiondata BLOB NOT NULL
);
-- Here we store Intrenationalized messages and labels
DROP TABLE IF EXISTS i18n;
CREATE TABLE i18n (
lang VARCHAR(5) DEFAULT 'en',
msgid VARCHAR(255),
-- files where this message is used
locations TEXT DEFAULT '',
lib/Ado/Control.pm view on Meta::CPAN
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);
Use this method to ensure uniform and predictable representation across all
listing resources. Use the C<$meta> key for arbitrary metadata, specific to
your resource. See L<http://127.0.0.1:3000/ado-users/list.json> for example
output and L<Ado::Control::Ado::Users/list> for the example source.
lib/Ado/Control/Test.pm view on Meta::CPAN
=head2 authenticateduser
Used to test the L<Ado::Plugin::Auth/authenticated> condition.
=head2 bgl10n
Used to test the C<language> helper L<Ado::Plugin::I18n/language>.
=head2 guest
Renders the user C<guest> as JSON.
=head2 index
Alias for C<l10n> action.
=head2 ingroup
Used to test the C<ingroup> condition and L<Ado::Model::Users/by_group_name>.
=head2 l10n
lib/Ado/Manual.pod view on Meta::CPAN
To ease discussions on Ado further development, a forum was created.
L<https://groups.google.com/d/forum/ado-dev>.
=head1 REST API
Ado strives for strict separation of concerns. 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 L<Mojolicious>. Every resource(route) is
accessible via a browser as C</path/to/resourse> an returns HTML or using
C</path/to/resourse.json> and returns JSON. We follow closely and elaborate
on the recommendations in "RESTful Service Best Practices" at
L<http://www.RestApiTutorial.com>. See L<Ado::Manual::RESTAPI>.
=head1 PLUGINS
Business-specific applications for an Ado-based system are usually implemented
as plugins. One way to contribute to L<Ado> is by writing plugins.
Ado plugins work the same way as L<Mojolicious::Plugins> and share the same
common base trough L<Ado::Plugin> which ISA L<Mojolicious::Plugins>. Ado
lib/Ado/Plugin.pm view on Meta::CPAN
# /home/you/dev/Ado-Plugin-Foo/lib/Ado/Plugin/Foo.pm
# /home/you/dev/Ado-Plugin-Foo
$p =~ s|[\\/]lib.+||x
|| return $_[0]->app->home;
return $p;
};
has ext => 'conf';
has config_classes => sub {
{ conf => 'Mojolicious::Plugin::Config',
json => 'Mojolicious::Plugin::JSONConfig',
pl => 'Mojolicious::Plugin::Config'
};
};
sub _get_plugin_config {
my ($self) = @_;
state $app = $self->app;
state $mode = $app->mode;
state $home = $app->home;
state $local_config_dir = catdir($home, 'etc', 'plugins');
lib/Ado/Plugin.pm view on Meta::CPAN
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
Extension used for the plugin specific configuration file. defaults to 'conf';
lib/Ado/Plugin/AdoHelpers.pm view on Meta::CPAN
};
}
sub register {
my ($self, $app, $conf) = shift->initialise(@_);
# Add helpers
$app->helper(user => sub { shift->user(@_) });
# http://irclog.perlgeek.de/mojo/2014-10-03#i_9453021
$app->helper(to_json => sub { Mojo::JSON::to_json($_[1]) });
Mojo::Util::monkey_patch(ref($app), do_sql_file => \&Ado::Plugin::AdoHelpers::do_sql_file);
$app->helper('head_css' => \&_head_css);
$app->helper('head_javascript' => \&_head_javascript);
return $self;
} #end of register
my $file_re = qr/\w+\.\w+(\?.*)?$/;
lib/Ado/Sessions.pm view on Meta::CPAN
package Ado::Sessions;
use Mojo::Base -base;
use Mojo::JSON;
has [qw(cookie_domain secure)];
has cookie_name => 'ado';
has cookie_path => '/';
has default_expiration => 3600;
sub generate_id {
return Mojo::Util::sha1_hex(rand() . $$ . {} . time);
}
lib/Ado/Sessions/Database.pm view on Meta::CPAN
package Ado::Sessions::Database;
use Mojo::Base 'Ado::Sessions';
use Mojo::JSON;
use Mojo::Util qw(b64_decode b64_encode);
use Ado::Model::Sessions;
sub load {
my ($self, $c) = @_;
my $session = {};
my $id = $self->session_id($c) || '';
if ($id) {
my $adosession = Ado::Model::Sessions->find($id);
if ($adosession->data) {
return
unless $session = Mojo::JSON::j(b64_decode $adosession->sessiondata);
}
}
return $self->prepare_load($c, $session);
}
sub store {
my ($self, $c) = @_;
my ($id, $session) = $self->prepare_store($c);
return unless $id;
my $value = b64_encode(Mojo::JSON::encode_json($session), '');
my $adosession = Ado::Model::Sessions->find($id);
if ($adosession->data) {
$adosession->sessiondata($value)->update();
return;
}
Ado::Model::Sessions->create(id => $id, tstamp => time(), sessiondata => $value);
return;
}
lib/Ado/Sessions/Database.pm view on Meta::CPAN
=encoding UTF-8
=head1 NAME
Ado::Sessions::Database - manage sessions stored in the database
=head1 DESCRIPTION
L<Ado::Sessions::Database> manages sessions for
L<Ado>. All data gets serialized with L<Mojo::JSON> and stored
C<Base64> encoded in the database. A cookie or a request parameter can
be used to share the session id between the server and the user agents.
=head1 METHODS
=head2 load
Load session data from database.
=head2 store
lib/Ado/Sessions/File.pm view on Meta::CPAN
sub load {
my ($self, $c) = @_;
my $session = {};
my $id = $self->session_id($c) || '';
my $cookie_file = $self->absfile($id);
if ($id and -e $cookie_file) {
my $sessiondata = path($cookie_file)->slurp();
return
unless $session = Mojo::JSON::j(b64_decode($sessiondata));
}
return $self->prepare_load($c, $session);
}
sub store {
my ($self, $c) = @_;
my ($id, $session) = $self->prepare_store($c);
my $value = b64_encode(Mojo::JSON::encode_json($session), '');
my $file = $self->absfile($id);
path($file)->spurt($value);
chmod(oct('0600'), $file);
return;
}
# TODO
sub cleanup {
# go to session dir
lib/Ado/Sessions/File.pm view on Meta::CPAN
=encoding UTF-8
=head1 NAME
Ado::Sessions::File - manage sessions stored in files
=head1 DESCRIPTION
L<Ado::Sessions::File> manages sessions for
L<Ado>. All data gets serialized with L<Mojo::JSON> and stored
C<Base64> encoded in a file. A cookie or a request parameter can be used to
share the session id between the server and the user agents.
=head1 ATTRIBUTES
L<Ado::Sessions::File> inherits all attributes from
L<Ado::Sessions> and implements the following new ones.
=head2 dstdir
public/js/jquery.cookie.js view on Meta::CPAN
function encode(s) {
return config.raw ? s : encodeURIComponent(s);
}
function decode(s) {
return config.raw ? s : decodeURIComponent(s);
}
function stringifyCookieValue(value) {
return encode(config.json ? JSON.stringify(value) : String(value));
}
function parseCookieValue(s) {
if (s.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape...
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
try {
// Replace server-side written pluses with spaces.
// If we can't decode the cookie, ignore it, it's unusable.
// If we can't parse the cookie, ignore it, it's unusable.
s = decodeURIComponent(s.replace(pluses, ' '));
return config.json ? JSON.parse(s) : s;
} catch(e) {}
}
function read(s, converter) {
var value = config.raw ? s : parseCookieValue(s);
return $.isFunction(converter) ? converter(value) : value;
}
var config = $.cookie = function (key, value, options) {
t/ado/lib/Ado/Plugin/Foo.pm view on Meta::CPAN
#t/ado/lib/Ado/Plugin/Foo.pm
package Ado::Plugin::Foo;
use Mojo::Base 'Ado::Plugin';
# prefer Mojolicious::Plugin::JSONConfig.
has config_classes => sub { {dummy => 'Mojolicious::Plugin::JSONConfig'} };
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 : {})}};
t/ado/lib/Ado/Plugin/Primer.pm view on Meta::CPAN
#t/ado/lib/Ado/Plugin/Primer.pm
package Ado::Plugin::Primer;
use Mojo::Base 'Ado::Plugin';
has config_dir => sub { $_[0]->app->home->rel_file('etc/plugins') };
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...
t/plugin/example-00.t view on Meta::CPAN
'All plugin configs are merged right!'
);
my $primer = $app->plugin('primer', {lelemale => 1});
is_deeply(
$primer->config,
{ foo => "bar",
dev => 1,
lelemale => 1
},
'All plugin JSON configs are merged right!'
);
my $foo = $app->plugin('foo');
is_deeply($foo->config, {foo => "bar"}, 'Changing JSON configs extension works!');
done_testing;
t/pod-spelling.t view on Meta::CPAN
plan(skip_all => $msg);
}
#TODO: Make Lingua::Ispell aware of UTF8
#or find another way to shut up "Wide character in print" warnings
add_stopwords(
qw(
Krasimir Berov ÐÑаÑÐ¸Ð¼Ð¸Ñ ÐеÑов berov Joachim Astel Renee Baecker kumcho
vulcho com ÐÑлÑо ÐеделÑев Nedelchev Valcho http html org metacpan url
urls de ingroup absfile Mojolicious Mojo app apps Foo SQLite ActivePerl
URI OM ORM CPAN ENV CORS REST JSON ERP TODO API STDOUT PLUGIN CMS CMF
SQL CRM WMD JS UI MVC FCGI CGI ISA JavaScript MYDLjE precompiled perldoc
RESTful tstamp linkedin wikipedia accessor accessors seq distro bashrc
perltidy perltidyrc cpan cpanm perl perlbrew auth eg authbar ep wiki
conf plugin plugins yourpluginroute htaccess suexec env ServerName ln
ServerAlias ServerAdmin DocumentRoot UserAgent initialisation camelized
blog uninstall initialise args init bgln dstdir dstfile OAuth2 OAuth ext
)
);
all_pod_files_spelling_ok();
done_testing();