Initial checkin of project. Creates sites and goes to dashboard

This commit is contained in:
Kyle Drake 2013-05-24 00:47:50 -07:00
parent d1d1d61f18
commit b2bdf32275
26 changed files with 540 additions and 0 deletions

2
.gitignore vendored
View file

@ -16,3 +16,5 @@ tmp
.yardoc .yardoc
_yardoc _yardoc
doc/ doc/
tests/coverage
config.yml

38
Gemfile Normal file
View file

@ -0,0 +1,38 @@
source 'https://rubygems.org'
gem 'sinatra'
gem 'redis'
gem 'sequel'
gem 'slim'
gem 'bcrypt-ruby', require: 'bcrypt'
gem 'sinatra-flash', require: 'sinatra/flash'
gem 'puma', require: nil
platform :mri do
gem 'pg'
gem 'hiredis'
group :development, :test do
gem 'pry'
gem 'pry-debugger'
end
end
group :development do
gem 'shotgun', require: nil
end
group :test do
gem 'faker'
gem 'fabrication', require: 'fabrication'
gem 'minitest'
gem 'minitest-reporters', require: 'minitest/reporters'
gem 'rack-test', require: 'rack/test'
gem 'webmock'
gem 'mocha', require: nil
gem 'rake', require: nil
platform :mri do
gem 'simplecov', require: nil
end
end

101
Gemfile.lock Normal file
View file

@ -0,0 +1,101 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.3.4)
ansi (1.4.3)
bcrypt-ruby (3.0.1)
builder (3.2.0)
coderay (1.0.9)
columnize (0.3.6)
crack (0.3.2)
debugger (1.6.0)
columnize (>= 0.3.1)
debugger-linecache (~> 1.2.0)
debugger-ruby_core_source (~> 1.2.1)
debugger-linecache (1.2.0)
debugger-ruby_core_source (1.2.2)
fabrication (2.7.1)
faker (1.1.2)
i18n (~> 0.5)
hashie (2.0.5)
hiredis (0.4.5)
i18n (0.6.4)
metaclass (0.0.1)
method_source (0.8.1)
minitest (4.7.4)
minitest-reporters (0.14.19)
ansi
builder
minitest (>= 2.12, < 5.0)
powerbar
mocha (0.14.0)
metaclass (~> 0.0.1)
multi_json (1.7.3)
pg (0.15.1)
powerbar (1.0.11)
ansi (~> 1.4.0)
hashie (>= 1.1.0)
pry (0.9.12.2)
coderay (~> 1.0.5)
method_source (~> 0.8)
slop (~> 3.4)
pry-debugger (0.2.2)
debugger (~> 1.3)
pry (~> 0.9.10)
puma (2.0.1)
rack (>= 1.1, < 2.0)
rack (1.5.2)
rack-protection (1.5.0)
rack
rack-test (0.6.2)
rack (>= 1.0)
rake (10.0.4)
redis (3.0.4)
sequel (3.47.0)
shotgun (0.9)
rack (>= 1.0)
simplecov (0.7.1)
multi_json (~> 1.0)
simplecov-html (~> 0.7.1)
simplecov-html (0.7.1)
sinatra (1.4.2)
rack (~> 1.5, >= 1.5.2)
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
sinatra-flash (0.3.0)
sinatra (>= 1.0.0)
slim (1.3.9)
temple (~> 0.6.3)
tilt (~> 1.3, >= 1.3.3)
slop (3.4.5)
temple (0.6.5)
tilt (1.4.1)
webmock (1.11.0)
addressable (>= 2.2.7)
crack (>= 0.3.2)
PLATFORMS
ruby
DEPENDENCIES
bcrypt-ruby
fabrication
faker
hiredis
minitest
minitest-reporters
mocha
pg
pry
pry-debugger
puma
rack-test
rake
redis
sequel
shotgun
simplecov
sinatra
sinatra-flash
slim
webmock

10
Rakefile Normal file
View file

@ -0,0 +1,10 @@
require "rake/testtask"
desc "Run all tests"
Rake::TestTask.new do |t|
t.libs << "spec"
t.test_files = FileList['tests/*_test.rb']
t.verbose = true
end
task :default => :test

63
app.rb Normal file
View file

@ -0,0 +1,63 @@
require './environment.rb'
get '/' do
slim :index
end
get '/new' do
@site = Site.new
slim :'new'
end
get '/dashboard' do
slim :'dashboard'
end
post '/create' do
@site = Site.new username: params[:username], password: params[:password], email: params[:email]
if @site.valid?
@server = Server.with_slots_available
if @server.nil?
raise 'no slots available'
end
@site.server = @server
@site.save
session[:username] = @site.username
redirect '/dashboard'
else
slim :'/new'
end
end
post '/signin' do
if Site.valid_login? params[:username], params[:password]
session[:username] = params[:username]
redirect '/dashboard'
else
flash[:error] = 'Invalid login.'
redirect '/'
end
end
get '/signout' do
require_login
session[:username] = nil
session[:timezone] = nil
redirect '/'
end
def dashboard_if_signed_in
redirect '/dashboard' if signed_in?
end
def require_login
redirect '/' unless signed_in?
end
def signed_in?
!session[:username].nil?
end

3
config.ru Normal file
View file

@ -0,0 +1,3 @@
require './app.rb'
map('/') { run Sinatra::Application }

2
config.yml.template Normal file
View file

@ -0,0 +1,2 @@
development:
database: 'postgres://localhost/neocities'

38
environment.rb Normal file
View file

@ -0,0 +1,38 @@
ENV['RACK_ENV'] ||= 'development'
ENV['TZ'] = 'UTC'
DIR_ROOT = File.expand_path File.dirname(__FILE__)
Encoding.default_internal = 'UTF-8'
require 'yaml'
require 'json'
require 'logger'
Bundler.require
Bundler.require :development if ENV['RACK_ENV'] == 'development'
$config = YAML.load_file(File.join(DIR_ROOT, 'config.yml'))[ENV['RACK_ENV']]
DB = Sequel.connect $config['database']
Dir.glob('workers/*.rb').each {|w| require File.join(DIR_ROOT, "/#{w}") }
if defined?(Pry)
Pry.commands.alias_command 'c', 'continue'
Pry.commands.alias_command 's', 'step'
Pry.commands.alias_command 'n', 'next'
Pry.commands.alias_command 'f', 'finish'
end
Sequel.datetime_class = Time
Sequel.extension :pagination
Sequel.extension :migration
Sequel::Model.plugin :validation_helpers
Sequel::Model.plugin :force_encoding, 'UTF-8'
Sequel::Model.plugin :timestamps, create: :created_at, update: :updated_at
Sequel::Model.plugin :defaults_setter
Sequel.default_timezone = 'UTC'
Sequel::Migrator.apply DB, './migrations'
Dir.glob('models/*.rb').each {|m| require File.join(DIR_ROOT, "#{m}") }
DB.loggers << Logger.new(STDOUT) if ENV['RACK_ENV'] == 'development'

View file

@ -0,0 +1,16 @@
Sequel.migration do
up {
DB.create_table! :sites do
String :username, primary_key: true
String :email
String :password
Integer :server_id
DateTime :created_at
DateTime :updated_at
end
}
down {
DB.drop_table :sites
}
end

View file

@ -0,0 +1,15 @@
Sequel.migration do
up {
DB.create_table! :servers do
primary_key :id
String :ip
Integer :slots_available
DateTime :created_at
DateTime :updated_at
end
}
down {
DB.drop_table :servers
}
end

7
models/server.rb Normal file
View file

@ -0,0 +1,7 @@
class Server < Sequel::Model
one_to_many :sites
def self.with_slots_available
where{slots_available > 0}.first
end
end

50
models/site.rb Normal file
View file

@ -0,0 +1,50 @@
class Site < Sequel::Model
MINIMUM_PASSWORD_LENGTH = 5
unrestrict_primary_key
many_to_one :server
class << self
def valid_login?(username, plaintext)
site = self[username: username]
return false if site.nil?
site.valid_password? plaintext
end
def bcrypt_cost
@bcrypt_cost
end
def bcrypt_cost=(cost)
@bcrypt_cost = cost
end
end
def valid_password?(plaintext)
BCrypt::Password.new(values[:password]) == plaintext
end
def password=(plaintext)
@password_length = plaintext.nil? ? 0 : plaintext.length
@password_plaintext = plaintext
values[:password] = BCrypt::Password.create plaintext, cost: (self.class.bcrypt_cost || BCrypt::Engine::DEFAULT_COST)
end
def validate
super
if values[:username].nil? || values[:username].empty?
errors.add :username, 'valid username is required'
end
# Check for existing user
user = self.class.select(:username).filter(username: values[:username]).first
if !user.nil? && (user.id != values[:id])
errors.add :username, 'this username is already taken'
end
if values[:password].nil? || (@password_length && @password_length < MINIMUM_PASSWORD_LENGTH)
errors.add :password, "password must be at least #{MINIMUM_PASSWORD_LENGTH} characters"
end
end
end

File diff suppressed because one or more lines are too long

9
public/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

33
public/css/font-awesome.min.css vendored Normal file

File diff suppressed because one or more lines are too long

0
public/css/styles.css Normal file
View file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

6
public/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

5
public/js/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

0
tests/app_test.rb Normal file
View file

34
tests/environment.rb Normal file
View file

@ -0,0 +1,34 @@
ENV['RACK_ENV'] = 'test'
raise 'Forget it.' if ENV['RACK_ENV'] == 'production'
require 'simplecov'
SimpleCov.coverage_dir File.join('tests', 'coverage')
SimpleCov.start do
add_filter "/migrations/"
end
require './environment'
require 'webmock'
include WebMock::API
require './app'
Bundler.require :test
#require 'minitest/pride'
require 'minitest/autorun'
require 'sidekiq/testing/inline'
Account.bcrypt_cost = BCrypt::Engine::MIN_COST
MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
# Bootstrap the database
Sequel.extension :migration
Sequel::Migrator.apply DB, './migrations', 0
Sequel::Migrator.apply DB, './migrations'
Fabrication.configure do |config|
config.fabricator_path = 'tests/fabricators'
config.path_prefix = DIR_ROOT
end

4
views/dashboard.slim Normal file
View file

@ -0,0 +1,4 @@
.row
.span12
h1 Dashboard!

29
views/index.slim Normal file
View file

@ -0,0 +1,29 @@
.row
.span12
h1 Your free home page is waiting.. once again.
h2 NeoCities allows you to create your own free home page!
div style="margin-top: 30px"
table.table.table-bordered
tbody
tr
td: b What kind of look and feel can my home page have?
td Anything you want! It's just HTML. It's your home page, your vision. You can make it as straight or crazy as you want. You're the artist, you're in control. Make a web site about you, or make it about cats that play Dungeons and Dragons, or make a Daft Punk Fan Site, or a Daft Punk Sucks Site.
tr
td: b What information can I put on it?
td Anything you wan't, as long as it's not illegal to host it in the United States. We don't care if it offends somebody, or you remain anonymous.
tr
td: b Do I own my content?
td Yes, you do. It's yours. We're just giving you a place to host it.
tr
td: b How much space do I get?
td 5 Megabytes. You can have HTML, text, and images. That's it.
tr
td: b How are you paying for this?
td Hopefully with donations. If you feel this is a useful service, help us pay the bills to run it. <a href="/donate">Click here to contribute!</a>
div.text-center
h1: a href="/new" JOIN NOW

28
views/layout.slim Normal file
View file

@ -0,0 +1,28 @@
doctype html
html
head
title NeoCities #{@title.nil? ? '' : " - #{@title}"}
link href="/favicon.ico" rel="icon" type="image/x-icon"
link href="/css/bootstrap.min.css" rel="stylesheet"
link href="/css/bootstrap-responsive.min.css" rel="stylesheet"
link href="/css/font-awesome.min.css" rel="stylesheet"
link href="/css/styles.css" rel="stylesheet"
script src="/js/jquery.min.js"
body
a id="top"
.container
.row
.span12
.navbar
.navbar-inner
a.brand href="/" NeoCities
- flash.keys.each do |key|
div class="alert alert-#{key}"
button.close type="button" data-dismiss="alert" &times;
= flash[key]
container
== yield
script src="/js/bootstrap.min.js"

38
views/new.slim Normal file
View file

@ -0,0 +1,38 @@
.row
.span8.offset3
form method="POST" action="/create"
h2 Create a new Home Page
.row
.span6
p First, enter a username. This will be used to login to your site.
.row
.span1
h5 Username
.span6
input name="username" type="text" style="color: #000000" placeholder="bulbasaur1000"
.row
.span6
p Next, enter a password. This will be used to allow you to login. Minimum 5 characters.
.row
.span1
h5 Password
.span6
input name="password" type="password" style="color: #000000"
.row
.span6
p Now, you can enter an e-mail address if you want to be able to reset your password incase you lose it. This is optional, but recommended. <b>We will not give your email to anybody</b>.
.row
.span1
h5 Email
.span6
input name="email" type="text" style="color: #000000" placeholder="youremail@example.com"
.row style="margin-top: 30px"
.span3.offset1
input.btn.btn-success.btn-large type="submit" value="Create Home Page"