mirror of
https://github.com/neocities/neocities.git
synced 2025-04-24 17:22:35 +02:00
fix migrations, acceptance testing for auth, 32 char username limit
This commit is contained in:
parent
fdd4017523
commit
5dfc715148
18 changed files with 247 additions and 125 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -20,3 +20,4 @@ tests/coverage
|
||||||
config.yml
|
config.yml
|
||||||
.DS_Store
|
.DS_Store
|
||||||
domains
|
domains
|
||||||
|
public/sites_test
|
||||||
|
|
4
Gemfile
4
Gemfile
|
@ -52,6 +52,10 @@ group :test do
|
||||||
gem 'webmock'
|
gem 'webmock'
|
||||||
gem 'mocha', require: nil
|
gem 'mocha', require: nil
|
||||||
gem 'rake', require: nil
|
gem 'rake', require: nil
|
||||||
|
gem 'poltergeist'
|
||||||
|
gem 'phantomjs', require: 'phantomjs/poltergeist'
|
||||||
|
gem 'capybara'
|
||||||
|
gem 'capybara_minitest_spec'
|
||||||
|
|
||||||
platform :mri do
|
platform :mri do
|
||||||
gem 'simplecov', require: nil
|
gem 'simplecov', require: nil
|
||||||
|
|
26
Gemfile.lock
26
Gemfile.lock
|
@ -6,10 +6,20 @@ GEM
|
||||||
ansi (1.4.3)
|
ansi (1.4.3)
|
||||||
bcrypt (3.1.7)
|
bcrypt (3.1.7)
|
||||||
builder (3.2.2)
|
builder (3.2.2)
|
||||||
|
capybara (2.2.1)
|
||||||
|
mime-types (>= 1.16)
|
||||||
|
nokogiri (>= 1.3.3)
|
||||||
|
rack (>= 1.0.0)
|
||||||
|
rack-test (>= 0.5.4)
|
||||||
|
xpath (~> 2.0)
|
||||||
|
capybara_minitest_spec (1.0.1)
|
||||||
|
capybara (>= 2)
|
||||||
|
minitest (>= 2)
|
||||||
celluloid (0.15.2)
|
celluloid (0.15.2)
|
||||||
timers (~> 1.1.0)
|
timers (~> 1.1.0)
|
||||||
childprocess (0.5.2)
|
childprocess (0.5.2)
|
||||||
ffi (~> 1.0, >= 1.0.11)
|
ffi (~> 1.0, >= 1.0.11)
|
||||||
|
cliver (0.3.2)
|
||||||
coderay (1.1.0)
|
coderay (1.1.0)
|
||||||
columnize (0.3.6)
|
columnize (0.3.6)
|
||||||
connection_pool (2.0.0)
|
connection_pool (2.0.0)
|
||||||
|
@ -39,6 +49,7 @@ GEM
|
||||||
metaclass (0.0.4)
|
metaclass (0.0.4)
|
||||||
method_source (0.8.2)
|
method_source (0.8.2)
|
||||||
mime-types (1.25.1)
|
mime-types (1.25.1)
|
||||||
|
mini_portile (0.5.3)
|
||||||
minitest (5.3.1)
|
minitest (5.3.1)
|
||||||
minitest-reporters (1.0.2)
|
minitest-reporters (1.0.2)
|
||||||
ansi
|
ansi
|
||||||
|
@ -48,7 +59,15 @@ GEM
|
||||||
mocha (1.0.0)
|
mocha (1.0.0)
|
||||||
metaclass (~> 0.0.1)
|
metaclass (~> 0.0.1)
|
||||||
multi_json (1.9.2)
|
multi_json (1.9.2)
|
||||||
|
nokogiri (1.6.1)
|
||||||
|
mini_portile (~> 0.5.0)
|
||||||
pg (0.17.1)
|
pg (0.17.1)
|
||||||
|
phantomjs (1.9.7.0)
|
||||||
|
poltergeist (1.5.0)
|
||||||
|
capybara (~> 2.1)
|
||||||
|
cliver (~> 0.3.1)
|
||||||
|
multi_json (~> 1.0)
|
||||||
|
websocket-driver (>= 0.2.0)
|
||||||
polyglot (0.3.4)
|
polyglot (0.3.4)
|
||||||
powerbar (1.0.11)
|
powerbar (1.0.11)
|
||||||
ansi (~> 1.4.0)
|
ansi (~> 1.4.0)
|
||||||
|
@ -129,6 +148,9 @@ GEM
|
||||||
addressable (>= 2.2.7)
|
addressable (>= 2.2.7)
|
||||||
crack (>= 0.3.2)
|
crack (>= 0.3.2)
|
||||||
websocket (1.0.7)
|
websocket (1.0.7)
|
||||||
|
websocket-driver (0.3.2)
|
||||||
|
xpath (2.0.0)
|
||||||
|
nokogiri (~> 1.3)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
@ -136,6 +158,8 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
ago
|
ago
|
||||||
bcrypt
|
bcrypt
|
||||||
|
capybara
|
||||||
|
capybara_minitest_spec
|
||||||
fabrication
|
fabrication
|
||||||
faker
|
faker
|
||||||
hiredis
|
hiredis
|
||||||
|
@ -148,6 +172,8 @@ DEPENDENCIES
|
||||||
minitest-reporters
|
minitest-reporters
|
||||||
mocha
|
mocha
|
||||||
pg
|
pg
|
||||||
|
phantomjs
|
||||||
|
poltergeist
|
||||||
pry
|
pry
|
||||||
pry-debugger
|
pry-debugger
|
||||||
puma
|
puma
|
||||||
|
|
2
Rakefile
2
Rakefile
|
@ -7,7 +7,7 @@ end
|
||||||
desc "Run all tests"
|
desc "Run all tests"
|
||||||
Rake::TestTask.new do |t|
|
Rake::TestTask.new do |t|
|
||||||
t.libs << "spec"
|
t.libs << "spec"
|
||||||
t.test_files = FileList['tests/*_test.rb']
|
t.test_files = FileList['tests/*_tests.rb']
|
||||||
t.verbose = true
|
t.verbose = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
19
app.rb
19
app.rb
|
@ -103,12 +103,12 @@ end
|
||||||
|
|
||||||
get '/blog' do
|
get '/blog' do
|
||||||
# expires 500, :public, :must_revalidate
|
# expires 500, :public, :must_revalidate
|
||||||
return File.read File.join(DIR_ROOT, 'public', 'sites', 'blog', 'index.html')
|
return File.read File.join(Sites::SITE_FILES_ROOT, 'blog', 'index.html')
|
||||||
end
|
end
|
||||||
|
|
||||||
get '/blog/:article' do |article|
|
get '/blog/:article' do |article|
|
||||||
# expires 500, :public, :must_revalidate
|
# expires 500, :public, :must_revalidate
|
||||||
path = File.join DIR_ROOT, 'public', 'sites', 'blog', "#{article}.html"
|
path = File.join Sites::SITE_FILES_ROOT, 'blog', "#{article}.html"
|
||||||
pass if !File.exist?(path)
|
pass if !File.exist?(path)
|
||||||
File.read path
|
File.read path
|
||||||
end
|
end
|
||||||
|
@ -137,9 +137,16 @@ end
|
||||||
|
|
||||||
post '/create' do
|
post '/create' do
|
||||||
dashboard_if_signed_in
|
dashboard_if_signed_in
|
||||||
@site = Site.new username: params[:username], password: params[:password], email: params[:email], new_tags: params[:tags], is_nsfw: params[:is_nsfw], ip: request.ip
|
@site = Site.new(
|
||||||
|
username: params[:username],
|
||||||
|
password: params[:password],
|
||||||
|
email: params[:email],
|
||||||
|
new_tags: params[:tags],
|
||||||
|
is_nsfw: params[:is_nsfw],
|
||||||
|
ip: request.ip
|
||||||
|
)
|
||||||
|
|
||||||
recaptcha_is_valid = recaptcha_valid?
|
recaptcha_is_valid = ENV['RACK_ENV'] == 'test' || recaptcha_valid?
|
||||||
|
|
||||||
if @site.valid? && recaptcha_is_valid
|
if @site.valid? && recaptcha_is_valid
|
||||||
|
|
||||||
|
@ -148,7 +155,7 @@ post '/create' do
|
||||||
DB.transaction {
|
DB.transaction {
|
||||||
@site.save
|
@site.save
|
||||||
|
|
||||||
FileUtils.mkdir base_path
|
FileUtils.mkdir_p base_path
|
||||||
|
|
||||||
File.write File.join(base_path, 'index.html'), slim(:'templates/index', pretty: true, layout: false)
|
File.write File.join(base_path, 'index.html'), slim(:'templates/index', pretty: true, layout: false)
|
||||||
File.write File.join(base_path, 'not_found.html'), slim(:'templates/not_found', pretty: true, layout: false)
|
File.write File.join(base_path, 'not_found.html'), slim(:'templates/not_found', pretty: true, layout: false)
|
||||||
|
@ -661,7 +668,7 @@ def current_site
|
||||||
end
|
end
|
||||||
|
|
||||||
def site_base_path(subname)
|
def site_base_path(subname)
|
||||||
File.join settings.public_folder, 'sites', subname
|
File.join Site::SITE_FILES_ROOT, subname
|
||||||
end
|
end
|
||||||
|
|
||||||
def site_file_path(filename)
|
def site_file_path(filename)
|
||||||
|
|
|
@ -4,6 +4,6 @@ Sequel.migration do
|
||||||
}
|
}
|
||||||
|
|
||||||
down {
|
down {
|
||||||
DB.add_column :sites, :hits
|
DB.drop_column :sites, :hits
|
||||||
}
|
}
|
||||||
end
|
end
|
|
@ -4,6 +4,6 @@ Sequel.migration do
|
||||||
}
|
}
|
||||||
|
|
||||||
down {
|
down {
|
||||||
DB.add_column :sites, :is_admin
|
DB.drop_column :sites, :is_admin
|
||||||
}
|
}
|
||||||
end
|
end
|
|
@ -4,6 +4,6 @@ Sequel.migration do
|
||||||
}
|
}
|
||||||
|
|
||||||
down {
|
down {
|
||||||
DB.add_column :sites, :is_banned
|
DB.drop_column :sites, :is_banned
|
||||||
}
|
}
|
||||||
end
|
end
|
|
@ -4,6 +4,6 @@ Sequel.migration do
|
||||||
}
|
}
|
||||||
|
|
||||||
down {
|
down {
|
||||||
DB.add_column :sites, :ip
|
DB.drop_column :sites, :ip
|
||||||
}
|
}
|
||||||
end
|
end
|
|
@ -6,6 +6,5 @@ Sequel.migration do
|
||||||
|
|
||||||
down {
|
down {
|
||||||
DB.drop_column :sites, :password_reset_token
|
DB.drop_column :sites, :password_reset_token
|
||||||
DB.drop_index :sites, :password_reset_token
|
|
||||||
}
|
}
|
||||||
end
|
end
|
|
@ -6,6 +6,5 @@ Sequel.migration do
|
||||||
|
|
||||||
down {
|
down {
|
||||||
DB.drop_column :sites, :site_changed
|
DB.drop_column :sites, :site_changed
|
||||||
DB.drop_index :sites, :site_changed
|
|
||||||
}
|
}
|
||||||
end
|
end
|
|
@ -6,6 +6,5 @@ Sequel.migration do
|
||||||
|
|
||||||
down {
|
down {
|
||||||
DB.drop_column :sites, :changed_count
|
DB.drop_column :sites, :changed_count
|
||||||
DB.drop_index :sites, :changed_count
|
|
||||||
}
|
}
|
||||||
end
|
end
|
|
@ -1,11 +1,38 @@
|
||||||
class Site < Sequel::Model
|
class Site < Sequel::Model
|
||||||
# We might need to include fonts in here..
|
# We might need to include fonts in here..
|
||||||
VALID_MIME_TYPES = ['text/plain', 'text/html', 'text/css', 'application/javascript', 'image/png', 'image/jpeg', 'image/gif', 'image/svg+xml', 'application/vnd.ms-fontobject', 'application/x-font-ttf', 'application/octet-stream', 'text/csv', 'text/tsv', 'text/cache-manifest', 'image/x-icon', 'application/pdf', 'application/pgp-keys', 'text/xml', 'application/xml', 'audio/midi']
|
VALID_MIME_TYPES = %w{
|
||||||
VALID_EXTENSIONS = %w{ html htm txt text css js jpg jpeg png gif svg md markdown eot ttf woff json geojson csv tsv mf ico pdf asc key pgp xml mid midi }
|
text/plain
|
||||||
#USERNAME_SHITLIST = %w{ payment secure login signin www ww web } # I thought they were funny personally, but everybody is freaking out so..
|
text/html
|
||||||
|
text/css
|
||||||
|
application/javascript
|
||||||
|
image/png
|
||||||
|
image/jpeg
|
||||||
|
image/gif
|
||||||
|
image/svg+xml
|
||||||
|
application/vnd.ms-fontobject
|
||||||
|
application/x-font-ttf
|
||||||
|
application/octet-stream
|
||||||
|
text/csv
|
||||||
|
text/tsv
|
||||||
|
text/cache-manifest
|
||||||
|
image/x-icon
|
||||||
|
application/pdf
|
||||||
|
application/pgp-keys
|
||||||
|
text/xml
|
||||||
|
application/xml
|
||||||
|
audio/midi
|
||||||
|
}
|
||||||
|
VALID_EXTENSIONS = %w{
|
||||||
|
html htm txt text css js jpg jpeg png gif svg md markdown eot ttf woff json
|
||||||
|
geojson csv tsv mf ico pdf asc key pgp xml mid midi
|
||||||
|
}
|
||||||
MAX_SPACE = (5242880*2) # 10MB
|
MAX_SPACE = (5242880*2) # 10MB
|
||||||
MINIMUM_PASSWORD_LENGTH = 5
|
MINIMUM_PASSWORD_LENGTH = 5
|
||||||
BAD_USERNAME_REGEX = /[^\w-]/i
|
BAD_USERNAME_REGEX = /[^\w-]/i
|
||||||
|
VALID_HOSTNAME = /^[a-z0-9][a-z0-9-]+?[a-z0-9]$/i # http://tools.ietf.org/html/rfc1123
|
||||||
|
|
||||||
|
SITE_FILES_ROOT = File.join(DIR_ROOT, 'public', (ENV['RACK_ENV'] == 'test' ? 'sites_test' : 'sites'))
|
||||||
|
|
||||||
many_to_one :server
|
many_to_one :server
|
||||||
many_to_many :tags
|
many_to_many :tags
|
||||||
|
|
||||||
|
@ -77,13 +104,15 @@ class Site < Sequel::Model
|
||||||
errors.add :over_capacity, 'We are currently at capacity, and cannot create your home page. We will fix this shortly. Please come back later and try again, our apologies.'
|
errors.add :over_capacity, 'We are currently at capacity, and cannot create your home page. We will fix this shortly. Please come back later and try again, our apologies.'
|
||||||
end
|
end
|
||||||
|
|
||||||
if values[:username].nil? || values[:username].empty? || values[:username].match(BAD_USERNAME_REGEX)
|
if !values[:username].match(VALID_HOSTNAME)
|
||||||
errors.add :username, 'A valid username is required.'
|
errors.add :username, 'A valid user/site name is required.'
|
||||||
|
end
|
||||||
|
|
||||||
|
if values[:username].length > 32
|
||||||
|
errors.add :username, 'User/site name cannot exceed 32 characters.'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check for existing user
|
# Check for existing user
|
||||||
|
|
||||||
|
|
||||||
user = self.class.select(:id, :username).filter(username: values[:username]).first
|
user = self.class.select(:id, :username).filter(username: values[:username]).first
|
||||||
|
|
||||||
if user
|
if user
|
||||||
|
@ -109,7 +138,7 @@ class Site < Sequel::Model
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_path
|
def file_path
|
||||||
File.join DIR_ROOT, 'public', 'sites', username
|
File.join SITE_FILES_ROOT, username
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_list
|
def file_list
|
||||||
|
|
144
tests/acceptance_tests.rb
Normal file
144
tests/acceptance_tests.rb
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
require_relative './environment'
|
||||||
|
|
||||||
|
Capybara.app = Sinatra::Application
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
Capybara.reset_sessions!
|
||||||
|
Capybara.use_default_driver
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'index' do
|
||||||
|
include Capybara::DSL
|
||||||
|
it 'goes to signup' do
|
||||||
|
visit '/'
|
||||||
|
click_button 'Create My Website'
|
||||||
|
page.must_have_content('Create a New Home Page')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'signup' do
|
||||||
|
include Capybara::DSL
|
||||||
|
|
||||||
|
def fill_in_valid
|
||||||
|
@site = Fabricate.attributes_for(:site)
|
||||||
|
fill_in 'username', with: @site[:username]
|
||||||
|
fill_in 'password', with: @site[:password]
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit_signup
|
||||||
|
visit '/'
|
||||||
|
click_button 'Create My Website'
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
Capybara.reset_sessions!
|
||||||
|
visit_signup
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'succeeds with valid data' do
|
||||||
|
fill_in_valid
|
||||||
|
click_button 'Create Home Page'
|
||||||
|
page.must_have_content 'Your Website'
|
||||||
|
assert_equal(
|
||||||
|
true,
|
||||||
|
File.exist?(File.join(Site::SITE_FILES_ROOT, @site[:username], 'index.html'))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails to create for existing site' do
|
||||||
|
fill_in_valid
|
||||||
|
click_button 'Create Home Page'
|
||||||
|
page.must_have_content 'Your Website'
|
||||||
|
Capybara.reset_sessions!
|
||||||
|
visit_signup
|
||||||
|
fill_in 'username', with: @site[:username]
|
||||||
|
fill_in 'password', with: @site[:password]
|
||||||
|
click_button 'Create Home Page'
|
||||||
|
page.must_have_content 'already taken'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails with missing password' do
|
||||||
|
fill_in_valid
|
||||||
|
fill_in 'password', with: ''
|
||||||
|
click_button 'Create Home Page'
|
||||||
|
page.must_have_content 'Password must be at least 5 characters'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails with short password' do
|
||||||
|
fill_in_valid
|
||||||
|
fill_in 'password', with: 'derp'
|
||||||
|
click_button 'Create Home Page'
|
||||||
|
page.must_have_content 'Password must be at least 5 characters'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails with invalid hostname for username' do
|
||||||
|
fill_in_valid
|
||||||
|
fill_in 'username', with: '|\|0p|E'
|
||||||
|
click_button 'Create Home Page'
|
||||||
|
page.current_path.must_equal '/create'
|
||||||
|
page.must_have_content 'A valid user/site name is required'
|
||||||
|
fill_in 'username', with: 'nope-'
|
||||||
|
click_button 'Create Home Page'
|
||||||
|
page.must_have_content 'A valid user/site name is required'
|
||||||
|
fill_in 'username', with: '-nope'
|
||||||
|
click_button 'Create Home Page'
|
||||||
|
page.must_have_content 'A valid user/site name is required'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails with username greater than 32 characters' do
|
||||||
|
fill_in_valid
|
||||||
|
fill_in 'username', with: SecureRandom.hex+'1'
|
||||||
|
click_button 'Create Home Page'
|
||||||
|
page.current_path.must_equal '/create'
|
||||||
|
page.must_have_content 'cannot exceed 32 characters'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'signin' do
|
||||||
|
include Capybara::DSL
|
||||||
|
|
||||||
|
def fill_in_valid
|
||||||
|
site = Fabricate.attributes_for :site
|
||||||
|
fill_in 'username', with: site[:username]
|
||||||
|
fill_in 'password', with: site[:password]
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
Capybara.reset_sessions!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails for invalid login' do
|
||||||
|
visit '/'
|
||||||
|
click_link 'Sign In'
|
||||||
|
page.must_have_content 'Welcome back'
|
||||||
|
fill_in_valid
|
||||||
|
click_button 'Sign in'
|
||||||
|
page.must_have_content 'Invalid login'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails for missing login' do
|
||||||
|
visit '/'
|
||||||
|
click_link 'Sign In'
|
||||||
|
auth = {username: SecureRandom.hex, password: Faker::Internet.password}
|
||||||
|
fill_in 'username', with: auth[:username]
|
||||||
|
fill_in 'password', with: auth[:password]
|
||||||
|
click_button 'Sign in'
|
||||||
|
page.must_have_content 'Invalid login'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'logs in with proper credentials' do
|
||||||
|
visit '/'
|
||||||
|
click_button 'Create My Website'
|
||||||
|
site = Fabricate.attributes_for(:site)
|
||||||
|
fill_in 'username', with: site[:username]
|
||||||
|
fill_in 'password', with: site[:password]
|
||||||
|
click_button 'Create Home Page'
|
||||||
|
Capybara.reset_sessions!
|
||||||
|
visit '/'
|
||||||
|
click_link 'Sign In'
|
||||||
|
fill_in 'username', with: site[:username]
|
||||||
|
fill_in 'password', with: site[:password]
|
||||||
|
click_button 'Sign in'
|
||||||
|
page.must_have_content 'Your Website'
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,93 +0,0 @@
|
||||||
require_relative './environment'
|
|
||||||
|
|
||||||
include Rack::Test::Methods
|
|
||||||
|
|
||||||
def app; App end
|
|
||||||
def status; last_response.status end
|
|
||||||
def headers; last_response.headers end
|
|
||||||
def body; last_response.body end
|
|
||||||
|
|
||||||
describe 'index' do
|
|
||||||
it 'loads' do
|
|
||||||
get '/'
|
|
||||||
status.must_equal 200
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'signin' do
|
|
||||||
it 'fails for missing login' do
|
|
||||||
post '/signin', username: 'derpie', password: 'lol'
|
|
||||||
fail_signin
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'fails for bad password' do
|
|
||||||
@site = Fabricate :site
|
|
||||||
post '/signin', username: @site.username, password: 'derp'
|
|
||||||
fail_signin
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'fails for no input' do
|
|
||||||
post '/signin'
|
|
||||||
fail_signin
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'succeeds for valid input' do
|
|
||||||
password = '1tw0rkz'
|
|
||||||
@account = Fabricate :account, password: password
|
|
||||||
post '/accounts/signin', username: @account.email, password: password
|
|
||||||
headers['Location'].must_equal 'http://example.org/dashboard'
|
|
||||||
mock_dashboard_calls @account.email
|
|
||||||
get '/dashboard'
|
|
||||||
body.must_match /Dashboard/
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'account creation' do
|
|
||||||
it 'fails for no input' do
|
|
||||||
post '/accounts/create'
|
|
||||||
status.must_equal 200
|
|
||||||
body.must_match /There were some errors.+Valid email address is required.+Password must be/
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'fails with invalid email' do
|
|
||||||
post '/accounts/create', email: 'derplol'
|
|
||||||
status.must_equal 200
|
|
||||||
body.must_match /errors.+valid email/i
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'fails with invalid password' do
|
|
||||||
post '/accounts/create', 'email@example.com', password: 'sdd'
|
|
||||||
status.must_equal 200
|
|
||||||
body.must_match /errors.+Password must be at least #{Account::MINIMUM_PASSWORD_LENGTH} characters/i
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'succeeds with valid info' do
|
|
||||||
account_attributes = Fabricate.attributes_for :account
|
|
||||||
|
|
||||||
mock_dashboard_calls account_attributes[:email]
|
|
||||||
|
|
||||||
post '/accounts/create', account_attributes
|
|
||||||
status.must_equal 302
|
|
||||||
headers['Location'].must_equal 'http://example.org/dashboard'
|
|
||||||
|
|
||||||
get '/dashboard'
|
|
||||||
body.must_match /Dashboard/
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'temporary account login' do
|
|
||||||
end
|
|
||||||
|
|
||||||
def fail_signin
|
|
||||||
headers['Location'].must_equal 'http://example.org/'
|
|
||||||
get '/'
|
|
||||||
body.must_match /invalid signin/i
|
|
||||||
end
|
|
||||||
|
|
||||||
def api_url
|
|
||||||
uri = Addressable::URI.parse $config['bitcoind_rpchost'] ? $config['bitcoind_rpchost'] : 'http://localhost'
|
|
||||||
uri.port = 8332 if uri.port.nil?
|
|
||||||
uri.user = $config['bitcoind_rpcuser'] if uri.user.nil?
|
|
||||||
uri.password = $config['bitcoind_rpcpassword'] if uri.password.nil?
|
|
||||||
"#{uri.to_s}/"
|
|
||||||
end
|
|
|
@ -20,7 +20,7 @@ Bundler.require :test
|
||||||
require 'minitest/autorun'
|
require 'minitest/autorun'
|
||||||
require 'sidekiq/testing/inline'
|
require 'sidekiq/testing/inline'
|
||||||
|
|
||||||
Account.bcrypt_cost = BCrypt::Engine::MIN_COST
|
Site.bcrypt_cost = BCrypt::Engine::MIN_COST
|
||||||
|
|
||||||
MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
|
MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
|
||||||
|
|
||||||
|
@ -29,8 +29,11 @@ Sequel.extension :migration
|
||||||
|
|
||||||
Sequel::Migrator.apply DB, './migrations', 0
|
Sequel::Migrator.apply DB, './migrations', 0
|
||||||
Sequel::Migrator.apply DB, './migrations'
|
Sequel::Migrator.apply DB, './migrations'
|
||||||
|
Server.create ip: '127.0.0.1', slots_available: 999999
|
||||||
|
|
||||||
Fabrication.configure do |config|
|
Fabrication.configure do |config|
|
||||||
config.fabricator_path = 'tests/fabricators'
|
config.fabricator_path = 'tests/fabricators'
|
||||||
config.path_prefix = DIR_ROOT
|
config.path_prefix = DIR_ROOT
|
||||||
end
|
end
|
||||||
|
|
||||||
|
I18n.enforce_available_locales = true
|
|
@ -1,4 +1,4 @@
|
||||||
Fabricator(:site) do
|
Fabricator(:site) do
|
||||||
username { Faker::Internet.email }
|
username { SecureRandom.hex }
|
||||||
password { 'abcde' }
|
password { 'abcde' }
|
||||||
end
|
end
|
|
@ -19,35 +19,39 @@ javascript:
|
||||||
h2.txt-Center Create a New Home Page
|
h2.txt-Center Create a New Home Page
|
||||||
|
|
||||||
.col.col-50 style="margin:0 auto; float:none"
|
.col.col-50 style="margin:0 auto; float:none"
|
||||||
p.tiny First, enter a username. This will also be used as your site path.<br><b>Do not forget this, it will be used to sign in to and manage your home page.</b> It cannot contain spaces, and can only use the following characters: a-z A-Z 0-9 _ -
|
hr
|
||||||
|
p.tiny First, enter a username. This will also be used as your site name.<br><b>Do not forget this, it will be used to sign in to and manage your home page.</b> It can only contain letters, numbers, underscores and hyphens, and can only be 32 characters long.
|
||||||
br
|
br
|
||||||
h5 Username
|
h5 Username
|
||||||
p.tiny <input class="input-Area" name="username" type="text" placeholder="yourusername" value="#{@site.username}" autocapitalize="off" autocorrect="off">.neocities.org
|
p.tiny <input class="input-Area" name="username" type="text" placeholder="yourusername" value="#{@site.username}" autocapitalize="off" autocorrect="off">.neocities.org
|
||||||
|
hr
|
||||||
p.tiny Next, enter a password. This will be used to allow you to login. Minimum 5 characters. If you don't make it a good password, Dade Murphy from the movie Hackers will come in and steal your "garbage files".
|
p.tiny Next, enter a password. This will be used to allow you to login. Minimum 5 characters. If you don't make it a good password, Dade Murphy from the movie Hackers will come in and steal your "garbage files".
|
||||||
|
|
||||||
hr
|
|
||||||
h5 Password
|
h5 Password
|
||||||
input class="input-Area" name="password" type="password"
|
input class="input-Area" name="password" type="password"
|
||||||
|
|
||||||
br
|
br
|
||||||
|
hr
|
||||||
p.tiny Now you can enter an e-mail address. Your e-mail address is private and we will not show it to anyone for any reason. You don't have to provide one, but <b>we will not be able to reset your password without it, so don't lose your username and password if you leave this blank!</b>
|
p.tiny Now you can enter an e-mail address. Your e-mail address is private and we will not show it to anyone for any reason. You don't have to provide one, but <b>we will not be able to reset your password without it, so don't lose your username and password if you leave this blank!</b>
|
||||||
|
|
||||||
hr
|
|
||||||
h5 Email
|
h5 Email
|
||||||
input class="input-Area" name="email" type="email" placeholder="youremail@example.com" value="#{@site.email}"
|
input class="input-Area" name="email" type="email" placeholder="youremail@example.com" value="#{@site.email}"
|
||||||
|
|
||||||
br
|
br
|
||||||
|
hr
|
||||||
|
|
||||||
p.tiny You can optionally enter some tags! Tags will allow others to find your site based on your interests, or your site's theme. <b>Separate multiple tags with commas</b>. Don't think too hard about this, you can change them later. You can have a maximum of ten tags, and there is a two word per tag maximum (extra words in a tag will be removed).
|
p.tiny You can optionally enter some tags! Tags will allow others to find your site based on your interests, or your site's theme. <b>Separate multiple tags with commas</b>. Don't think too hard about this, you can change them later. You can have a maximum of ten tags, and there is a two word per tag maximum (extra words in a tag will be removed).
|
||||||
|
|
||||||
hr
|
|
||||||
h5 Tags
|
h5 Tags
|
||||||
p: input class="input-Area" name="tags" type="text" style="width: 400px; max-width:100%" placeholder="pokemon, video games, bulbasaur" value="#{params[:tags]}" autocapitalize="off" autocorrect="off"
|
p: input class="input-Area" name="tags" type="text" style="width: 400px; max-width:100%" placeholder="pokemon, video games, bulbasaur" value="#{params[:tags]}" autocapitalize="off" autocorrect="off"
|
||||||
|
|
||||||
|
hr
|
||||||
input name="is_nsfw" type="hidden" value="false"
|
input name="is_nsfw" type="hidden" value="false"
|
||||||
p: strong If your page will contain objectionable (adult) content, check this box: <input name="is_nsfw" type="checkbox" value="true" style="margin-top:0">
|
p If your page will contain objectionable (adult) content, check this box: <input name="is_nsfw" type="checkbox" value="true" style="margin-top:0">
|
||||||
|
|
||||||
|
hr
|
||||||
p.tiny <b>Last thing!</b> Enter these two words correctly (with spaces) so we know you're not a robot (don't worry robots, we still love you).
|
p.tiny <b>Last thing!</b> Enter these two words correctly (with spaces) so we know you're not a robot (don't worry robots, we still love you).
|
||||||
div style="background:#fff; width:100%; overflow:auto"
|
div style="background:#fff; width:100%; overflow:auto"
|
||||||
== recaptcha_tag :challenge, ssl: true
|
== recaptcha_tag :challenge, ssl: true
|
||||||
|
|
Loading…
Add table
Reference in a new issue