view release on metacpan or search on metacpan
README.markdown view on Meta::CPAN
Here is an example project to get things going.
In the `data_connections.main` section of `conf/asp4-config.json` you should have
something like this:
...
"main": {
"dsn": "DBI:mysql:database_name:data.mywebsite.com",
"username": "db-username",
"password": "db-pAsswOrd"
}
...
Suppose you had the following tables in your database:
create table users (
user_id bigint unsigned not null primary key auto_increment,
email varchar(200) not null,
password char(32) not null,
created_on timestamp not null default current_timestamp,
unique(email)
) engine=innodb charset=utf8;
create table messages (
message_id bigint unsigned not null primary key auto_increment,
from_user_id bigint unsigned not null,
to_user_id bigint unsigned not null,
subject varchar(100) not null,
README.markdown view on Meta::CPAN
# Get our main database connection info:
my $conn = $Config->data_connections->main;
# Setup our database connection:
__PACKAGE__->connection(
$conn->dsn,
$conn->username,
$conn->password
);
1;# return true:
Add the following `Class::DBI::Lite` entity classes:
`lib/App/db/user.pm`
package App::db::user;
README.markdown view on Meta::CPAN
);
__PACKAGE__->has_many(
messages_out =>
'App::db::message' =>
'from_user_id'
);
# Hash the password before storing it in the database:
__PACKAGE__->add_trigger( before_create => sub {
my ($self) = @_;
# Sign the password instead of storing it as plaintext:
unless( $self->{password} =~ m{^([a-f0-9]{32})$}i ) {
$self->{password} = $self->hash_password( $self->password );
}
});
# Hash the new password before storing it in the database:
__PACKAGE__->add_trigger( before_update_password => sub {
my ($self, $old, $new) = @_;
unless( $new =~ m{^([a-f0-9]{32})$}i ) {
$self->{password} = $self->hash_password( $new );
}
});
# Verify an email/password combination and return the user if a match is found:
sub check_credentials {
my ($self, %args) = @_;
my ($result) = $self->search(
email => $args{email},
password => $self->hash_password( $args{password} ),
);
$result ? return $result : return;
}
# Convert a password string into its hashed value:
sub hash_password {
my ($self, $str) = @_;
my $key = ASP4::ConfigLoader->load->system->settings->signing_key;
return md5_hex( $str . $key );
}
1;# return true:
README.markdown view on Meta::CPAN
};
%>
<form id="register_form" method="post" action="/handlers/myapp.register">
<p>
<label>Email:</label>
<input type="text" name="email" value="<%= $Server->HTMLEncode( $Form->{email} ) %>" />
<% $::err->("email"); %>
</p>
<p>
<label>Password:</label>
<input type="password" name="password" />
<% $::err->("password"); %>
</p>
<p>
<label>Confirm Password:</label>
<input type="password" name="password2" />
<% $::err->("password2"); %>
</p>
<p>
<input type="submit" value="Register Now" />
</p>
</form>
</asp:Content>
The form submits to the URL `/handlers/app.register` which means `handlers/app/register.pm`
File: `handlers/app/register.pm`
README.markdown view on Meta::CPAN
$Session->save;
return $Response->Redirect( $ENV{HTTP_REFERER} );
}
# Create the user:
my $user = eval {
App::db::user->do_transaction(sub {
return App::db::user->create(
email => $Form->{email},
password => $Form->{password},
);
});
};
if( $@ ) {
# There was an error:
$Session->{validation_errors} = {email => "Server error. Sorry!"};
$Session->{__lastArgs} = $Form;
$Session->save;
README.markdown view on Meta::CPAN
# Basic email validation:
unless( $Form->{email} =~ m{[^@]+@[^@]+\.[^@]+} ) {
$errors->{email} = "Invalid email address";
}
}
else {
$errors->{email} = "Required";
}
# password:
unless( length($Form->{password} ) {
$errors->{password} = "Required";
}
# password2:
if( length($Form->{password2}) ) {
if( length($Form->{password}) ) {
unless( $Form->{password} eq $Form->{password2} ) {
$errors->{password2} = "Passwords don't match";
}
}
}
else {
$errors->{password2} = "Required";
}
# Bail out of we already have errors:
return $errors if keys %$errors;
# See if the user already exists:
if( App::db::user->count_search( email => $Form->{email} ) ) {
$errors->{email} = "Already in use";
lib/ASP4.pm view on Meta::CPAN
Here is an example project to get things going.
In the C<data_connections.main> section of C<conf/asp4-config.json> you should have
something like this:
...
"main": {
"dsn": "DBI:mysql:database_name:data.mywebsite.com",
"username": "db-username",
"password": "db-pAsswOrd"
}
...
Suppose you had the following tables in your database:
create table users (
user_id bigint unsigned not null primary key auto_increment,
email varchar(200) not null,
password char(32) not null,
created_on timestamp not null default current_timestamp,
unique(email)
) engine=innodb charset=utf8;
create table messages (
message_id bigint unsigned not null primary key auto_increment,
from_user_id bigint unsigned not null,
to_user_id bigint unsigned not null,
subject varchar(100) not null,
body text,
lib/ASP4.pm view on Meta::CPAN
# Get our configuration object:
my $Config = ASP4::ConfigLoader->load();
# Get our main database connection info:
my $conn = $Config->data_connections->main;
# Setup our database connection:
__PACKAGE__->connection(
$conn->dsn,
$conn->username,
$conn->password
);
1;# return true:
Add the following C<Class::DBI::Lite> entity classes:
C<lib/App/db/user.pm>
package App::db::user;
lib/ASP4.pm view on Meta::CPAN
'App::db::message' =>
'to_user_id'
);
__PACKAGE__->has_many(
messages_out =>
'App::db::message' =>
'from_user_id'
);
# Hash the password before storing it in the database:
__PACKAGE__->add_trigger( before_create => sub {
my ($self) = @_;
# Sign the password instead of storing it as plaintext:
unless( $self->{password} =~ m{^([a-f0-9]{32})$}i ) {
$self->{password} = $self->hash_password( $self->password );
}
});
# Hash the new password before storing it in the database:
__PACKAGE__->add_trigger( before_update_password => sub {
my ($self, $old, $new) = @_;
unless( $new =~ m{^([a-f0-9]{32})$}i ) {
$self->{password} = $self->hash_password( $new );
}
});
# Verify an email/password combination and return the user if a match is found:
sub check_credentials {
my ($self, %args) = @_;
my ($result) = $self->search(
email => $args{email},
password => $self->hash_password( $args{password} ),
);
$result ? return $result : return;
}
# Convert a password string into its hashed value:
sub hash_password {
my ($self, $str) = @_;
my $key = ASP4::ConfigLoader->load->system->settings->signing_key;
return md5_hex( $str . $key );
}
1;# return true:
C<lib/App/db/message.pm>
lib/ASP4.pm view on Meta::CPAN
};
%>
<form id="register_form" method="post" action="/handlers/myapp.register">
<p>
<label>Email:</label>
<input type="text" name="email" value="<%= $Server->HTMLEncode( $Form->{email} ) %>" />
<% $::err->("email"); %>
</p>
<p>
<label>Password:</label>
<input type="password" name="password" />
<% $::err->("password"); %>
</p>
<p>
<label>Confirm Password:</label>
<input type="password" name="password2" />
<% $::err->("password2"); %>
</p>
<p>
<input type="submit" value="Register Now" />
</p>
</form>
</asp:Content>
The form submits to the URL C</handlers/app.register> which means C<handlers/app/register.pm>
File: C<handlers/app/register.pm>
lib/ASP4.pm view on Meta::CPAN
$Session->{__lastArgs} = $Form;
$Session->save;
return $Response->Redirect( $ENV{HTTP_REFERER} );
}
# Create the user:
my $user = eval {
App::db::user->do_transaction(sub {
return App::db::user->create(
email => $Form->{email},
password => $Form->{password},
);
});
};
if( $@ ) {
# There was an error:
$Session->{validation_errors} = {email => "Server error. Sorry!"};
$Session->{__lastArgs} = $Form;
$Session->save;
return $Response->Redirect( $ENV{HTTP_REFERER} );
lib/ASP4.pm view on Meta::CPAN
if( length($Form->{email}) ) {
# Basic email validation:
unless( $Form->{email} =~ m{[^@]+@[^@]+\.[^@]+} ) {
$errors->{email} = "Invalid email address";
}
}
else {
$errors->{email} = "Required";
}
# password:
unless( length($Form->{password} ) {
$errors->{password} = "Required";
}
# password2:
if( length($Form->{password2}) ) {
if( length($Form->{password}) ) {
unless( $Form->{password} eq $Form->{password2} ) {
$errors->{password2} = "Passwords don't match";
}
}
}
else {
$errors->{password2} = "Required";
}
# Bail out of we already have errors:
return $errors if keys %$errors;
# See if the user already exists:
if( App::db::user->count_search( email => $Form->{email} ) ) {
$errors->{email} = "Already in use";
}
lib/ASP4/Config.pm view on Meta::CPAN
$Config->web->handler_root;
$Config->web->media_manager_upload_root;
$Config->web->page_cache_root;
# Data Connections:
foreach my $conn ( map { $Config->data_connections->$_ } qw/ session application main / )
{
my $dbh = DBI->connect(
$conn->dsn,
$conn->username,
$conn->password
);
}# end foreach()
=head1 JSON Config File
ASP4::ASP keeps all of its configuration inside of C</conf/asp4-config.json>
Here is an example:
{
lib/ASP4/Config.pm view on Meta::CPAN
]
},
"data_connections": {
"session": {
"manager": "ASP4::SessionStateManager",
"cookie_name": "session-id",
"cookie_domain": ".mysite.com",
"session_timeout": 30,
"dsn": "DBI:SQLite:dbname=/tmp/db_asp4",
"username": "",
"password": ""
},
"main": {
"dsn": "DBI:SQLite:dbname=/tmp/db_asp4",
"username": "",
"password": ""
}
}
}
=head1 BUGS
It's possible that some bugs have found their way into this release.
Use RT L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ASP4> to submit bug reports.
lib/ASP4/ConfigNode/System.pm view on Meta::CPAN
it is considered "ready for use" by the rest of the application.
=head2 env_vars
A hash of C<%ENV> variables that should be set.
=head2 settings
A collection of special read-only values that should be available throughout the application.
Examples include encryption keys, API keys and username/password combos to access remote services.
=head1 BUGS
It's possible that some bugs have found their way into this release.
Use RT L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ASP4> to submit bug reports.
=head1 HOMEPAGE
Please visit the ASP4 homepage at L<http://0x31337.org/code/> to see examples
lib/ASP4/SessionStateManager.pm view on Meta::CPAN
sub new
{
my ($class, $r) = @_;
my $s = bless { }, $class;
my $conn = context()->config->data_connections->session;
local $^W = 0;
$class->set_db('Session',
$conn->dsn,
$conn->username,
$conn->password
);
my $id = $s->parse_session_id();
unless( $id && $s->verify_session_id( $id, $conn->session_timeout ) )
{
$s->{SessionID} = $s->new_session_id();
$s->write_session_cookie($r);
return $s->create( $s->{SessionID} );
}# end unless()
lib/ASP4/UserAgent.pm view on Meta::CPAN
ASP4::UserAgent - Execute ASP4 requests without a web server.
=head1 SYNOPSIS
B<NOTE:> 99.99% of the time you will access this via L<ASP4::API>.
my HTTP::Response $res = $api->ua->get('/index.asp?foo=bar');
my $res = $api->ua->post('/handlers/user.login', [
username => 'willy',
password => 'wonka',
]);
my $res = $api->ua->upload('/handlers/file.upload', [
foo => 'bar',
baz => 'bux',
file => ['/home/john/avatar.jpg']
]);
# Some form testing:
my ($form) = HTML::Form->parse( $res->content, '/' );
sbin/asphelper view on Meta::CPAN
"db=s" => \$dbName,
"user=s" => \$dbUser,
"host=s" => \$dbHost,
);
$appName && $domain && $email or die "Usage: $0 --app=AppName --domain=domain.com --email=you\@your-email.com [--host=dbhost --db=dbname --user=dbusername]\n";
$dbHost ||= "localhost";
if( $dbName && $dbUser )
{
print STDERR "Enter your database password: ";
ReadMode('noecho');
chomp($dbPass = <STDIN>);
ReadMode('restore');
print "\n";
}# end if()
my @DSN = (
"DBI:mysql:$dbName:$dbHost",
$dbUser,
$dbPass
sbin/asphelper view on Meta::CPAN
use strict;
use warnings 'all';
use base 'Class::DBI::Lite::mysql';
use ASP4::ConfigLoader;
my \$Config = ASP4::ConfigLoader->load();
my \$conn = \$Config->data_connections->main;
__PACKAGE__->connection(
\$conn->dsn,
\$conn->username,
\$conn->password
);
1;# return true:
\=pod
\=head1 NAME
$appName\::db::model - Base class for all $appName entity classes.
sbin/asphelper view on Meta::CPAN
if( $has_db )
{
$str .= <<'EOF';
"session": {
"manager": "ASP4::SessionStateManager",
"cookie_name": "session-id",
"cookie_domain": "*",
"session_timeout": "*",
"dsn": "DBI:mysql:%dbName%:%dbHost%",
"username": "%dbUser%",
"password": "%dbPass%"
},
"main": {
"dsn": "DBI:mysql:%dbName%:%dbHost%",
"username": "%dbUser%",
"password": "%dbPass%"
}
EOF
}
else
{
$str .= <<'EOF';
"session": {
"manager": "ASP4::SessionStateManager::NonPersisted",
"cookie_name": "session-id",
"cookie_domain": "*",
"session_timeout": "*",
"dsn": "DBI:mysql:dbname:hostname",
"username": "admin",
"password": "swordfish"
},
"main": {
"dsn": "DBI:mysql:dbname:hostname",
"username": "admin",
"password": "swordfish"
}
EOF
}# end if()
$str .= <<'EOF';
}
}
EOF
return $str;
sbin/asphelper view on Meta::CPAN
=pod
=head1 NAME
asphelper - Generate an ASP4 skeleton web application
=head1 USAGE
asphelper --app=AppName --domain=example.com --email=you@your-email.com [--host=dbhost --db=dbname --user=dbusername]
If you specify C<--dbname> and C<--dbuser> it will ask you for a database password - completely optional.
=head1 DESCRIPTION
The C<asphelper> program offers a way to get up-and-running quickly with a new ASP4 web application.
After successfully answering its questions, C<asphelper> will generate a skeleton web application
including config files, full directory structure and a simple unit test.
Use the resulting application as a starting-point for your own development.
t/conf/asp4-config.json view on Meta::CPAN
]
},
"data_connections": {
"session": {
"manager": "ASP4::SessionStateManager::InMemory",
"cookie_name": "session-id",
"cookie_domain": "*",
"session_timeout": "*",
"dsn": "DBI:SQLite:dbname=/tmp/db_asp4",
"username": "",
"password": ""
},
"main": {
"dsn": "DBI:SQLite:dbname=/tmp/db_asp4",
"username": "",
"password": ""
}
}
}