Merge pull request #85 from Bushido/bushido

Bushido integration
This commit is contained in:
Didier Lafforgue 2011-05-31 15:06:09 -07:00
commit 372941ad89
28 changed files with 365 additions and 64 deletions

2
.gitignore vendored
View File

@ -30,3 +30,5 @@ config/deploy.rb
perf/*.rb
gem_graph.png
sites/
permanent
doc/bushido

13
Gemfile
View File

@ -27,7 +27,6 @@ gem 'fog', '0.3.7'
gem 'mimetype-fu'
gem 'actionmailer-with-request', :require => 'actionmailer_with_request'
gem 'heroku', '1.19.1'
gem 'bushido'
gem 'httparty', '>= 0.6.1'
gem 'RedCloth', '4.2.7'
gem 'delayed_job', '2.1.4'
@ -44,8 +43,16 @@ group :development do
end
group :test, :development do
gem "ruby-debug", :platforms => :mri_18
gem "ruby-debug19", :platforms => :mri_19
gem 'ruby-debug', :platforms => :mri_18
gem 'ruby-debug19', :platforms => :mri_19
gem 'bushido_stub', :git => 'git://github.com/did/bushido_stub.git'
# :path => '../gems/bushido_stub'
# gem 'bushido'
end
group :production do
gem 'bushido'
end
group :test do

View File

@ -1,6 +1,13 @@
GIT
remote: git://github.com/did/bushido_stub.git
revision: 6b83b2c4847832ffe7a213e725d2ceb7f864e360
specs:
bushido_stub (0.0.1)
activesupport (>= 3.0.7)
GIT
remote: git://github.com/floehopper/mocha.git
revision: adeb8ae0189963cf3024f2b37d5348a7feaae11e
revision: 6da1242f26b12a24c4fcf67bf5921a25bc1bc88d
specs:
mocha (0.9.12.20110213002255)
@ -58,7 +65,7 @@ GEM
bson (1.3.1)
bson_ext (1.3.1)
builder (2.1.2)
bushido (0.0.12)
bushido (0.0.14)
highline (>= 1.6.1)
json (>= 1.4.6)
rest-client (>= 1.6.1)
@ -74,7 +81,6 @@ GEM
celerity (0.8.9)
childprocess (0.1.9)
ffi (~> 1.0.6)
closure-compiler (1.1.1)
columnize (0.3.2)
configuration (1.2.0)
crack (0.1.8)
@ -141,9 +147,8 @@ GEM
inherited_resources (1.1.2)
has_scope (~> 0.5.0)
responders (~> 0.6.0)
jammit (0.6.0)
closure-compiler (>= 0.1.0)
yui-compressor (>= 0.9.1)
jammit (0.6.3)
yui-compressor (>= 0.9.3)
json (1.5.1)
json_pure (1.4.6)
kgio (2.4.1)
@ -244,7 +249,7 @@ GEM
ffi (>= 1.0.7)
json_pure
rubyzip
spork (0.8.4)
spork (0.8.5)
term-ansicolor (1.0.5)
thor (0.14.6)
treetop (1.4.9)
@ -271,6 +276,7 @@ DEPENDENCIES
autotest
bson_ext (~> 1.3.0)
bushido
bushido_stub!
capybara
cucumber (= 0.8.5)
cucumber-rails

View File

@ -5,7 +5,7 @@ module Admin
layout '/admin/layouts/application'
before_filter :authenticate_admin!
before_filter :require_admin
before_filter :require_site
@ -28,6 +28,10 @@ module Admin
protected
def require_admin
authenticate_admin!
end
def begin_of_association_chain
current_site
end

View File

@ -7,7 +7,7 @@ module Admin
skip_before_filter :validate_site_membership
before_filter :authenticate_admin!, :only => :new
before_filter :require_admin, :only => :new
def new
if site = current_admin.sites.detect { |s| s._id.to_s == params[:target_id] }

View File

@ -5,7 +5,7 @@ module Admin
skip_before_filter :require_site
skip_before_filter :authenticate_admin!
skip_before_filter :require_admin
skip_before_filter :verify_authenticity_token
@ -42,13 +42,7 @@ module Admin
@site = Site.create_first_one(params[:site])
if @site.valid?
begin
unless params[:zipfile].blank?
Locomotive::Import::Job.run!(params[:zipfile], @site, { :samples => true })
end
rescue Exception => e
logger.error "Import failed because of #{e.message}"
end
Site.install_template(@site, params)
redirect_to last_url
else
@ -61,8 +55,8 @@ module Admin
def is_step_already_done?
case params[:step].to_i
when 1 # already an account in db
if Account.count > 0
@step_done = t('admin.installation.step_1.done', Account.first.attributes)
if account = Account.first
@step_done = I18n.t('admin.installation.step_1.done', :name => account.name, :email => account.email)
render 'step_1' and return false
end
else

View File

@ -1,7 +1,7 @@
module Admin
class SitemapsController < BaseController
skip_before_filter :authenticate_admin!, :validate_site_membership, :set_locale
skip_before_filter :require_admin, :validate_site_membership, :set_locale
before_filter :require_site

View File

@ -13,6 +13,24 @@ module Extensions
site
end
def install_template(site, options = {})
default_template = Boolean.set(options.delete(:default_site_template)) || false
zipfile = options.delete(:zipfile)
# do not try to process anything if said so
return unless default_template || zipfile.present?
# default template options has a higher priority than the zipfile
source = default_template ? Locomotive.default_site_template_path : zipfile
begin
Locomotive::Import::Job.run!(source, site, { :samples => true })
rescue Exception => e
logger.error "The import of the site template failed because of #{e.message}"
end
end
end
end
end

View File

@ -5,6 +5,7 @@
- content_for :head do
= include_stylesheets :installation
= include_javascripts :installation
= semantic_form_for(@site, :url => admin_installation_step_url(2), :html => { :multipart => true }) do |f|
.inner
@ -18,9 +19,16 @@
- if multi_sites?
= f.input :subdomain, :required => true
%li{ :class => 'string optional', :id => 'zipfile_input' }
- if Locomotive.default_site_template_present?
%li{ :class => 'question', :id => 'default_site_template_input' }
= check_box_tag 'default_site_template', '1', params[:default_site_template].blank? || params[:default_site_template] == '1'
%label{ :for => 'default_site_template' }!= t('formtastic.labels.import.new.default_site_template')
%li{ :class => 'string optional', :id => 'zipfile_input', :style => "#{'display: none' if Locomotive.default_site_template_present?}" }
%label{ :for => 'zipfile' }= t('formtastic.labels.import.new.source')
= file_field_tag 'zipfile'
- if Locomotive.default_site_template_present?
%p.inline-hints!= t('.back_to_default_template')
.footer
= box_button_tag t('.next')

View File

@ -7,6 +7,9 @@ s3_secret_access_key: <%= ENV['S3_SECRET_KEY'] %>
javascripts:
box:
- public/javascripts/admin/jquery.js
installation:
- public/javascripts/admin/jquery.js
- public/javascripts/admin/installation.js
common:
- public/javascripts/admin/jquery.js
- public/javascripts/admin/jquery.ui.js

View File

@ -3,5 +3,6 @@
"platform_version": 3,
"ruby_version": "1.9.2",
"sql": false,
"mongodb": true
"mongodb": true,
"start_page": "admin/pages"
}

View File

@ -27,4 +27,14 @@ Locomotive::Application.configure do
:port => 1025,
:domain => "example.com"
}
# set up the bushido stub (uncomment it)
# config.bushido_stub_env = false
# config.bushido_stub_env = {
# 'APP_TLD' => 'bushi.do',
# 'BUSHIDO_APP' => 'san_francisco',
# 'BUSHIDO_HOST' => 'bushi.do',
# 'LOCOMOTIVE_SITE_NAME' => 'Locomotive TEST',
# 'BUSHIDO_CLAIMED' => 'true'
# }
end

View File

@ -259,8 +259,8 @@ en:
imports:
new:
title: Import
help: "Be careful when you upload a new theme for your existing website, your current data could be modified or even removed."
title: Import site template
help: "Be careful when you upload a new template for your existing website, your current data could be modified or even removed."
show:
title: Import in progress
help: "Your site is being updated from the theme zip file you have just uploaded. It lasts a couple of seconds."
@ -289,5 +289,6 @@ en:
next: Create account
step_2:
title: "Step 2/2 &mdash; Create your first site"
explanations: "This is the last step of the installation. You can upload a theme as a zip file. We have free available themes <a href=\"http://www.locomotivecms.com/support/themes\">here</a>."
explanations: "If you already uploaded the default site template (see instructions), you can use it right away. Or you can upload a site template as a zip file (free available templates <a href=\"http://www.locomotivecms.com/support/themes\">here</a>)."
back_to_default_template: "Click <a href='#'>here</a> to select the default site template instead"
next: Create site

View File

@ -258,8 +258,8 @@ fr:
imports:
new:
title: Import
help: "Faites attention quand vous envoyez un nouveau theme sur votre site, les données de celui-ci pourront être modifiées voire même supprimées."
title: Importer template de site
help: "Faites attention quand vous envoyez un nouveau template sur votre site, les données de celui-ci pourront être modifiées voire même supprimées."
show:
title: Import en cours
help: "Votre site est en train d'être mis à jour à partir du fichier zip précédemment envoyé sur le serveur. Cette opération peut durer quelques secondes."
@ -288,5 +288,6 @@ fr:
next: Créer compte
step_2:
title: "Étape 2/2 &mdash; Créer votre premier site"
explanations: "C'est la dernière étape de l'installation. Vous pouvez uploader un theme sous forme d'un fichier zip. Nous avons quelques themes disponibles <a href=\"http://www.locomotivecms.com/support/themes\">ici</a>."
explanations: "Si vous avez déjà uploadé le template de site par défaut (voir instructions), vous pouvez l'utiliser dès maintenant. Ou vous pouvez uploader un template de site sous forme d'un fichier zip (quelques themes disponibles <a href=\"http://www.locomotivecms.com/support/themes\">ici</a>)."
back_to_default_template: "Cliquez <a href='#'>ici</a> pour sélectionner à la place le template de site par défault"
next: Créer site

View File

@ -36,6 +36,7 @@ en:
source: File
samples: Copy samples
reset: Reset site
default_site_template: "Use the default site template. Click <a href='#'>here</a> to upload a site template as a zip file instead."
content_type:
api_accounts: Notified Accounts
account:

View File

@ -14,7 +14,7 @@ it:
membership_email: Email account
file: File
preview: Anteprima
options: Opzioni
options: Opzioni avanzate
custom_fields: Campi personalizzati
other_fields: Altre informazioni
presentation: Presentazione

View File

@ -1,28 +1,25 @@
BOARD:
x bugs:
x #50
x #51
~ editable_elements: inheritable: false (Mattias) => seems to be fixed by Dirk's last pull request (#44) => content tag
- bushido version
- upgrade warning if new version of locomotive (maybe based on the commit id)
- duostack version
x 2 different sites on the same main domain (one in www, the other one in something else) (Raphael Costa)
- seo section for the page form: seo title, seo keywords, seo description
- icon for redirection page in the pages section (back-office)
- write my first tutorial about locomotive
- default template
BACKLOG:
- custom_fields:
- validation: regexp (pre-defined regexps ?)
- new type: belongs_to => association
x new type: belongs_to => association
- inline editing (http://www.aloha-editor.com/wiki/index.php/Aloha_PHP_Example)
- html view in the aloha popup
- editable elements should wrap a tag: div, h1, ...etc (default span)
- edit images (upload new ones, ...etc) => wait for aloha or send them an email ?
- global regions: keyword in editable element (http://www.mongodb.org/display/DOCS/Updating)
- cucumber features for admin pages (in progress)
(- duostack/doutcloud version)
- icon for redirection page in the pages section (back-office)
- write my first tutorial about locomotive
- upgrade warning if new version of locomotive (maybe based on the commit id)
REFACTORING:
@ -212,3 +209,6 @@ x pull request #44
x bug on dates (https://github.com/locomotivecms/engine/issues#issue/48)
x generated sitemaps are invalid (url + date)
x integrate new locomotivecms home
x seo section for the page form: seo title, seo keywords, seo description
x bugs: #50, #51
x 2 different sites on the same main domain (one in www, the other one in something else) (Raphael Costa)

View File

@ -8,7 +8,6 @@ require 'locomotive/logger'
require 'locomotive/liquid'
require 'locomotive/mongoid'
require 'locomotive/carrierwave'
require 'locomotive/hosting'
require 'locomotive/custom_fields'
require 'locomotive/httparty'
require 'locomotive/inherited_resources'
@ -20,6 +19,7 @@ require 'locomotive/import'
require 'locomotive/delayed_job'
require 'locomotive/middlewares'
require 'locomotive/session_store'
require 'locomotive/hosting'
module Locomotive
@ -39,6 +39,14 @@ module Locomotive
self.const_defined?('Engine')
end
def self.default_site_template_present?
File.exists?(self.default_site_template_path)
end
def self.default_site_template_path
File.join(Rails.root, 'tmp/default_site_template.zip')
end
def self.configure
self.config ||= Configuration.new
@ -58,7 +66,7 @@ module Locomotive
# Devise
mail_address = self.config.mailer_sender
Devise.mailer_sender = mail_address =~ /.+@.+/ ? mail_address : "#{mail_address}@#{Locomotive.config.domain}"
::Devise.mailer_sender = mail_address =~ /.+@.+/ ? mail_address : "#{mail_address}@#{Locomotive.config.domain}"
# cookies stored in mongodb (mongoid_store)
Rails.application.config.session_store :mongoid_store, {
@ -96,7 +104,7 @@ module Locomotive
if self.config.multi_sites?
self.config.manage_subdomain = self.config.manage_domains = true
else
# Note: (Did) modify the code below if Locomotive handles a new hosting solution
# Note: (Did) modify the code below if Locomotive handles a new hosting solution (not a perfect solution though)
self.config.manage_domains = self.heroku? || self.bushido?
self.config.manage_subdomain = self.bushido?
end

View File

@ -1,6 +1,9 @@
require 'bushido'
require 'locomotive/hosting/bushido/custom_domain'
require 'locomotive/hosting/bushido/first_installation'
require 'locomotive/hosting/bushido/account_ext'
require 'locomotive/hosting/bushido/middleware'
require 'locomotive/hosting/bushido/devise'
module Locomotive
module Hosting
@ -22,22 +25,35 @@ module Locomotive
(self.config.hosting == :auto && ENV['APP_TLD'] == 'bushi.do')
end
def bushido_app_claimed?
ENV['BUSHIDO_CLAIMED'].present? && ENV['BUSHIDO_CLAIMED'].to_s.downcase == 'true'
end
def enable_bushido
self.config.domain = ENV['APP_TLD'] unless self.config.multi_sites?
self.enhance_site_model_with_bushido
self.enhance_models_with_bushido
self.disable_authentication_for_not_claimed_app
self.setup_smtp_settings
self.config.delayed_job = true # force the use of delayed_job
self.add_middleware
self.config.delayed_job = true # force to use delayed_job
self.bushido_domains = ::Bushido::App.domains
self.bushido_subdomain = ::Bushido::App.subdomain
end
def enhance_site_model_with_bushido
def enhance_models_with_bushido
Site.send :include, Locomotive::Hosting::Bushido::CustomDomain
Site.send :include, Locomotive::Hosting::Bushido::FirstInstallation
Account.send :include, Locomotive::Hosting::Bushido::AccountExt
end
def disable_authentication_for_not_claimed_app
Admin::BaseController.send :include, Locomotive::Hosting::Bushido::Devise
end
def setup_smtp_settings
@ -53,6 +69,12 @@ module Locomotive
}
end
def add_middleware
::Locomotive::Application.configure do |config|
config.middleware.use '::Locomotive::Hosting::Bushido::Middleware'
end
end
# manage domains
def add_bushido_domain(name)

View File

@ -0,0 +1,19 @@
module Locomotive
module Hosting
module Bushido
module AccountExt
extend ActiveSupport::Concern
included do
field :bushido_user_id, :type => Integer
end
end
end
end
end

View File

@ -0,0 +1,28 @@
module Locomotive
module Hosting
module Bushido
module Devise
extend ActiveSupport::Concern
included do
alias_method_chain :require_admin, :bushido
end
module InstanceMethods
def require_admin_with_bushido
if ::Locomotive.bushido_app_claimed?
require_admin_without_bushido
else
# open back-office for everybody as long as the application is not claimed
sign_in(Account.order_by(:created_at).first)
end
end
end
end
end
end
end

View File

@ -0,0 +1,48 @@
require 'rack/utils'
module Locomotive
module Hosting
module Bushido
class Middleware
# BUSHIDO_JS_URL = 'http://localhost:4567/javascripts/bushido.js'
BUSHIDO_JS_URL = 'http://bushi.do/api/bushido.js'
include Rack::Utils
def initialize(app, opts = {})
@app = app
@bushido_app_name = ENV['BUSHIDO_APP']
@bushido_claimed = ::Locomotive.bushido_app_claimed?
end
def call(env)
status, headers, response = @app.call(env)
content = ""
response.each { |part| content += part }
# "claiming" bar + stats ?
content.gsub!(/<\/body>/i, <<-STR
<script type="text/javascript">
var _bushido_app = '#{@bushido_app_name}';
var _bushido_claimed = #{@bushido_claimed.to_s};
(function() {
var bushido = document.createElement('script'); bushido.type = 'text/javascript'; bushido.async = true;
bushido.src = '#{BUSHIDO_JS_URL}';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(bushido, s);
})();
</script>
</body>
STR
)
headers['content-length'] = bytesize(content).to_s
[status, headers, [content]]
end
end
end
end
end

View File

@ -7,3 +7,9 @@ require 'locomotive/import/asset_collections'
require 'locomotive/import/content_types'
require 'locomotive/import/snippets'
require 'locomotive/import/pages'
module Locomotive
module Import
DEFAULT_SITE_TEMPLATE = 'https://github.com/locomotivecms/default-site-template/zipball/master'
end
end

View File

@ -70,6 +70,7 @@ module Locomotive
job = self.new(zipfile, site, options)
if Locomotive.config.delayed_job
puts "delayed::JOB !"
Delayed::Job.enqueue job, { :site => site, :job_type => 'import' }
else
job.perform

View File

@ -1,14 +1,86 @@
require 'bushido'
require 'jammit'
require 'net/http'
namespace :bushido do
desc "Prepare an app to run on the Bushido hosting platform, only called during the initial installation. Called just before booting the app."
task :install do
task :install => :environment do
# re-built assets
Jammit.package!
if ENV['BUSHIDO_USER_EMAIL'] && ENV['BUSHIDO_USER_ID']
# already logged in in Bushido
account = Account.create!({
:email => ENV['BUSHIDO_USER_EMAIL'],
:name => ENV['BUSHIDO_USER_NAME'] || ENV['BUSHIDO_USER_EMAIL'].split('@').first,
:bushido_user_id => ENV['BUSHIDO_USER_ID'],
:password => ActiveSupport::SecureRandom.base64(6)
})
else
# create an anonymous account right away
account = Account.create!({
:email => "#{ENV['BUSHIDO_APP']}@#{ENV['BUSHIDO_HOST']}",
:name => ENV['BUSHIDO_APP'],
:password => ActiveSupport::SecureRandom.base64(6)
})
end
# create the site
site = Site.create_first_one(:name => ENV['LOCOMOTIVE_SITE_NAME'] || ENV['BUSHIDO_APP'])
# fetch the site template
template_url = ENV['SITE_TEMPLATE_URL'] || Locomotive::Import::DEFAULT_SITE_TEMPLATE
template_url = "http://#{template_url}" unless template_url =~ /^https?:\/\//
template_local_path = "#{Rails.root}/permanent/site_template.zip"
uri = URI.parse(template_url)
http = Net::HTTP.new(uri.host, uri.port)
if template_url.starts_with?('https') # ssl request ?
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
case http.request(Net::HTTP::Get.new(uri.request_uri))
when Net::HTTPSuccess, Net::HTTPFound
`curl -L -s -o #{template_local_path} #{template_url}`
tmp, Locomotive.config.delayed_job = Locomotive.config.delayed_job, false # disable DJ during this import
Locomotive::Import::Job.run!(File.open(template_local_path), site, { :samples => true })
Locomotive.config.delayed_job = tmp # restore DJ flag
else
# do nothing
end
end
desc "Perform custom actions triggered by the Bushido hosting platform."
task :event => :environment do
event = ::Bushido::Event.last
puts "processing...#{event.inspect}"
case event.category.to_s
when 'app'
case event.name.to_s
when 'claimed'
# an user has just claimed his application
account = Account.order_by(:created_at).first
account.email = event.data['bushido_user_email']
account.bushido_user_id = event.data['bushido_user_id']
account.save!
end
end
end
desc "Prepare an app to run on the Bushido hosting platform, called on every update. Called just before booting the app."
task :update do
# re-built assets
Jammit.package!
end
end

12
lib/tasks/locomotive.rake Normal file
View File

@ -0,0 +1,12 @@
namespace :locomotive do
desc 'Fetch the Locomotive default site template for the installation'
task :fetch_default_site_template => :environment do
puts "Downloading default site template from '#{Locomotive::Import.DEFAULT_SITE_TEMPLATE}'"
`curl -L -s -o #{Rails.root}/tmp/default_site_template.zip #{Locomotive::Import.DEFAULT_SITE_TEMPLATE}`
puts '...done'
end
end

View File

@ -0,0 +1,17 @@
$(document).ready(function() {
$('#default_site_template_input label a').click(function(e) {
$('#default_site_template_input input[type=checkbox]').attr('checked', '');
$('#default_site_template_input').hide();
$('#zipfile_input').show();
e.preventDefault();
});
$('#zipfile_input p.inline-hints a').click(function(e) {
$('#default_site_template_input input[type=checkbox]').attr('checked', 'checked');
$('#zipfile_input').hide();
$('#default_site_template_input').show();
e.preventDefault();
});
});

View File

@ -4,20 +4,20 @@
color: #222;
}
#panel .inner p.explanations {
margin-top: 10px;
font-size: 1.2em;
}
#panel .inner p.explanations a {
#panel .inner a {
color: #1F82BC;
text-decoration: none;
}
#panel .inner p.explanations a:hover {
#panel .inner a:hover {
text-decoration: underline;
}
#panel .inner p.explanations {
margin-top: 10px;
font-size: 1.2em;
}
#panel .inner p.done {
margin: 20px 0px 15px;
font-size: 1.2em;
@ -45,6 +45,18 @@
}
#panel .inner dd p {
}
/* ___ custom ___ */
#panel fieldset ol li.question input[type=checkbox] {
display: inline;
width: auto;
margin-right: 10px;
}
#panel fieldset ol li.question label {
display: inline;
font-weight: normal;
}