Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: ac8e68c57f
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 213 lines (196 sloc) 6.102 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
require 'sinatra'
require 'haml'
require 'sass'
require 'compass'
require 'dropbox'
require 'sequel'
require 'rack-flash'
require 'rack/csrf'
require 'uri'
require 'rdiscount'
require 'redcloth'
require 'org-ruby'

configure do
  enable :sessions
  use Rack::Flash
  use Rack::Csrf, :raise => true
  Compass.configuration do |config|
    config.project_path = File.dirname(__FILE__)
    config.sass_dir = 'views'
  end
  set :public, File.dirname(__FILE__) + '/static'
  set :haml, :format => :html5
  set :sass, Compass.sass_engine_options
end

DB = Sequel.connect(ENV['DATABASE_URL'] || 'sqlite://test.db')

class User < Sequel::Model
  plugin :validation_helpers
  def validate
    super
    validates_presence [:email]
  end
end

def wikify(page)
  if page[:text].kind_of? String then
    case page[:name].split('.').last
    when 'md', 'mkd', 'mdown', 'markdown'
      text = markdown(page[:text])
    when 'textile'
      text = textile(page[:text])
    when 'org'
      text = Orgmode::Parser.new(page[:text]).to_html
    else
      text = page[:text]
    end
    text.gsub /\[\[([\s\w.]+)\]\]/ do "<a href='/pages/#{$1}'>#{$1}</a>" end
  else "This page doesn't exist yet." end
end

get '/' do
  if session[:db_session] then
    redirect '/pages'
  else
    haml :landing
  end
end

get '/auth' do
  if params[:oauth_token] then
    db_session = Dropbox::Session.deserialize(session[:db_session])
    db_session.authorize(params)
    session[:db_session] = db_session.serialize
    if not User[:email => db_session.account.email]
      user = User.new
      user[:email] = db_session.account.email
      user.save
      flash[:info] = 'Welcome to Wikibox! Please choose a folder for your wiki.'
      redirect '/settings'
    else
      flash[:info] = 'Welcome back!'
      redirect '/pages'
    end
  else
    db_session = Dropbox::Session.new(ENV['DROPBOX_KEY'], ENV['DROPBOX_SECRET'])
    session[:db_session] = db_session.serialize
    redirect db_session.authorize_url(:oauth_callback => request.url)
  end
end

get '/logout' do
  session[:db_session] = nil
  flash[:info] = 'Good bye!'
  redirect '/'
end

get '/settings' do
  return redirect '/auth' unless session[:db_session]
  db_session = Dropbox::Session.deserialize(session[:db_session])
  return redirect '/auth' unless db_session.authorized?
  @user = User[:email => db_session.account.email]
  haml :settings
end

post '/settings' do
  return redirect '/auth' unless session[:db_session]
  db_session = Dropbox::Session.deserialize(session[:db_session])
  return redirect '/auth' unless db_session.authorized?
  @user = User[:email => db_session.account.email]
  valid_re = /\A[0-9A-Za-z]+\z/
  if params[:folder] =~ valid_re
    @user[:folder] = params[:folder]
    @user[:indexfile] = params[:indexfile]
    @user.save
    flash[:info] = 'Yay, settings are saved.'
    redirect '/pages'
  else
    flash[:error] = 'Invalid folder name!'
    haml :settings
  end
end

get '/pages' do
  return redirect '/auth' unless session[:db_session]
  db_session = Dropbox::Session.deserialize(session[:db_session])
  return redirect '/auth' unless db_session.authorized?
  user = User[:email => db_session.account.email]
  if not user.indexfile then user.indexfile = 'index.md' end
  redirect "/pages/#{user.indexfile}"
end

get '/pages/:page' do |page|
  return redirect '/auth' unless session[:db_session]
  db_session = Dropbox::Session.deserialize(session[:db_session])
  return redirect '/auth' unless db_session.authorized?
  @user = User[:email => db_session.account.email]
  if not @user.folder then
    flash[:info] = 'Please specify a folder for your wiki.'
    redirect '/settings'
  end
  db_session.mode=(:dropbox)
  root = db_session.list("/")
  root.each do |entry|
    if entry.directory? and entry.path == "/" + @user.folder then folder = entry end
  end
  if not folder then
    begin
      db_session.create_folder(@user.folder)
    rescue Dropbox::UnsuccessfulResponseError # extra safety
      flash[:info] = 'Please specify a folder for your wiki.'
      redirect '/settings'
    end
  end
  pages = db_session.list(@user.folder)
  @pages = []
  pages.each do |entry|
    if entry.path == "/#{@user.folder}/#{page}" then reqpage = entry end
    @pages.push(entry.path.gsub("/#{@user.folder}/", ""))
  end
  @cur_page = {:name => page}
  if reqpage then
    @cur_page[:text] = db_session.download("/#{@user.folder}/#{page}")
  end
  haml :pages
end

post '/pages/:page' do |page|
  return redirect '/auth' unless session[:db_session]
  db_session = Dropbox::Session.deserialize(session[:db_session])
  return redirect '/auth' unless db_session.authorized?
  user = User[:email => db_session.account.email]
  if not user.folder then
    flash[:info] = 'Please specify a folder for your wiki.'
    redirect '/settings'
  end
  db_session.mode=(:dropbox)
  root = db_session.list("/")
  root.each do |entry|
    if entry.directory? and entry.path == "/" + user.folder then folder = entry end
  end
  if not folder then db_session.create_folder(user.folder) end
  db_session.upload(StringIO.new(params[:text]), "/#{user.folder}", {:as => page})
  flash[:info] = "Saved #{page}."
  redirect "/pages/#{page}"
end

get '/pages/:page/delete' do |page|
  return redirect '/auth' unless session[:db_session]
  db_session = Dropbox::Session.deserialize(session[:db_session])
  return redirect '/auth' unless db_session.authorized?
  user = User[:email => db_session.account.email]
  if not user.folder then
    flash[:info] = 'Please specify a folder for your wiki.'
    redirect '/settings'
  end
  db_session.mode=(:dropbox)
  root = db_session.list("/")
  root.each do |entry|
    if entry.directory? and entry.path == "/" + user.folder then folder = entry end
  end
  if not folder then db_session.create_folder(user.folder) end
  db_session.delete("/#{user.folder}/#{page}")
  flash[:info] = "Deleted #{page}."
  redirect "/pages"
end

get '/screen.css' do
  content_type 'text/css'
  sass :screen
end

helpers do
  def csrf_token
    Rack::Csrf.csrf_token(env)
  end

  def csrf_tag
    Rack::Csrf.csrf_tag(env)
  end
end
Something went wrong with that request. Please try again.