You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
6.9 KiB
218 lines
6.9 KiB
package MJB::Web::Controller::Blog;
|
|
use Mojo::Base 'Mojolicious::Controller', -signatures;
|
|
use Try::Tiny;
|
|
|
|
#=====
|
|
# This file handles the initial creation of a blog.
|
|
#
|
|
# It is a controller, the template files live in templates/blog.
|
|
#=====
|
|
|
|
#==
|
|
# GET /blog | show_blog
|
|
#
|
|
# Redirect the user to the initial step of the blog creation process.
|
|
#==
|
|
sub index ( $c ) {
|
|
$c->redirect_to( 'show_blog_domain_hosted' );
|
|
}
|
|
|
|
#==
|
|
# GET /blog/domain/hosted | show_blog_domain_hosted
|
|
#
|
|
# The initial entrypoint for blog creation.
|
|
#==
|
|
sub domain_hosted ( $c ) {
|
|
|
|
}
|
|
|
|
#==
|
|
# POST /blog/domain/hosted | do_blog_domain_hosted
|
|
# subdomain | A subdomain that the user would like to use
|
|
# hosted_domain_id | The id of a hosted_domain that the user wants to use
|
|
#
|
|
# This route will create a blog as a subdomain of a hosted domain. We control
|
|
# the DNS, SSL, etc.
|
|
#==
|
|
sub do_domain_hosted ( $c ) {
|
|
my $sub_domain = $c->stash->{form}->{subdomain} = $c->param('subdomain');
|
|
my $top_domain = $c->db->hosted_domain( $c->param('hosted_domain_id') );
|
|
|
|
# Store the hosted domain id so we can have the right domain selected on the drop down
|
|
# for errors.
|
|
$c->stash->{form}->{hdid} = $top_domain->id;
|
|
|
|
$sub_domain = lc($sub_domain);
|
|
|
|
push @{$c->stash->{errors}}, "Please select a domain from the drop down menu."
|
|
unless $top_domain;
|
|
|
|
push @{$c->stash->{errors}}, "Please enter a value for the subdomain."
|
|
unless $sub_domain;
|
|
|
|
push @{$c->stash->{errors}}, "Subdomains must start with a letter, and may use letters, numbers, dashes and hyphens."
|
|
unless $sub_domain =~ /^[a-z]+[a-z0-9-_]*$/;
|
|
|
|
push @{$c->stash->{errors}}, "That domain name is already being used."
|
|
unless $c->db->domains( { name => $sub_domain . '.' . $top_domain->name } )->count == 0;
|
|
|
|
return $c->redirect_error( 'show_blog_domain_hosted' )
|
|
if $c->stash->{errors};
|
|
|
|
my $domain_name = $sub_domain . '.' . $top_domain->name;
|
|
my $domain_ssl = $top_domain->letsencrypt_challenge ne 'http' ? $top_domain->name : '';
|
|
|
|
return $c->_initialize_blog( $domain_name, 'show_blog_domain_hosted', $domain_ssl );
|
|
}
|
|
|
|
#==
|
|
# GET /blog/domain/owned | show_blog_domain_owned
|
|
#
|
|
# The initial entrypoint for blog creation on a domain that the user controls
|
|
# DNS for.
|
|
#==
|
|
sub domain_owned ( $c ) {
|
|
$c->stash->{dns_record} = 'external.' . $c->db->hosted_domains->first->name;
|
|
|
|
}
|
|
|
|
#==
|
|
# POST /blog/domain/owned | do_blog_domain_owned
|
|
# domain_name | The domain name that the user would like to use
|
|
#
|
|
# This route will create a blog with whatever domain the user supplies. They will
|
|
# need to have ensured that DNS is pointed to the correct addresses so that it works.
|
|
#==
|
|
sub do_domain_owned ( $c ) {
|
|
my $domain_name = $c->stash->{form}->{domain_name} = $c->param('domain_name');
|
|
|
|
$domain_name = lc($domain_name);
|
|
|
|
push @{$c->stash->{errors}}, "Please enter a value for the domain name."
|
|
unless $domain_name;
|
|
|
|
push @{$c->stash->{errors}}, "That domain name is already being used."
|
|
unless $c->db->domains( { name => $domain_name } )->count == 0;
|
|
|
|
return $c->redirect_error( 'show_blog_domain_owned' )
|
|
if $c->stash->{errors};
|
|
|
|
return $c->_initialize_blog( $domain_name, 'show_blog_domain_owned', '' );
|
|
}
|
|
|
|
#==
|
|
# Helper Function...
|
|
#
|
|
# This will make the blog after domain_hosted / domain_owned figures out what
|
|
# it's making.
|
|
#==
|
|
sub _initialize_blog ( $c, $domain, $from, $ssl_domain ) {
|
|
|
|
# Do we already have this domain name?
|
|
if ( $c->db->domain( { name => $domain } ) ) {
|
|
$c->flash( errors => [ 'That domain name is already being hosted.' ] );
|
|
$c->redirect_to( $c->url_for( $from ) );
|
|
return;
|
|
}
|
|
|
|
# Create the Jekyll repo for the site
|
|
# This is where a job to build it on the build server should happen...
|
|
|
|
my $jekyll = $c->jekyll($domain)->init;
|
|
|
|
my $blog = try {
|
|
$c->db->storage->schema->txn_do( sub {
|
|
# Make the domain name record.
|
|
my $domain_record = $c->stash->{person}->create_related('domains', {
|
|
name => $domain,
|
|
( $ssl_domain ? ( ssl => $ssl_domain ) : () ),
|
|
});
|
|
|
|
# Make the website record
|
|
my $blog = $c->stash->{person}->create_related('blogs', {
|
|
domain_id => $domain_record->id,
|
|
});
|
|
|
|
$blog->create_related( 'repoes', {
|
|
url => $jekyll->repo,
|
|
});
|
|
|
|
return $blog;
|
|
});
|
|
} catch {
|
|
push @{$c->stash->{errors}}, "Blog could not be created: $_";
|
|
};
|
|
|
|
if ( $c->stash->{errors} ) {
|
|
$c->flash( errors => $c->stash->{errors} );
|
|
$c->redirect_to( $c->url_for( $from ) );
|
|
return;
|
|
}
|
|
|
|
# Schedule a job to deploy the website
|
|
if ( ! $ssl_domain ) {
|
|
my $ssl_job_id = $c->minion->enqueue( 'create_ssl_cert', [ $blog->id ], {
|
|
notes => { '_bid_' . $blog->id => 1 },
|
|
priority => $blog->build_priority,
|
|
queue => 'certbot',
|
|
});
|
|
$blog->create_related( 'jobs', { minion_job_id => $ssl_job_id } );
|
|
}
|
|
|
|
$c->redirect_to( $c->url_for( 'show_blog_settings', { id => $blog->id } ) );
|
|
}
|
|
|
|
#==
|
|
# GET /blog/:id/settings | show_blog_settings
|
|
#
|
|
# This page gives the user the chance to set the title, description, email, etc.
|
|
#==
|
|
sub settings ( $c ) {
|
|
|
|
}
|
|
|
|
#==
|
|
# POST /blog/:id/settings | show_blog_settings
|
|
# configTitle | The title for the blog
|
|
# configDesc | The description for the blog
|
|
# configEmail | An email address for the blog's author
|
|
#
|
|
# This route handles the initial configuration of the blog, and schedules
|
|
# the minion job to initialize it.
|
|
#==
|
|
sub do_settings ( $c ) {
|
|
my $blog = $c->stash->{blog} = $c->db->blog( $c->param('id') );
|
|
|
|
if ( $blog->person->id ne $c->stash->{person}->id ) {
|
|
$c->render(
|
|
text => "Error: This blog isn't owned by you.",
|
|
status => 404,
|
|
format => 'txt',
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $jekyll = $c->jekyll($blog->domain->name);
|
|
|
|
my $title = $c->stash->{form_title} = $c->param( 'configTitle' );
|
|
my $desc = $c->stash->{form_desc} = $c->param( 'configDesc' );
|
|
my $email = $c->stash->{form_email} = $c->param( 'configEmail' );
|
|
|
|
$jekyll->config->data->{title} = $title;
|
|
$jekyll->config->data->{description} = $desc;
|
|
$jekyll->config->data->{email} = $email;
|
|
$jekyll->config->data->{url} = 'https://' . $blog->domain->name ;
|
|
|
|
$jekyll->write_config;
|
|
|
|
my $build_job_id = $c->minion->enqueue( 'initialize_blog', [ $blog->id ], {
|
|
notes => { '_bid_' . $blog->id => 1 },
|
|
priority => $blog->build_priority,
|
|
});
|
|
$blog->create_related( 'jobs', { minion_job_id => $build_job_id } );
|
|
|
|
$c->flash( confirmation => "Welcome to the dashboard for your new blog!" );
|
|
$c->redirect_to( $c->url_for( 'show_dashboard_blog', { id => $blog->id } ) );
|
|
}
|
|
|
|
1;
|
|
|