separate site and account settings context

This commit is contained in:
Kyle Drake 2014-10-07 10:09:16 -07:00
parent 7e36dc83f8
commit d0970cdf9e
16 changed files with 515 additions and 443 deletions

439
app.rb
View file

@ -125,11 +125,11 @@ post '/site/:username/set_editor_theme' do
'ok'
end
post '/site/create_child' do
post '/settings/create_child' do
require_login
site = Site.new
site.parent_site_id = current_site.id
site.parent_site_id = parent_site.id
site.username = params[:username]
if site.valid?
@ -553,38 +553,57 @@ get '/signin' do
erb :'signin'
end
get '/settings' do
get '/settings/?' do
require_login
erb :'settings'
@site = parent_site
erb :'settings/account'
end
post '/settings/profile' do
def require_ownership_for_settings
@site = Site[username: params[:username]]
unless @site.owned_by? parent_site
flash[:error] = 'Cannot edit this site, you do not have permission.'
redirect request.referrer
end
end
get '/settings/:username/?' do
require_login
current_site.update(
require_ownership_for_settings
erb :'settings/site'
end
post '/settings/:username/profile' do
require_login
require_ownership_for_settings
@site.update(
profile_comments_enabled: params[:site][:profile_comments_enabled]
)
flash[:success] = 'Profile settings changed.'
redirect '/settings#profile'
redirect "/settings/#{@site.username}#profile"
end
post '/settings/ssl' do
post '/settings/:username/ssl' do
require_login
require_ownership_for_settings
unless params[:key] && params[:cert]
flash[:error] = 'SSL key and certificate are required.'
redirect '/custom_domain'
redirect "/settings/#{@site.username}#custom_domain"
end
begin
key = OpenSSL::PKey::RSA.new params[:key][:tempfile].read, ''
rescue => e
flash[:error] = 'Could not process SSL key, file may be incorrect, damaged, or passworded (you need to remove the password).'
redirect '/custom_domain'
redirect "/settings/#{@site.username}#custom_domain"
end
if !key.private?
flash[:error] = 'SSL Key file does not have private key data.'
redirect '/custom_domain'
redirect "/settings/#{@site.username}#custom_domain"
end
certs_string = params[:cert][:tempfile].read
@ -593,7 +612,7 @@ post '/settings/ssl' do
if cert_array.empty?
flash[:error] = 'Cert file does not contain any certificates.'
redirect '/custom_domain'
redirect "/settings/#{@site.username}#custom_domain"
end
cert_valid_for_domain = false
@ -603,21 +622,21 @@ post '/settings/ssl' do
cert = OpenSSL::X509::Certificate.new cert_string
rescue => e
flash[:error] = 'Could not process SSL certificate, file may be incorrect or damaged.'
redirect '/custom_domain'
redirect "/settings/#{@site.username}#custom_domain"
end
if cert.not_after < Time.now
flash[:error] = 'SSL Certificate has expired, please create a new one.'
redirect '/custom_domain'
redirect "/settings/#{@site.username}#custom_domain"
end
cert_cn = cert.subject.to_a.select {|a| a.first == 'CN'}.flatten[1]
cert_valid_for_domain = true if cert_cn && cert_cn.match(current_site.domain)
cert_valid_for_domain = true if cert_cn && cert_cn.match(@site.domain)
end
unless cert_valid_for_domain
flash[:error] = "Your certificate CN (common name) does not match your domain: #{current_site.domain}"
redirect '/custom_domain'
flash[:error] = "Your certificate CN (common name) does not match your domain: #{@site.domain}"
redirect "/settings/#{@site.username}#custom_domain"
end
# Everything else was worse.
@ -640,7 +659,7 @@ post '/settings/ssl' do
access_log off;
server {
listen 60000 ssl;
server_name #{current_site.domain} *.#{current_site.domain};
server_name #{@site.domain} *.#{@site.domain};
ssl_certificate #{crtfile.path};
ssl_certificate_key #{keyfile.path};
}
@ -658,14 +677,197 @@ post '/settings/ssl' do
output = line.run path: nginx_testfile.path
rescue Cocaine::ExitStatusError => e
flash[:error] = "There is something wrong with your certificate, please check with your issuing CA."
redirect '/custom_domain'
redirect "/settings/#{@site.username}#custom_domain"
end
end
current_site.update ssl_key: key.to_pem, ssl_cert: cert_array.join
@site.update ssl_key: key.to_pem, ssl_cert: cert_array.join
flash[:success] = 'Updated SSL key/certificate.'
redirect '/custom_domain'
redirect "/settings/#{@site.username}#custom_domain"
end
post '/settings/:username/change_name' do
require_login
require_ownership_for_settings
old_username = @site.username
if params[:name] == nil || params[:name] == ''
flash[:error] = 'Name cannot be blank.'
redirect "/settings/#{@site.username}#username"
end
if old_username == params[:name]
flash[:error] = 'You already have this name.'
redirect "/settings/#{@site.username}#username"
end
old_host = @site.host
old_file_paths = @site.file_list.collect {|f| f[:path]}
@site.username = params[:name]
if @site.valid?
DB.transaction {
@site.save_changes
@site.move_files_from old_username
}
old_file_paths.each do |file_path|
@site.purge_cache file_path
end
flash[:success] = "Site/user name has been changed. You will need to use this name to login, <b>don't forget it</b>."
redirect "/settings/#{@site.username}#username"
else
flash[:error] = @site.errors.first.last.first
redirect "/settings/#{old_username}#username"
end
end
post '/settings/:username/change_nsfw' do
require_login
require_ownership_for_settings
@site.update is_nsfw: params[:is_nsfw]
flash[:success] = @site.is_nsfw ? 'Marked 18+' : 'Unmarked 18+'
redirect "/settings/#{@site.username}#nsfw"
end
post '/settings/:username/custom_domain' do
require_login
require_ownership_for_settings
@site.domain = params[:domain]
if @site.valid?
@site.save_changes
flash[:success] = 'The domain has been successfully updated.'
redirect "/settings/#{@site.username}#custom_domain"
else
flash[:error] = @site.errors.first.last.first
redirect "/settings/#{@site.username}#custom_domain"
end
end
post '/settings/change_password' do
require_login
if !Site.valid_login?(parent_site.username, params[:current_password])
flash[:error] = 'Your provided password does not match the current one.'
redirect "/settings#password"
end
parent_site.password = params[:new_password]
parent_site.valid?
if params[:new_password] != params[:new_password_confirm]
parent_site.errors.add :password, 'New passwords do not match.'
end
if parent_site.errors.empty?
parent_site.save_changes
flash[:success] = 'Successfully changed password.'
redirect "/settings#password"
else
flash[:error] = current_site.errors.first.last.first
redirect '/settings#password'
end
end
post '/settings/change_email' do
require_login
if params[:email] == current_site.email
flash[:error] = 'You are already using this email address for this account.'
redirect '/settings#email'
end
parent_site.email = params[:email]
parent_site.email_confirmation_token = SecureRandom.hex 3
parent_site.email_confirmed = false
if parent_site.valid?
parent_site.save_changes
send_confirmation_email
flash[:success] = 'Successfully changed email. We have sent a confirmation email, please use it to confirm your email address.'
redirect '/settings#email'
end
flash[:error] = parent_site.errors.first.last.first
redirect '/settings#email'
end
get '/password_reset' do
erb :'password_reset'
end
post '/send_password_reset' do
sites = Site.filter(email: params[:email]).all
if sites.length > 0
token = SecureRandom.uuid.gsub('-', '')
sites.each do |site|
site.update password_reset_token: token
end
body = <<-EOT
Hello! This is the Neocities cat, and I have received a password reset request for your e-mail address. Purrrr.
Go to this URL to reset your password: http://neocities.org/password_reset_confirm?token=#{token}
After clicking on this link, your password for all the sites registered to this email address will be changed to this token.
Token: #{token}
If you didn't request this reset, you can ignore it. Or hide under a bed. Or take a nap. Your call.
Meow,
the Neocities Cat
EOT
body.strip!
EmailWorker.perform_async({
from: 'web@neocities.org',
to: params[:email],
subject: '[Neocities] Password Reset',
body: body
})
end
flash[:success] = 'If your email was valid (and used by a site), the Neocities Cat will send an e-mail to your account with password reset instructions.'
redirect '/'
end
get '/password_reset_confirm' do
if params[:token].nil? || params[:token].empty?
flash[:error] = 'Could not find a site with this token.'
redirect '/'
end
reset_site = Site[password_reset_token: params[:token]]
if reset_site.nil?
flash[:error] = 'Could not find a site with this token.'
redirect '/'
end
sites = Site.filter(email: reset_site.email).all
if sites.length > 0
sites.each do |site|
site.password = reset_site.password_reset_token
site.save_changes
end
flash[:success] = 'Your password for all sites with your email address has been changed to the token sent in your e-mail. Please login and change your password as soon as possible.'
else
flash[:error] = 'Could not find a site with this token.'
end
redirect '/'
end
post '/signin' do
@ -704,98 +906,6 @@ get '/site_files/new_page' do
erb :'site_files/new_page'
end
post '/change_password' do
require_login
if !Site.valid_login?(current_site.username, params[:current_password])
flash[:error] = 'Your provided password does not match the current one.'
redirect '/settings#password'
end
current_site.password = params[:new_password]
current_site.valid?
if params[:new_password] != params[:new_password_confirm]
current_site.errors.add :password, 'New passwords do not match.'
end
if current_site.errors.empty?
current_site.save_changes
flash[:success] = 'Successfully changed password.'
redirect '/settings#password'
else
flash[:error] = current_site.errors.first.last.first
redirect '/settings#password'
end
end
post '/change_email' do
require_login
if params[:email] == current_site.email
flash[:error] = 'You are already using this email address for this account.'
redirect '/settings#email'
end
current_site.email = params[:email]
current_site.email_confirmation_token = SecureRandom.hex 3
current_site.email_confirmed = false
if current_site.valid?
current_site.save_changes
send_confirmation_email
flash[:success] = 'Successfully changed email. We have sent a confirmation email, please use it to confirm your email address.'
redirect '/settings#email'
end
flash[:error] = current_site.errors.first.last.first
redirect '/settings#email'
end
post '/change_name' do
require_login
old_username = current_site.username
if params[:name] == nil || params[:name] == ''
flash[:error] = 'Name cannot be blank.'
redirect '/settings#username'
end
if old_username == params[:name]
flash[:error] = 'You already have this name.'
redirect '/settings#username'
end
old_host = current_site.host
old_file_paths = current_site.file_list.collect {|f| f[:path]}
current_site.username = params[:name]
if current_site.valid?
DB.transaction {
current_site.save_changes
current_site.move_files_from old_username
}
old_file_paths.each do |file_path|
current_site.purge_cache file_path
end
flash[:success] = "Site/user name has been changed. You will need to use this name to login, <b>don't forget it</b>."
redirect '/settings#username'
else
flash[:error] = current_site.errors.first.last.first
redirect '/settings#username'
end
end
post '/change_nsfw' do
require_login
current_site.update is_nsfw: params[:is_nsfw]
flash[:success] = current_site.is_nsfw ? 'Marked 18+' : 'Unmarked 18+'
redirect '/settings#nsfw'
end
post '/site_files/create_page' do
require_login
@errors = []
@ -1027,95 +1137,6 @@ post '/admin/mark_nsfw' do
redirect '/admin'
end
get '/password_reset' do
erb :'password_reset'
end
post '/send_password_reset' do
sites = Site.filter(email: params[:email]).all
if sites.length > 0
token = SecureRandom.uuid.gsub('-', '')
sites.each do |site|
site.update password_reset_token: token
end
body = <<-EOT
Hello! This is the Neocities cat, and I have received a password reset request for your e-mail address. Purrrr.
Go to this URL to reset your password: http://neocities.org/password_reset_confirm?token=#{token}
After clicking on this link, your password for all the sites registered to this email address will be changed to this token.
Token: #{token}
If you didn't request this reset, you can ignore it. Or hide under a bed. Or take a nap. Your call.
Meow,
the Neocities Cat
EOT
body.strip!
EmailWorker.perform_async({
from: 'web@neocities.org',
to: params[:email],
subject: '[Neocities] Password Reset',
body: body
})
end
flash[:success] = 'If your email was valid (and used by a site), the Neocities Cat will send an e-mail to your account with password reset instructions.'
redirect '/'
end
get '/password_reset_confirm' do
if params[:token].nil? || params[:token].empty?
flash[:error] = 'Could not find a site with this token.'
redirect '/'
end
reset_site = Site[password_reset_token: params[:token]]
if reset_site.nil?
flash[:error] = 'Could not find a site with this token.'
redirect '/'
end
sites = Site.filter(email: reset_site.email).all
if sites.length > 0
sites.each do |site|
site.password = reset_site.password_reset_token
site.save_changes
end
flash[:success] = 'Your password for all sites with your email address has been changed to the token sent in your e-mail. Please login and change your password as soon as possible.'
else
flash[:error] = 'Could not find a site with this token.'
end
redirect '/'
end
get '/custom_domain' do
require_login
erb :custom_domain
end
post '/custom_domain' do
require_login
current_site.domain = params[:domain]
if current_site.valid?
current_site.save_changes
flash[:success] = 'The domain has been successfully updated.'
redirect '/custom_domain'
else
erb :custom_domain
end
end
get '/contact' do
erb :'contact'
end
@ -1380,14 +1401,6 @@ post '/site/:username/block' do |username|
end
end
post '/site/delete' do
require_login
if current_site.username != params[:username]
current_site.errors.add :username, 'Could not delete site, site name did not match.'
halt erb(:settings)
end
end
def require_admin
redirect '/' unless signed_in? && current_site.is_admin
end
@ -1420,7 +1433,11 @@ end
def current_site
return nil if session[:id].nil?
@site ||= Site[id: session[:id]]
@_site ||= Site[id: session[:id]]
end
def parent_site
current_site.parent? ? current_site : current_site.parent
end
def require_unbanned_ip

View file

@ -162,7 +162,7 @@ class Site < Sequel::Model
if parent?
return children
else
sites = (parent + children)
sites = ([parent] + children)
sites.delete self
sites
end
@ -204,6 +204,14 @@ class Site < Sequel::Model
false
end
def owner
parent? ? self : parent
end
def owned_by?(site)
account_sites.include? site
end
def is_following?(site)
followings_dataset.select(:id).filter(site_id: site.id).first ? true : false
end

View file

@ -0,0 +1,86 @@
require_relative '../environment.rb'
describe 'site/settings' do
describe 'email' do
include Capybara::DSL
before do
EmailWorker.jobs.clear
@email = "#{SecureRandom.uuid.gsub('-', '')}@example.com"
@site = Fabricate :site, email: @email
page.set_rack_session id: @site.id
visit '/settings'
end
it 'should change email' do
@new_email = "#{SecureRandom.uuid.gsub('-', '')}@example.com"
fill_in 'email', with: @new_email
click_button 'Change Email'
page.must_have_content /successfully changed email/i
@site.reload
@site.email.must_equal @new_email
EmailWorker.jobs.length.must_equal 1
args = EmailWorker.jobs.first['args'].first
args['to'].must_equal @new_email
args['subject'].must_match /confirm your email address/i
args['body'].must_match /hello #{@site.username}/i
args['body'].must_match /#{@site.email_confirmation_token}/
end
it 'should fail for invalid email address' do
@new_email = SecureRandom.uuid.gsub '-', ''
fill_in 'email', with: @new_email
click_button 'Change Email'
page.must_have_content /a valid email address is required/i
@site.reload
@site.email.wont_equal @new_email
EmailWorker.jobs.empty?.must_equal true
end
it 'should fail for existing email' do
@existing_email = "#{SecureRandom.uuid.gsub('-', '')}@example.com"
@existing_site = Fabricate :site, email: @existing_email
fill_in 'email', with: @existing_email
click_button 'Change Email'
page.must_have_content /this email address already exists on neocities/i
@site.reload
@site.email.wont_equal @new_email
EmailWorker.jobs.empty?.must_equal true
end
end
describe 'change password' do
include Capybara::DSL
before do
@site = Fabricate :site, password: 'derpie'
page.set_rack_session id: @site.id
visit '/settings'
end
it 'should change correctly' do
fill_in 'current_password', with: 'derpie'
fill_in 'new_password', with: 'derpie2'
fill_in 'new_password_confirm', with: 'derpie2'
click_button 'Change Password'
page.must_have_content /successfully changed password/i
@site.reload
@site.valid_password?('derpie').must_equal false
@site.valid_password?('derpie2').must_equal true
end
it 'should not change for invalid current password' do
fill_in 'current_password', with: 'dademurphy'
fill_in 'new_password', with: 'derpie2'
fill_in 'new_password_confirm', with: 'derpie2'
click_button 'Change Password'
page.must_have_content /provided password does not match the current one/i
@site.reload
@site.valid_password?('derpie').must_equal true
@site.valid_password?('derpie2').must_equal false
end
end
end

View file

@ -1,4 +1,4 @@
require_relative './environment.rb'
require_relative '../environment.rb'
def generate_ssl_certs(opts={})
# https://github.com/kyledrake/ruby-openssl-cheat-sheet/blob/master/certificate_authority.rb
@ -92,13 +92,13 @@ describe 'site/settings' do
it 'fails without domain set' do
@site = Fabricate :site
page.set_rack_session id: @site.id
visit '/custom_domain'
visit "/settings/#{@site.username}#custom_domain"
page.must_have_content /Cannot upload SSL certificate until domain is added/i
end
it 'fails with expired key' do
@ssl = generate_ssl_certs domain: @domain, expired: true
visit '/custom_domain'
visit "/settings/#{@site.username}#custom_domain"
attach_file 'key', @ssl[:key_path]
attach_file 'cert', @ssl[:combined_cert_path]
click_button 'Upload SSL Key and Certificate'
@ -107,14 +107,14 @@ describe 'site/settings' do
it 'works with valid key and unified cert' do
@ssl = generate_ssl_certs domain: @domain
visit '/custom_domain'
visit "/settings/#{@site.username}#custom_domain"
key = File.read @ssl[:key_path]
combined_cert = File.read @ssl[:combined_cert_path]
page.must_have_content /status: inactive/i
attach_file 'key', @ssl[:key_path]
attach_file 'cert', @ssl[:combined_cert_path]
click_button 'Upload SSL Key and Certificate'
page.current_path.must_equal '/custom_domain'
page.current_path.must_equal "/settings/#{@site.username}"
page.must_have_content /Updated SSL/
page.must_have_content /status: installed/i
@site.reload
@ -123,9 +123,9 @@ describe 'site/settings' do
end
it 'fails with no uploads' do
visit '/custom_domain'
visit "/settings/#{@site.username}#custom_domain"
click_button 'Upload SSL Key and Certificate'
page.current_path.must_equal '/custom_domain'
page.current_path.must_equal "/settings/#{@site.username}"
page.must_have_content /ssl key.+certificate.+required/i
@site.reload
@site.ssl_key.must_equal nil
@ -134,42 +134,42 @@ describe 'site/settings' do
it 'fails gracefully with encrypted key' do
@ssl = generate_ssl_certs domain: @domain
visit '/custom_domain'
visit "/settings/#{@site.username}#custom_domain"
attach_file 'key', './tests/files/ssl/derpie.com-encrypted.key'
attach_file 'cert', @ssl[:cert_path]
click_button 'Upload SSL Key and Certificate'
page.current_path.must_equal '/custom_domain'
page.current_path.must_equal "/settings/#{@site.username}"
page.must_have_content /could not process ssl key/i
end
it 'fails with junk key' do
@ssl = generate_ssl_certs domain: @domain
visit '/custom_domain'
visit "/settings/#{@site.username}#custom_domain"
attach_file 'key', './tests/files/index.html'
attach_file 'cert', @ssl[:cert_path]
click_button 'Upload SSL Key and Certificate'
page.current_path.must_equal '/custom_domain'
page.current_path.must_equal "/settings/#{@site.username}"
page.must_have_content /could not process ssl key/i
end
it 'fails with junk cert' do
@ssl = generate_ssl_certs domain: @domain
visit '/custom_domain'
visit "/settings/#{@site.username}#custom_domain"
attach_file 'key', @ssl[:key_path]
attach_file 'cert', './tests/files/index.html'
click_button 'Upload SSL Key and Certificate'
page.current_path.must_equal '/custom_domain'
page.current_path.must_equal "/settings/#{@site.username}"
page.must_have_content /could not process ssl certificate/i
end
if ENV['TRAVIS'] != 'true'
it 'fails with bad cert chain' do
@ssl = generate_ssl_certs domain: @domain
visit '/custom_domain'
visit "/settings/#{@site.username}#custom_domain"
attach_file 'key', @ssl[:key_path]
attach_file 'cert', @ssl[:bad_combined_cert_path]
click_button 'Upload SSL Key and Certificate'
page.current_path.must_equal '/custom_domain'
page.current_path.must_equal "/settings/#{@site.username}"
page.must_have_content /there is something wrong with your certificate/i
end
end
@ -200,7 +200,7 @@ describe 'site/settings' do
click_button 'Create My Website'
fill_in_valid
click_button 'Create Home Page'
visit '/settings'
visit "/settings/#{@site[:username]}#username"
fill_in 'name', with: ''
click_button 'Change Name'
fill_in 'name', with: '../hack'
@ -215,87 +215,4 @@ describe 'site/settings' do
Site[username: ''].must_equal nil
end
end
describe 'email' do
include Capybara::DSL
before do
EmailWorker.jobs.clear
@email = "#{SecureRandom.uuid.gsub('-', '')}@example.com"
@site = Fabricate :site, email: @email
page.set_rack_session id: @site.id
visit '/settings'
end
it 'should change email' do
@new_email = "#{SecureRandom.uuid.gsub('-', '')}@example.com"
fill_in 'email', with: @new_email
click_button 'Change Email'
page.must_have_content /successfully changed email/i
@site.reload
@site.email.must_equal @new_email
EmailWorker.jobs.length.must_equal 1
args = EmailWorker.jobs.first['args'].first
args['to'].must_equal @new_email
args['subject'].must_match /confirm your email address/i
args['body'].must_match /hello #{@site.username}/i
args['body'].must_match /#{@site.email_confirmation_token}/
end
it 'should fail for invalid email address' do
@new_email = SecureRandom.uuid.gsub '-', ''
fill_in 'email', with: @new_email
click_button 'Change Email'
page.must_have_content /a valid email address is required/i
@site.reload
@site.email.wont_equal @new_email
EmailWorker.jobs.empty?.must_equal true
end
it 'should fail for existing email' do
@existing_email = "#{SecureRandom.uuid.gsub('-', '')}@example.com"
@existing_site = Fabricate :site, email: @existing_email
fill_in 'email', with: @existing_email
click_button 'Change Email'
page.must_have_content /this email address already exists on neocities/i
@site.reload
@site.email.wont_equal @new_email
EmailWorker.jobs.empty?.must_equal true
end
end
describe 'change password' do
include Capybara::DSL
before do
@site = Fabricate :site, password: 'derpie'
page.set_rack_session id: @site.id
visit '/settings'
end
it 'should change correctly' do
fill_in 'current_password', with: 'derpie'
fill_in 'new_password', with: 'derpie2'
fill_in 'new_password_confirm', with: 'derpie2'
click_button 'Change Password'
page.must_have_content /successfully changed password/i
@site.reload
@site.valid_password?('derpie').must_equal false
@site.valid_password?('derpie2').must_equal true
end
it 'should not change for invalid current password' do
fill_in 'current_password', with: 'dademurphy'
fill_in 'new_password', with: 'derpie2'
fill_in 'new_password_confirm', with: 'derpie2'
click_button 'Change Password'
page.must_have_content /provided password does not match the current one/i
@site.reload
@site.valid_password?('derpie').must_equal true
@site.valid_password?('derpie2').must_equal false
end
end
end

View file

@ -1,80 +0,0 @@
<div class="header-Outro">
<div class="row content single-Col">
<h1>Custom Domain</h1>
<h3 class="subtitle">Add your own domain name to your Neocities site!</h3>
</div>
</div>
<div class="content single-Col misc-page">
<h3></h3>
<article>
<% if flash.keys.length > 0 %>
<div class="alert alert-block alert-success">
<% flash.keys.each do |key| %>
<%== flash[key] %>
<% end %>
</div>
<% end %>
<p>
Adding a custom domain allows you to have a domain name attached to your web site. So if you had a domain like <strong>catsknitting.com</strong>, you could have it point to your Neocities site!
</p>
<p>
You will have to purchase a domain name from a registrar like <a href="https://www.namecheap.com/?aff=53678" target="_blank">Namecheap</a>, and then add an A record to point your domain (catsknitting.com) to the following IP address:
</p>
<p><code>198.27.81.179</code></p>
<p>
If you want to add a <strong>www</strong> subdomain, or use a wildcard that will answer to everything (<strong>*</strong>), you will have to make a CNAME pointing to <strong>catsknitting.com</strong> for <strong>www</strong> and/or <strong>*</strong>.
</p>
<p>
After that, you can add the domain to the box below (just the <strong>catsknitting.com</strong>, don't add any subdomains), and your domain should come online within 5 minutes:
</p>
<form method="POST" action="/custom_domain">
<%== csrf_token_input_html %>
<input name="domain" type="text" placeholder="catsknitting.com" value="<%= current_site.domain %>">
<br>
<input class="btn-Action" type="submit" value="Update Domain">
</form>
</article>
<article>
<h2>Add SSL Certificate</h2>
<p>
This allows you to add an SSL key and certificate for your domain, enabling encryption for your site (https). It can take up to 5-30 minutes for the changes to go live, so please be patient. All files must be in PEM format. If your certificate is not bundled with the root and intermediate certificates, ask your certificate provider for help on how to do that.
</p>
<% if current_site.domain.nil? || current_site.domain.empty? %>
<p><strong>Cannot upload SSL certificate until domain is added.</strong></p>
<% else %>
<form method="POST" action="/settings/ssl" enctype="multipart/form-data">
<%== csrf_token_input_html %>
<p>
<strong>
Status: <%= current_site.ssl_installed? ? 'Installed' : 'Inactive' %>
</strong>
</p>
<p>
SSL Key (yourdomain.com.key):
<input name="key" type="file">
</p>
<p>
Bundled Certificates (yourdomain.com-bundle.crt):
<input name="cert" type="file">
</p>
<input class="btn-Action" type="submit" value="Upload SSL Key and Certificate">
</form>
<% end %>
</article>
</div>

View file

@ -1,7 +1,7 @@
<div class="header-Outro">
<div class="row content single-Col">
<h1>Settings</h1>
<h3 class="subtitle">Manage your account</h3>
<h1>Account Settings</h1>
<h3 class="subtitle">Manage the account for your sites</h3>
</div>
</div>
@ -25,37 +25,21 @@
<ul class="nav nav-tabs">
<li class="active"><a href="#plan" data-toggle="tab">Plan</a></li>
<li><a href="#sites" data-toggle="tab">Sites</a></li>
<li><a href="#profile" data-toggle="tab">Profile</a></li>
<li><a href="#customdomain" data-toggle="tab">Custom Domain</a></li>
<li><a href="#password" data-toggle="tab">Password</a></li>
<li><a href="#email" data-toggle="tab">Email</a></li>
<li><a href="#username" data-toggle="tab">Username</a></li>
<li><a href="#nsfw" data-toggle="tab">18+</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="plan">
<%== erb :'settings/plan' %>
<%== erb :'settings/account/plan' %>
</div>
<div class="tab-pane" id="sites">
<%== erb :'settings/sites' %>
</div>
<div class="tab-pane" id="profile">
<%== erb :'settings/profile' %>
</div>
<div class="tab-pane" id="customdomain">
<%== erb :'settings/custom_domain' %>
<%== erb :'settings/account/sites' %>
</div>
<div class="tab-pane" id="password">
<%== erb :'settings/password' %>
<%== erb :'settings/account/password' %>
</div>
<div class="tab-pane" id="email">
<%== erb :'settings/email' %>
</div>
<div class="tab-pane" id="username">
<%== erb :'settings/username' %>
</div>
<div class="tab-pane" id="nsfw">
<%== erb :'settings/nsfw' %>
<%== erb :'settings/account/email' %>
</div>
</div>
</div>

View file

@ -1,5 +1,5 @@
<h2>Change Email</h2>
<form method="POST" action="/change_email">
<form method="POST" action="/settings/change_email">
<%== csrf_token_input_html %>
<p>Current Email: <strong><%= current_site.email %></strong></p>

View file

@ -1,5 +1,5 @@
<h2>Change Password</h2>
<form method="POST" action="/change_password">
<form method="POST" action="/settings/change_password">
<%== csrf_token_input_html %>
<p>Current Password:</p>

View file

@ -4,21 +4,16 @@
<h6>No other sites are currently linked to this account.</h6>
<% else %>
<table class="table">
<tr>
<td>
<a href="//<%= current_site.host %>"><strong><%= current_site.title %></strong></a> (primary)
</td>
<td>
Manage this site
</td>
</tr>
<% current_site.children.each do |site| %>
<% current_site.owner.account_sites.each do |site| %>
<tr>
<td>
<a href="//<%= site.host %>" target="_blank"><%= site.title %></a>
<% if site.parent? %>
<strong>(parent account)</strong>
<% end %>
</td>
<td>
<a href="#">Manage this site</a>
<a href="/settings/<%= site.username %>">Settings</a>
</td>
</tr>
<% end %>
@ -29,7 +24,7 @@
<p>You can now create new sites that are linked to this account! Sites will share the free space you have available. You have <strong><%= Site::CHILD_SITES_MAX - current_site.children_dataset.count %></strong> new sites remaining.</p>
<form action="/site/create_child" method="POST">
<form action="/settings/create_child" method="POST">
<%== csrf_token_input_html %>
<p>Site Name:</p>

View file

@ -1,4 +0,0 @@
<h2>Custom Domain</h2>
<p>
You can configure a custom domain for your Neocities site! <strong><a href="/custom_domain">Click Here</a></strong> for more information.
</p>

89
views/settings/site.erb Normal file
View file

@ -0,0 +1,89 @@
<div class="header-Outro">
<div class="row content single-Col">
<h1>Site Settings</h1>
<h3 class="subtitle"><strong><%= @site.username %></strong></h3>
</div>
</div>
<div class="content single-Col misc-page txt-Center">
<article>
<section>
<div class="txt-Center">
<% if flash[:success] %>
<div class="alert alert-block alert-success" style="margin-top: 20px">
<%== flash[:success] %>
</div>
<% end %>
<% if flash[:error] %>
<div class="alert alert-block alert-error" style="margin-top: 20px">
<%== flash[:error] %>
</div>
<% end %>
</div>
<div class="tabbable" style="margin-top: 20px"> <!-- Only required for left/right tabs -->
<ul class="nav nav-tabs">
<li class="active"><a href="#profile" data-toggle="tab">Profile</a></li>
<li><a href="#custom_domain" data-toggle="tab">Custom Domain</a></li>
<li><a href="#username" data-toggle="tab">Username</a></li>
<li><a href="#nsfw" data-toggle="tab">18+</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="profile">
<%== erb :'settings/site/profile' %>
</div>
<div class="tab-pane" id="custom_domain">
<%== erb :'settings/site/custom_domain' %>
</div>
<div class="tab-pane" id="username">
<%== erb :'settings/site/username' %>
</div>
<div class="tab-pane" id="nsfw">
<%== erb :'settings/site/nsfw' %>
</div>
</div>
</div>
<!--
<h2>Delete Site</h2>
<p class="tiny">
If you want to delete your account, you can do that here. We're sorry to see you go, but we understand if Neocities isn't right for you. If there's any specific reason you're leaving, it would be great if you <a href="/contact">let us know</a> so we can try to make your experience better in the future.
</p>
<div>
<a href="#deleteSite" data-toggle="modal" class="btn">Delete Site</a>
</div>
-->
</section>
</article>
</div>
<div class="modal hide fade" id="deleteSite" tabindex="-1" role="dialog" aria-labelledby="deleteSiteLabel" aria-hidden="true">
<form method="POST" action="/site/delete">
<%== csrf_token_input_html %>
<div class="modal-header">
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">x</button>
<h3 id="deleteSiteLabel">Permanently Delete Site</h3>
</div>
<div class="modal-body">
<strong style="color: red">WARNING: This will permanently delete your web site and Neocities account. There is no undo!</strong>
<p>Delete Site Name: <strong><%= current_site.username %></strong></p>
<p>Confirm your site name by typing it here:</p>
<input class="input-Area" name="username" type="text">
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button type="submit" class="btn btn-Action">Permanently Delete Site</button>
</div>
</form>
</div>
<script>
$(document).ready(function() {
if (location.hash !== '') $('a[href="' + location.hash + '"]').tab('show');
return $('a[data-toggle="tab"]').on('shown', function(e) {
return location.hash = $(e.target).attr('href').substr(1);
});
});
</script>

View file

@ -0,0 +1,60 @@
<h2>Custom Domain</h2>
<h3 class="subtitle">Add your own domain name to your Neocities site!</h3>
<p>
Adding a custom domain allows you to have a domain name attached to your web site. So if you had a domain like <strong>catsknitting.com</strong>, you could have it point to your Neocities site!
</p>
<p>
You will have to purchase a domain name from a registrar like <a href="https://www.namecheap.com/?aff=53678" target="_blank">Namecheap</a>, and then add an A record to point your domain (catsknitting.com) to the following IP address:
</p>
<p><code>198.27.81.179</code></p>
<p>
If you want to add a <strong>www</strong> subdomain, or use a wildcard that will answer to everything (<strong>*</strong>), you will have to make a CNAME pointing to <strong>catsknitting.com</strong> for <strong>www</strong> and/or <strong>*</strong>.
</p>
<p>
After that, you can add the domain to the box below (just the <strong>catsknitting.com</strong>, don't add any subdomains), and your domain should come online within 5 minutes:
</p>
<form method="POST" action="/settings/<%= @site.username %>/custom_domain">
<%== csrf_token_input_html %>
<input name="domain" type="text" placeholder="catsknitting.com" value="<%= @site.domain %>">
<br>
<input class="btn-Action" type="submit" value="Update Domain">
</form>
<h2>Add SSL Certificate</h2>
<p>
This allows you to add an SSL key and certificate for your domain, enabling encryption for your site (https). It can take up to 5-30 minutes for the changes to go live, so please be patient. All files must be in PEM format. If your certificate is not bundled with the root and intermediate certificates, ask your certificate provider for help on how to do that.
</p>
<% if @site.domain.nil? || @site.domain.empty? %>
<p><strong>Cannot upload SSL certificate until domain is added.</strong></p>
<% else %>
<form method="POST" action="/settings/<%= @site.username %>/ssl" enctype="multipart/form-data">
<%== csrf_token_input_html %>
<p>
<strong>
Status: <%= @site.ssl_installed? ? 'Installed' : 'Inactive' %>
</strong>
</p>
<p>
SSL Key (yourdomain.com.key):
<input name="key" type="file">
</p>
<p>
Bundled Certificates (yourdomain.com-bundle.crt):
<input name="cert" type="file">
</p>
<input class="btn-Action" type="submit" value="Upload SSL Key and Certificate">
</form>
<% end %>

View file

@ -4,14 +4,14 @@
If your site contains objectionable (18+) content, check this box. Your site will not be removed, but it will be listed on a special browse page. We don't have an official policy on what defines 18+ content yet, but basically it's just pornography and lewd/sick/gross images. Thanks for your patience and understanding as we try to find a way to balance out the needs of everyone.
</p>
<form method="POST" action="/change_nsfw">
<form method="POST" action="/settings/<%= @site.username %>/change_nsfw">
<%== csrf_token_input_html %>
<input name="is_nsfw" type="hidden" value="false">
<p>
<strong>
My page has 18+ content:&nbsp;&nbsp;&nbsp;
<input name="is_nsfw" type="checkbox" value="true" style="margin-top: 0px"
<% if current_site.is_nsfw %>checked<% end %>
<% if @site.is_nsfw %>checked<% end %>
>
</strong>
</p>

View file

@ -1,11 +1,11 @@
<h2>Site Profile</h2>
<div>
<form method="POST" action="/settings/profile">
<form method="POST" action="/settings/<%= @site.username %>/profile">
<%== csrf_token_input_html %>
<p>
<input name="site[profile_comments_enabled]" type="hidden" value="true">
<input name="site[profile_comments_enabled]" type="checkbox" value="false"
<% if current_site.profile_comments_enabled == false %>checked<% end %>
<% if @site.profile_comments_enabled == false %>checked<% end %>
> Turn off profile comments
</p>

View file

@ -1,5 +1,5 @@
<h2>Change Site (User) Name</h2>
<form method="POST" action="/change_name">
<form method="POST" action="/settings/<%= @site.username %>/change_name">
<%== csrf_token_input_html %>
<p class="tiny">
It cannot contain spaces, and can only use the following characters: a-z A-Z 0-9 _ -
@ -7,7 +7,7 @@
<p>
Current Name:
<span style="color: green"><strong><%= current_site.username %></strong></span>
<span style="color: green"><strong><%= @site.username %></strong></span>
</p>
<p>