view release on metacpan or search on metacpan
.perltidyrc view on Meta::CPAN
-bt=1 # Medium brace tightness
-sbt=1 # Medium square bracket tightness
-bbt=1 # Medium block brace tightness
-nsfs # No space before semicolons
-nolq # Don't outdent long quoted strings
-wbb="% + - * / x != == >= <= =~ < > | & **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x="
# Break before all operators
# Extras/overrides/deviations from Perl Best Practices
--warning-output # Show warnings
--maximum-consecutive-blank-lines=2 # Default is 1
--nohanging-side-comments # Troublesome for commented out code
-isbc # Block comments may only be indented if they have some space characters before the #
# We use version control, so just rewrite the file and do not keep backup if there are no errors
-b -bext='/'
# For the up-tight folk :)
-pt=2 # High parenthesis tightness
-bt=2 # High brace tightness
-sbt=2 # High square bracket tightness
- 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
Semantic UI components. This way the first rendering of the default
page is faster on the browser side.
- Implemented header_css and header_javascript helpers to add minimalistic asset
management. Used to refer specific Semantic UI components from templates
and render links to them in the <head> section of the default layout.
- The /help section is deprecated and will be removed in the next release.
- Other cleanups...
0.901 2015-05-01
- Fixed bug in Ado::Plugin::Auth. Now you can disable local authentication
and use only OAuth2 authentication methods.
- Tested and works with Mojolicious 6.10.
- Cleaned up some (now seeming meaningless) TODOs.
0.90 2015-04-26
- Using $app->moniker instead of hardcodded 'ado' in
0.49 2014-07-03
- Fixed again failing tests on Windows ("The getpwuid function is unimplemented").
- Added support for mode specific plugin configuration files.
- Preferred Plack + FCGI + FCGI::ProcManager over Mojo::Server::FastCGI and
improved apache2htaccess.ep.
0.48 2014-06-29
- Fixed again failing tests on Windows.
Replaced backslashes with forward slashes.
- Moved most of the INSTALL section from READMEs
to Ado::Manual::Installation.
- Made READMEs smaller.
- Upgraded to Mojolicious 5.10.
0.47 2014-06-18
- $CODENAME changed to
"Ðлаголи" - U+2C03 GLAGOLITIC CAPITAL LETTER GLAGOLI (â°)
- No more major features (plugins, commands) will be added to Ado for now.
Ado core will be polished, made more stable and some
of the current features and assets will eventually go to plugins.
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
etc/ado-sqlite-schema.sql view on Meta::CPAN
login_password varchar(40) NOT NULL,
first_name varchar(100) NOT NULL DEFAULT '',
last_name varchar(100) NOT NULL DEFAULT '',
email varchar(255) NOT NULL UNIQUE,
description varchar(255) DEFAULT NULL,
-- 'id of who created this user.'
created_by INTEGER REFERENCES users(id),
-- 'Who modified this user the last time?'
changed_by INTEGER REFERENCES users(id),
-- 'last modification time'
-- 'All dates are stored as seconds since the epoch(1970) in GMT. In Perl we use gmtime as object from Time::Piece'
tstamp INTEGER NOT NULL DEFAULT 0,
-- 'registration time',,
reg_date INTEGER NOT NULL DEFAULT 0,
disabled INT(1) NOT NULL DEFAULT 1,
start_date INTEGER NOT NULL DEFAULT 0,
stop_date INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX user_start_date ON users(start_date);
CREATE INDEX user_stop_date ON users(stop_date);
etc/ado.conf view on Meta::CPAN
#This is the default Ado (Mojolicious) application configuration file.
#Application instance is also available here via "app" Mojolicious specific keyword.
#Documentation can be accessed at http://localhost:3000/perldoc/
#The operating mode for your application, defaults to a value
#from the MOJO_MODE and PLACK_ENV environment variables or 'development'.
#See /perldoc/Mojolicious/#mode
#Uncomment the line below to change it to 'production'.
#app->mode('production');
#Fallback to some default secret for this deployment
#See /perldoc/Mojolicious#secrets
#app->secrets([Mojo::Util::sha1_sum($mode . $home),]);
#Application/site specific templates
#See /perldoc/Mojolicious/Renderer#paths
#unshift @{app->renderer->paths}, $home->rel_dir('site_templates');
#Application specific static files
#See /perldoc/Mojolicious/Static
#It is better to leave static files to be served by a server like Apache
#This setting can be used during development.
#unshift @{$app->static->paths}, app->home->rel_dir('path/to/other/public/files');
etc/plugins/auth.conf view on Meta::CPAN
# to auth.development.conf or auth.production.conf only
# because this is highly sensitive and application specific information.
# Get the credentials from
# https://console.developers.google.com/project/yourproject/apiui/credential
# See https://developers.google.com/accounts/docs/OAuth2UserAgent
# https://developers.google.com/oauthplayground/
#Example for google:
# google =>{
# #client_id
# key =>'123456654321abcd.apps.googleusercontent.com',
# secret =>'Y0uRS3cretHEre',
# scope=>'profile email',
# info_url => 'https://www.googleapis.com/userinfo/v2/me',
# },
},
#Add your routes definitions here.
routes => [
#the login form and authentication
{ route => '/login/:auth_method',
etc/plugins/markdown_renderer.conf view on Meta::CPAN
use strict;
use warnings;
use utf8;
#$MOJO_HOME/etc/plugins/markdown_renderer.conf
#Default configuration for Ado::Plugin::MarkdownRenderer
{ md_renderer => 'Text::MultiMarkdown',
#Can be a method name or CODEREF.
#First paramether is the md_renderer instance and
#the second is the markdown text
md_method => 'markdown',
#md_method => sub {shift->markdown(shift)},
#These options will be passed to the md_renderer constructor
md_options => {use_wikilinks => 0, disable_footnotes => 0},
#Where the files reside?
md_root => app->home->rel_file('public/doc'),
md_file_sufixes => ['.md'],
my $templates_dir = $ado_home->rel_file('templates');
my $site_templates = $home->rel_file('site_templates');
my $renderer_paths = $app->renderer->paths;
my $public_dir = $ado_home->rel_file('public');
my $static_paths = $app->static->paths;
push @$renderer_paths, $templates_dir
unless (first { $_ eq $templates_dir } @$renderer_paths);
push @$static_paths, $public_dir
unless (first { $_ eq $public_dir } @$static_paths);
$app->secrets([Mojo::Util::sha1_sum($app->moniker . $mode . $home),]);
unshift @$renderer_paths, $site_templates if -d $site_templates;
$app->controller_class("${CLASS}::Control");
$app->routes->namespaces(["${CLASS}::Control"]);
$app->plugins->namespaces(['Mojolicious::Plugin', "${CLASS}::Plugin",]);
unshift @{$app->commands->namespaces}, "${CLASS}::Command";
return $app;
}
# This method will run once at server start
sub startup {
=head1 METHODS
Ado inherits all methods from Mojolicious and implements
the following new ones.
=head2 startup
Sets various default paths like C<templates>, C<site_templates>, C<public>.
Defines L<Mojolicious/secrets> as sha1_sum of C<$moniker.$mode. $home>. Sets
L<Mojolicious/controller_class> and L<Mojolicious::Routes/namespaces> to
L<${CLASS}::Control>. Sets L<Mojolicious::Plugins/namespaces> to
C<['Mojolicious::Plugin', "${CLASS}::Plugin"]>. Sets
L<Mojolicious::Commands/namespaces> to C<${CLASS}::Command>. C<$CLASS> is
usually L<Ado>. Then calls the following methods in the order they are listed.
Returns void.
You can amend this behavior in the application configuration file.
=head2 load_config
inherit from L<Ado::Plugin> which C<ISA> L<Mojolicious::Plugin>. Of course
Mojolicious plugins can be used - we count on this. There are plenty of
examples on CPAN. Returns $app.
=head2 load_routes
Does not accept any parameters. Loads predefined routes from
C<$config-E<gt>routes>. C<$config-E<gt>routes> is an C<ARRAYREF> in which each
element is a C<HASHREF> with keys corresponding to a method name and value the
parameters that will be passed to the method. Currently we use the C<route>
value to pass it to L<Mojolicious::Routes/route>,C<params> value is the second
parameter to instantiate the route. C<via> and C<to> values are passed to the
newly created route. See L<Mojolicious::Routes::Route> and
L<Mojolicious::Guides::Routing> for more.
Returns $app.
=head2 define_mime_types
Defines any MIME types listed in C<ado.conf> in C<types =E<gt> {...}>. Returns
$app.
lib/Ado/Command.pm view on Meta::CPAN
sub _get_command_config {
my ($self) = @_;
state $app = $self->app;
my $name = $self->name;
#first try (global config) !!!autovivification
my $config = $app->config->{commands} && $app->config->{commands}->{$name};
$config && return $config;
#second try (command specific configuration file)
my $conf_file = $app->home->rel_file('/etc/commands/' . decamelize($name) . '.conf');
if ($config = eval { Mojolicious::Plugin::Config->new->load($conf_file, {}, $app) }) {
return $config;
}
else {
$app->log->warn(
"Could not load configuration from file $conf_file! " . decode('UTF-8', $@));
return {};
}
}
lib/Ado/Command/generate/apache2htaccess.pm view on Meta::CPAN
If not provided the configuration is printed to the screen.
=head3 v|verbose
Verbose output.
=head2 M|modules=s@
Apache modules to use for running C<ado>. Currently supported modules are
C<mod_cgi> and C<mod_fcgid>. You can mention them both to add the corresponding
sections and Apache will use C<mod_fcgid> if loaded or C<mod_cgi>
(almost always enabled).
The generated configuration for mod_fcgid will use L<Plack> (C<plackup>) or
L<Mojo::Server::FastCGI>. So make sure you have at least one of them installed.
L<Plack> is recommended.
To use L<Plack> with C<mod_fcgid> you will need to install
L<FCGI>, L<FCGI::ProcManager> and L<Apache::LogFormat::Compiler>.
=head1 ATTRIBUTES
L<Ado::Command::generate::apache2htaccess> inherits all attributes from
lib/Ado/Command/generate/crud.pm view on Meta::CPAN
Short description of this command, used for the command list.
=head2 routes
$self->routtes();
Returns an ARRAY reference containing routes, prepared after C<$self-E<gt>args-E<gt>{tables}>.
Altough L<Ado> already has defined generic routes for CRUD,
this attribute contains more specific routes, that will secure the C<create>,
C<update> and C<delete> actions, so they are available only to an
authenticated user. This attribute is used for generating routes in
L<Ado::Command::generate::adoplugin>.
After generating a plugin you should end up with a
L<RESTful|http://en.wikipedia.org/wiki/REST>
service. The generated code uses
L<Mojolicious::Controller/respond_to>. For details see
L<Mojolicious::Guides::Rendering/Content-negotiation>.
=head2 usage
lib/Ado/Command/generate/crud.pm view on Meta::CPAN
L<Ado::Command::generate::crud> inherits all methods from
L<Ado::Command> and implements the following new ones.
=head2 initialise
sub run {
my ($self) = shift->initialise(@_);
#...
}
Parses arguments and prepares the command to be run. Calling this method for the second time has no effect.
Returns C<$self>.
=head2 run
Ado::Command::generate::crud->new(app=>$app)->run(@ARGV);
Run this command.
=head1 SEE ALSO
lib/Ado/Command/generate/crud.pm view on Meta::CPAN
@@ create_template
% $a = shift;
<article>
Create your form for creating a resource here.
</article>
@@ read_template
% $a = shift;
<article id="<%%= $article->{id} %>">
<h1><%%= $article->{title} %></h1>
<section><%%= $article->{body} %></section>
</article>
@@ update_template
% $a = shift;
<article>
Create your form for updating a resource here.
</article>
@@ delete_template
% $a = shift;
<article>
<section class="ui error form segment"><%%= $message %></section>
</article>
lib/Ado/Control.pm view on Meta::CPAN
#400 Bad Request
return $c->render(
status => 400,
json => $result->{json}
) if $result->{errors};
=head2 user
Returns the current user. This is the user C<guest> for not authenticated
users. Note that this instance is not meant for manipulation and some fields
are not available for security reasons. The fields are: C<login_password
created_by changed_by disabled start_date>. TODO: move as much as possible
checks and fields retrieval in SQL, not in Perl.
$c->user(Ado::Model::Users->by_login_name($login_name));
my $names = $c->user->name;
=head1 SEE ALSO
lib/Ado/Manual/FiveMinutes.pod view on Meta::CPAN
md_reuse_produced_html => 1,
};
Refresh L<http://127.0.0.1:3000/articles/my_article.html>. In C<~/ado/public/articles> You will find C<my_article.html>.
Congratulations! You created your first article with L<Ado> without much ado.
=head1 WHAT'S NEXT
Look at the source of L<Ado::Control::Articles> to see how it works. Go to
L<http://127.0.0.1:3000/> and play more or visit the links in the L</SEE ALSO>
section. Now you can fork the project on
L<Github|https://github.com/kberov/Ado>, improve C<menu.html.ep> to
automatically traverse the articles directory and generate the list of
articles, then make a merge request. You just contributed to the project.
=head1 SEE ALSO
L<Ado::Manual>, L<Ado>, L<Mojolicious::Guides>,
L<Mojolicious::Guides::Cookbook/DEPLOYMENT>, L<Ado::Command::generate::apache2htaccess>
=head1 COPYRIGHT AND LICENSE
lib/Ado/Plugin/AdoHelpers.pm view on Meta::CPAN
$app->do_sql_file($conf->{vest_data_sql_file});
# on the command line
$ ado eval 'app->do_sql_file(shift)' some_file.sql
# elsewhere in an application
$app->do_sql_file($sql_file)
=head2 head_css, head_javascript
Minimalist asset management for the C<E<lt>headE<gt>> section. Appends and
later renders assets (links to files and code-snippets) to
C<$c-E<gt>stash('head_css')> and C<app-E<gt>stash('head_javascript')>. The new
assets are only appended if they are not already present in the corresponding
list of assets. The defaults are populated in C<etc/ado.conf>. See also:
L<Mojolicious/defaults>; L<Mojolicious::Plugin::AssetPack>.
#in a template:
#append
<%
head_css([
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
#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}
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
#used as helper within login()
# this method is called as return_url after the user
# 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},
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
#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;
$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
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
],
#in etc/plugins/auth.$mode.conf
{
#methods which will be displayed in the "Sign in" menu
auth_methods => ['ado', 'facebook', 'google'],
providers => {
google => {
key =>'123456789....apps.googleusercontent.com',
secret =>'YourSECR3T',
scope=>'profile email',
info_url => 'https://www.googleapis.com/userinfo/v2/me',
},
facebook => {
key =>'123456789',
secret =>'123456789abcdef',
scope =>'public_profile,email',
info_url => 'https://graph.facebook.com/v2.2/me',
},
}
}
=head1 DESCRIPTION
L<Ado::Plugin::Auth> is a plugin that authenticates users to an L<Ado> system.
Users can be authenticated via Google, Facebook, locally and in the future
lib/Ado/Plugin/Auth.pm view on Meta::CPAN
auth_methods) and values, containing the configurations for the specific
providers. This option will be merged with already defined providers by
L<Mojolicious::Plugin::OAuth2>. Add the rest of the needed configuration
options to auth.development.conf or auth.production.conf only because this is
highly sensitive and application specific information.
#Example for google:
google =>{
#client_id
key =>'123456654321abcd.apps.googleusercontent.com',
secret =>'Y0uRS3cretHEre',
scope=>'profile email',
info_url => 'https://www.googleapis.com/userinfo/v2/me',
},
=head2 routes
Currently defined routes are described in L</ROUTES>.
=head1 CONDITIONS
lib/Ado/Plugin/I18n.pm view on Meta::CPAN
#Add helpers
$app->helper(language => \&language);
$app->helper(l => \&_maketext);
#default routes including language placeholder.
$app->load_routes($self->routes);
# Add hook around_action
$app->hook(around_action => \&around_action);
#Add to classes used for finding templates in DATA sections
push @{$app->renderer->classes}, __PACKAGE__;
#make plugin configuration available for later in the app
$app->config(__PACKAGE__, $config);
return $self;
}
#Mojolicious::around_action hook.
sub around_action {
my ($next, $c, $action, $last_step) = @_;
lib/Ado/Plugin/I18n.pm view on Meta::CPAN
and put into the stash. Default value is 1.
=head2 language_from_host
{
language_from_host => 1,
language_from_route => 1,
...
}
This is the second option that will be checked if enabled.
If you use languages as subdomains make sure to disable C<language_from_route>
or do not construct routes containing languages (eg. C<fr.example.com/en>).
Default value is 1.
=head2 language_from_param
{
language_from_param => 1,
language_from_host => 0,
lib/Ado/Plugin/MarkdownRenderer.pm view on Meta::CPAN
The class to load. This option exists because the user may want to use
L<Text::Markdown> or L<Text::Markup> instead.
=head2 md_method
md_method => 'markdown',
Method that will be used internally to produce the C<$HTML>.
Can also be a code reference.
First parameter is the md_renderer instance and the
second is the markdown text.
=head2 md_options
md_options => {
use_wikilinks => 1,
base_url => '/docs',
},
These options will be passed to the md_renderer constructor.
They are specific for each markup parser so look at it's documentation.
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);
}
sub session_id {
my ($self, $c) = @_;
lib/Ado/Sessions.pm view on Meta::CPAN
my $default = delete $session->{expires};
$session->{expires} = $default || time + $expiration
if $expiration || $default;
my $id = $self->session_id($c) || $self->generate_id();
my $options = {
domain => $self->cookie_domain,
expires => $session->{expires},
httponly => 1,
path => $self->cookie_path,
secure => $self->secure
};
#once
state $cookie_name = $self->cookie_name;
$c->cookie($cookie_name => $id, $options);
return ($id, $session);
}
1;
lib/Ado/Sessions.pm view on Meta::CPAN
Factory method for creating Ado session instance
=head2 prepare_load
Shares common logic which is compatible with L<Mojolicious::Sessions>.
The storage implementation class should call this method after it loads
the session from the respective storage.
$self->prepare_load($c, $session);
=head2 secure
Cookie is secure, flag
=head2 prepare_store
Shares common logic which is compatible with L<Mojolicious::Sessions>.
The storage implementation class should call this method before it stores
the session to the the respective storage.
Returns the session id and the session ready to be serialized
and base 64 encoded.
my ($id, $session) = $self->prepare_store($c);
=head2 session_id
Retrieves the session id from a parameter or cookie defaulting to L<cookie_name>.
The C<cookie_name> can be set in C<ado.conf> section C<session>.
my $id = $self->session_id($c);
=head1 SEE ALSO
L<Mojolicious::Sessions>, L<Ado::Sessions::File>, L<Ado::Sessions::Database>,
L<Using CORS|http://www.html5rocks.com/en/tutorials/cors/>
=cut
public/css/ado.css view on Meta::CPAN
/* box-shadow: none|h-shadow v-shadow blur spread color |inset|initial|inherit; */
#ado-img {
box-shadow: 1px 1px 0.1em 0.1em #aaa;
border: 1px #aaa outset;
}
.small {font-size: small}
code {
color: #993;
white-space: nowrap;
}
section.login_form {
padding-top: 2em;
margin: auto;
min-width: 300px;
width: 80%;
max-width: 600px;
}
/* articles */
.right.attached.launch.fixed.button {
position: fixed !important;
public/doc/en/intro.md view on Meta::CPAN
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.
2. Implement the Pages management controllers for the site.
3. Implement the Content (sections in pages) management controllers.
4. Implement the Users/Groups Management controllers.
Krasimir Berov, 2014-05-06
[^ado_]: Ado - busy or delaying activity; bustle; fuss.
See also http://www.thefreedictionary.com/ado
[^2]: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
public/js/auth.js view on Meta::CPAN
/* auth.js */
/**
* Generates digest value and adds it to digest field in the login form.
* Removes the password field. It is not sent over HTTP.
* See https://developer.mozilla.org/en-US/docs/Security/InsecurePasswords
*/
function generate_digest () {
var digest = $('#login_form [name="digest"]');
var login_name = $('#login_form [name="login_name"]');
var login_password = $('#login_form [name="login_password"]');
var csrf_token = $('#login_form [name="csrf_token"]');
login_password_sha1 = CryptoJS.SHA1(login_name.val() + login_password.val());
//set digest
digest.val(CryptoJS.SHA1(csrf_token.val() + login_password_sha1));
login_password.remove();
public/js/jquery.cookie.js view on Meta::CPAN
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setTime(+t + days * 864e+5);
}
return (document.cookie = [
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// Read
var result = key ? undefined : {};
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling $.cookie().
var cookies = document.cookie ? document.cookie.split('; ') : [];
for (var i = 0, l = cookies.length; i < l; i++) {
var parts = cookies[i].split('=');
var name = decode(parts.shift());
var cookie = parts.join('=');
if (key && key === name) {
// If second argument (value) is a function it's a converter...
result = read(cookie, value);
break;
}
// Prevent storing a cookie that we couldn't decode.
if (!key && (cookie = read(cookie)) !== undefined) {
result[name] = cookie;
}
}
public/vendor/pagedown/Markdown.Converter.js view on Meta::CPAN
text = text.replace(/\r/g, "\n"); // Mac to Unix
// Make sure text begins and ends with a couple of newlines:
text = "\n\n" + text + "\n\n";
// Convert all tabs to spaces.
text = _Detab(text);
// Strip any lines consisting only of spaces and tabs.
// This makes subsequent regexen easier to write, because we can
// match consecutive blank lines with /\n+/ instead of something
// contorted like /[ \t]*\n+/ .
text = text.replace(/^[ \t]+$/mg, "");
text = pluginHooks.postNormalization(text);
// Turn block-level HTML blocks into hash entries
text = _HashHTMLBlocks(text);
// Strip link definitions, store in hashes.
text = _StripLinkDefinitions(text);
public/vendor/pagedown/Markdown.Converter.js view on Meta::CPAN
// Each time we enter a list, we increment it; when we leave a list,
// we decrement. If it's zero, we're not in a list anymore.
//
// We do this because when we're not inside a list, we want to treat
// something like this:
//
// I recommend upgrading to version
// 8. Oops, now this line is treated
// as a sub-list.
//
// As a single paragraph, despite the fact that the second line starts
// with a digit-period-space sequence.
//
// Whereas when we're inside a list (or sub-list), that line will be
// treated as the start of a sub-list. What a kludge, huh? This is
// an aspect of Markdown's syntax that's hard to parse perfectly
// without resorting to mind-reading. Perhaps the solution is to
// change the syntax rules such that sub-lists must start with a
// starting cardinal number; e.g. "1." or "a.".
g_list_level++;
public/vendor/pagedown/Markdown.Converter.js view on Meta::CPAN
// attacklab: add sentinel to emulate \z
list_str += "~0";
// In the original attacklab showdown, list_type was not given to this function, and anything
// that matched /[*+-]|\d+[.]/ would just create the next <li>, causing this mismatch:
//
// Markdown rendered by WMD rendered by MarkdownSharp
// ------------------------------------------------------------------
// 1. first 1. first 1. first
// 2. second 2. second 2. second
// - third 3. third * third
//
// We changed this to behave identical to MarkdownSharp. This is the constructed RegEx,
// with {MARKER} being one of \d+[.] or [*+-], depending on list_type:
/*
list_str = list_str.replace(/
(^[ \t]*) // leading whitespace = $1
({MARKER}) [ \t]+ // list marker = $2
([^\r]+? // list item text = $3
public/vendor/pagedown/Markdown.Converter.js view on Meta::CPAN
// * You can use multiple backticks as the delimiters if you want to
// include literal backticks in the code span. So, this input:
//
// Just type ``foo `bar` baz`` at the prompt.
//
// Will translate to:
//
// <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
//
// There's no arbitrary limit to the number of backticks you
// can use as delimters. If you need three consecutive backticks
// in your code, use four for delimiters, etc.
//
// * You can use spaces to get literal backticks at the edges:
//
// ... type `` `bar` `` ...
//
// Turns to:
//
// ... type <code>`bar`</code> ...
//
public/vendor/pagedown/Markdown.Converter.js view on Meta::CPAN
}
function _DoBlockQuotes(text) {
/*
text = text.replace(/
( // Wrap whole match in $1
(
^[ \t]*>[ \t]? // '>' at the start of a line
.+\n // rest of the first line
(.+\n)* // subsequent consecutive lines
\n* // blanks
)+
)
/gm, function(){...});
*/
text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
function (wholeMatch, m1) {
var bq = m1;
public/vendor/pagedown/Markdown.Editor.js view on Meta::CPAN
//
// In other words, a non-escaped bracket. These have to be escaped now to make sure they
// don't count as the end of the link or similar.
// Note that the actual bracket has to be a lookahead, because (in case of to subsequent brackets),
// the bracket in one match may be the "not a backslash" character in the next match, so it
// should not be consumed by the first match.
// The "prepend a space and finally remove it" steps makes sure there is a "not a backslash" at the
// start of the string, so this also works if the selection begins with a bracket. We cannot solve
// this by anchoring with ^, because in the case that the selection starts with two brackets, this
// would mean a zero-width match at the start. Since zero-width matches advance the string position,
// the first bracket could then not act as the "not a backslash" for the second.
chunk.selection = (" " + chunk.selection).replace(/([^\\](?:\\\\)*)(?=[[\]])/g, "$1\\").substr(1);
var linkDef = " [999]: " + properlyEncoded(link);
var num = that.addLinkDef(chunk, linkDef);
chunk.startTag = isImage ? "![" : "[";
chunk.endTag = "][" + num + "]";
if (!chunk.selection) {
if (isImage) {
t/.perlcriticrc view on Meta::CPAN
#Set severity to 'gentle' and then try stern. If we achieve 'harsh' the code is good enough.
#5:gentle;4:stern;3:harsh
severity = harsh
#only = 1
#force = 1
#verbose = 11
top = 50
#theme = (pbp and security and bugs and maintenance and complexity and security)
#include = NamingConventions ClassHierarchies
#exclude = Variables Modules::RequirePackage
#criticism-fatal = 1
#color = 1
#allow-unsafe = 0
pager = less
#Perl::Critic::Policy::Subroutines::RequireArgUnpacking - Always unpack @_ first.
[Subroutines::RequireArgUnpacking]
short_subroutine_statements = 4
t/plugin/auth-01.t view on Meta::CPAN
#login form in a modal box hidden also there
->text_like('#authbar .modal form#login_form .ui.header:nth-child(1)' => qr'Sign in')
#user is Guest
->text_is('article.ui.main.container h1' => 'Hello Guest,');
#same form is at /login/:auth_method
my $test_auth_url = $t->ua->server->url->path('/test/authenticateduser');
$t->get_ok('/login/ado', {Referer => $test_auth_url})->status_is(200)
->element_exists('section.ui.login_form form#login_form')
->text_like('form#login_form .ui.header:nth-child(1)' => qr'Sign in')
->element_exists('#login_name')->element_exists('#login_password');
#try unexisting login method
my $help_url = $t->ua->server->url->path('/help');
$t->get_ok('/login/alabala', {Referer => $help_url})->status_is(401)
->element_exists_not('input[name="_method"][checked="checked"]');
$t->post_ok('/login/alabala', {Referer => $help_url})->status_is(401)
->text_like('.ui.error.message' => qr/of the supported login methods/);
t/plugin/example-00.t view on Meta::CPAN
ok($app->plugins->namespaces->[-1] eq 'Ado::Plugin',
'$app->plugins->namespaces->[-1]: ' . $app->plugins->namespaces->[-1]);
isnt($app->home, $app->ado_home, '$app->home is not $app->ado_home');
isnt($plugin->home_dir, $app->ado_home, '$plugin->home_dir is not $app->ado_home');
is($plugin->home_dir, $ENV{MOJO_HOME}, '$plugin->home_dir is $MOJO_HOME');
is( $plugin->config_dir,
catdir($ENV{MOJO_HOME}, 'etc', 'plugins'),
'$plugin->config_dir is $MOJO_HOME/etc/plugins'
);
is($app->home->rel_file('public'), $app->static->paths->[0], 'app static path is first');
is($app->ado_home->rel_file('public'), $app->static->paths->[1], 'Ado static path is second');
is($app->home->rel_file('templates'), $app->renderer->paths->[0], 'app renderer path is first');
is( $app->ado_home->rel_file('templates'),
$app->renderer->paths->[1],
'Ado renderer path is second'
);
is_deeply(
$plugin->config,
{ "a" => 1,
"bla" => "off",
"err" => 1,
"lelemale" => 1,
routes => [{route => '/a', to => 'a#b', over => 'a'}],
t/sessions/database.t view on Meta::CPAN
ok $sid, "new sid $sid ok";
$t->get_ok("/");
is $sid, $t->tx->res->cookie($cookie_name)->value, 'Cookie $sid ok';
#default_expiration
$t->get_ok("/");
my $default_expiration = $t->app->sessions->default_expiration;
my $expires = $t->tx->res->cookie($cookie_name)->expires;
#may differ with one second
ok($expires <= gmtime(time + $default_expiration)->epoch, '$default_expiration is ok');
#session expired
my $old_session_id = $t->tx->res->cookie($cookie_name)->value;
$t->app->sessions->default_expiration(-3);
$t->get_ok('/test', 'expired session');
$expires = $t->tx->res->cookie($cookie_name)->expires;
ok($expires <= gmtime(time)->epoch, '$expires is ok');
$t->get_ok("/test");
t/sessions/file.t view on Meta::CPAN
$t->get_ok("/");
is $sid, $t->tx->res->cookie($cookie_name)->value, 'Cookie $sid ok';
#default_expiration
$t->get_ok("/");
my $default_expiration = $t->app->sessions->default_expiration;
my $expires = $t->tx->res->cookie($cookie_name)->expires;
my $equal = $expires - gmtime(time + $default_expiration)->epoch;
#may differ with one second
ok($equal == 0 || $equal == -1, '$default_expiration is ok');
#session expired
my $old_session_id = $t->tx->res->cookie($cookie_name)->value;
$t->app->sessions->default_expiration(-3);
$t->get_ok('/test', 'expired session');
$expires = $t->tx->res->cookie($cookie_name)->expires;
ok($expires < gmtime(time)->epoch, '$expires is ok');
$t->get_ok("/test");