nesta-plugin-admin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ require 'sinatra'
2
+ require "nesta-plugin-admin/version"
3
+
4
+ Nesta::Plugin.register(__FILE__)
5
+
@@ -0,0 +1,253 @@
1
+ require 'fileutils'
2
+ module Nesta
3
+ module Plugin
4
+ module Admin
5
+ module Helpers
6
+ ########################################################################
7
+ # Simple Authentication Helpers
8
+ ########################################################################
9
+
10
+ # throw [:halt] on failure
11
+ def protected!
12
+ unless authorized?
13
+ response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
14
+ throw(:halt, [401, "Not authorized\n"])
15
+ end
16
+ end
17
+
18
+ # Check [Rack::Auth::Basic::Requst] for valid username
19
+ # and password against [Nesta::Config.username] and
20
+ # [Nesta::Config.password] set in config/config.yml
21
+ #
22
+ # @return [Boolean]
23
+ def authorized?
24
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
25
+ @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == [Nesta::Config.username, Nesta::Config.password]
26
+ end
27
+
28
+ ########################################################################
29
+ # View Helpers
30
+ ########################################################################
31
+
32
+ # Taken from Nesta helpers, as they weren't available in the
33
+ # Admin because it's a middleware.
34
+ #
35
+ # @return [String] clean path for linking
36
+ def path_to(page_path, absolute = false)
37
+ host = ''
38
+ if absolute
39
+ host << "http#{'s' if request.ssl?}://"
40
+ if (request.env.include?("HTTP_X_FORWARDED_HOST") or
41
+ request.port != (request.ssl? ? 443 : 80))
42
+ host << request.host_with_port
43
+ else
44
+ host << request.host
45
+ end
46
+ end
47
+ uri_parts = [host]
48
+ uri_parts << request.script_name.to_s if request.script_name
49
+ uri_parts << page_path
50
+ File.join(uri_parts)
51
+ end
52
+
53
+ # Taken from Nesta helpers, as they weren't available in the
54
+ # Admin because it's a middleware.
55
+ #
56
+ # @return [String] clean path for stylesheets
57
+ def local_stylesheet_link_tag(name)
58
+ pattern = File.expand_path("views/#{name}.s{a,c}ss", Nesta::App.root)
59
+ if Dir.glob(pattern).size > 0
60
+ haml_tag :link, :href => path_to("/css/#{name}.css"), :rel => "stylesheet"
61
+ end
62
+ end
63
+
64
+ # Override standard haml call to include special view location for
65
+ # admin templates. I know, I know, this will break templating for admin
66
+ # views, but it's a small price to pay.
67
+ #
68
+ # TODO: figure out a way to somehow inject these in to standard view path
69
+ #
70
+ # @return [String] rendered html from haml
71
+ def admin_haml template, options={}
72
+ haml template, { views: File.expand_path('../../views', File.dirname(__FILE__)), layout: :layout }.merge(options)
73
+ end
74
+ end
75
+
76
+ ########################################################################
77
+ # Core Modules
78
+ ########################################################################
79
+
80
+ # Write updates to disk:
81
+ # - strip begining slash
82
+ # - clean dirty chars
83
+ # - create directory if missing
84
+ #
85
+ # @param path [String] path to file being written
86
+ # @param params [String] params recieved by Sinatra from HTTP GET
87
+ def self.write path, params
88
+ path.gsub!(/^\//, '')
89
+ path.gsub!(/[\`\!\$\%\^\&\*\(\)\+\=\[\]\{\}\|\:\;\'\"\?\,\<\>\\]/, "-")
90
+ path = File.expand_path("#{path}.#{params["format"]}", File.join( Nesta::Env.root, Nesta::Config.page_path ))
91
+ FileUtils.mkdir_p(File.dirname(path)) unless File.directory?(File.dirname(path))
92
+ File.open(path, 'w') { |file| file.puts params["contents"] }
93
+ end
94
+
95
+ # Delete file from disk.
96
+ #
97
+ # @param path [String] path to file being deleted
98
+ def self.delete path
99
+ File.delete self.full_path(path).first
100
+ end
101
+
102
+ # Load file in raw form, existing Nesta load methods strip out metadata.
103
+ #
104
+ # @param path [String] path to file being loaded
105
+ def self.load_raw path
106
+ path, format = self.full_path(path)
107
+ [File.open(path, 'r').read, format]
108
+ end
109
+
110
+ # Load menu.txt file.
111
+ def self.load_menu
112
+ File.open(self.menu_path, 'r').read
113
+ end
114
+
115
+ # Write menu.txt file.
116
+ #
117
+ # @param params [String] params recieved by Sinatra from HTTP GET
118
+ def self.write_menu params
119
+ File.open(self.menu_path, 'w') { |file| file.puts params["contents"] }
120
+ end
121
+
122
+ # Build menu.txt path.
123
+ #
124
+ # @param path [String] path to menu.txt
125
+ def self.menu_path
126
+ File.expand_path("menu.txt", File.join( Nesta::Env.root, Nesta::Config.content_path ))
127
+ end
128
+
129
+ # Full path to page, technically a helper but here for plugins that use
130
+ # this plugin -- of which I may write.
131
+ #
132
+ # @param path [String] path to menu.txt
133
+ def self.full_path path
134
+ path.gsub!(/^\//, '')
135
+ Nesta::FileModel::FORMATS.each do |format|
136
+ [path, File.join(path, 'index')].each do |basename|
137
+ filename = File.expand_path("#{basename}.#{format}", File.join( Nesta::Env.root, Nesta::Config.page_path ))
138
+ if File.exist?(filename)
139
+ return [filename, format]
140
+ end
141
+ end
142
+ end
143
+ raise Sinatra::NotFound
144
+ end
145
+
146
+ # Expire all caches (both local and Sinatra::Cache).
147
+ def self.expire_caches
148
+ Nesta::Page.purge_cache
149
+ if Nesta::Config.cache
150
+ Nesta::Page.find_all.each do |page|
151
+ Sinatra::Cache.cache_expire(page.abspath)
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ # Adding username and password to settings list.
159
+ class Config
160
+ @settings += %w[ username password ]
161
+ end
162
+
163
+ class AdminScreens < Sinatra::Base
164
+ register Sinatra::Cache
165
+ set :cache_enabled, false
166
+
167
+ helpers Nesta::Plugin::Admin::Helpers
168
+
169
+ before '/admin*' do
170
+ protected!
171
+ headers['Cache-Control'] = 'no-cache'
172
+ end
173
+
174
+ after '/admin*', :method => :post do
175
+ Nesta::Plugin::Admin.expire_caches
176
+ end
177
+
178
+ after '/admin/*/delete' do
179
+ Nesta::Plugin::Admin.expire_caches
180
+ end
181
+
182
+ get '/admin/new' do
183
+ @action = "New Page"
184
+ @path, @content = nil
185
+ admin_haml :edit
186
+ end
187
+
188
+ post '/admin/new' do
189
+ response['Cache-Control'] = 'no-cache'
190
+ Nesta::Plugin::Admin.write(params["path"], params)
191
+ redirect "/"+params["path"]
192
+ end
193
+
194
+ get '/admin/*/delete' do
195
+ Nesta::Plugin::Admin.delete(File.join(params[:splat]))
196
+ redirect '/admin'
197
+ end
198
+
199
+ get '/admin' do
200
+ @action = "Pages"
201
+ @pages = Nesta::Page.find_all.sort { |a,b| a.title_for_admin <=> b.title_for_admin }
202
+ admin_haml :admin
203
+ end
204
+
205
+ get '/admin/menu' do
206
+ @action = "Edit Menu"
207
+ @path = "menu"
208
+ @format = nil
209
+ @content = Nesta::Plugin::Admin.load_menu
210
+ admin_haml :edit
211
+ end
212
+
213
+ post '/admin/menu' do
214
+ Nesta::Plugin::Admin.write_menu params
215
+ redirect "/"
216
+ end
217
+
218
+ post '/admin/*' do
219
+ path = File.join(params[:splat])
220
+ Nesta::Plugin::Admin.write(path, params)
221
+ redirect "/"+path
222
+ end
223
+
224
+ get '/admin/*' do
225
+ @action = "Edit Template"
226
+ @path = File.join(params[:splat])
227
+ @content, @format = Nesta::Plugin::Admin.load_raw @path
228
+ admin_haml :edit
229
+ end
230
+
231
+ end
232
+
233
+ # Adding special handlers for admin page. These may be better
234
+ # as helpers, but seemed to fix here within the context of
235
+ # the Page module.
236
+ class Page
237
+ attr_reader :format
238
+ def title_for_admin
239
+ t = self.title.gsub(" - #{Nesta::Config.title}","")
240
+ return (t.empty? ? 'Home' : t)
241
+ end
242
+ def path_for_admin
243
+ return (self.path.empty? ? 'index' : self.path)
244
+ end
245
+ end
246
+
247
+ # Include helpers and use AdminScreens.
248
+ class App
249
+ helpers Nesta::Plugin::Admin::Helpers
250
+ use AdminScreens
251
+ end
252
+ end
253
+
@@ -0,0 +1,7 @@
1
+ module Nesta
2
+ module Plugin
3
+ module Admin
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/nesta-plugin-admin/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Joshua Mervine"]
6
+ gem.email = ["joshua@mervine.net"]
7
+ gem.description = %q{An admin interface for Nesta.}
8
+ gem.summary = %q{An admin interface for Nesta focusing around adding, removing and editing pages.}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "nesta-plugin-admin"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Nesta::Plugin::Admin::VERSION
17
+ gem.add_dependency("nesta", ">= 0.9.11")
18
+ gem.add_development_dependency("rake")
19
+ end
data/spec_helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require File.join("..", "lib", "nesta-plugin-admin")
2
+
3
+ module SpecHelpers
4
+ extend self
5
+ TEMP_DIR=File.expand_path("tmp", File.dirname(__FILE__))
6
+ def setup_project
7
+ [
8
+ "cd #{TEMP_DIR}",
9
+ "cp ../Gemfile.spec Gemfile",
10
+ "bundle exec install --path ./vendor/bundle",
11
+ "bundle exec nesta new spec_site",
12
+ ""
13
+ ].join(" && ")
14
+ end
15
+ def breakdown_project
16
+
17
+ end
18
+ end
data/views/admin.haml ADDED
@@ -0,0 +1,14 @@
1
+ #admin_links
2
+ %a{:href=>"/admin/new"}new page
3
+ %br
4
+ %a{:href=>"/admin/menu"}edit menu
5
+ #admin_content
6
+ - @pages.each do |page|
7
+ %section(role="main")<
8
+ %a{:href=>"/admin/#{page.path_for_admin}"}>edit
9
+ &nbsp;|&nbsp;
10
+ %a{:href=>"/admin/#{page.path_for_admin}/delete"}<delete
11
+ &nbsp;&nbsp;&nbsp;
12
+ ="#{page.title_for_admin} (#{page.path_for_admin}.#{page.format})"
13
+ %br
14
+
data/views/edit.haml ADDED
@@ -0,0 +1,19 @@
1
+ %form{:action=>"/admin/#{@path||'new'}", :method=>"post"}
2
+ #admin_content
3
+ - unless @path == "menu"
4
+ %label Page Path:
5
+ %br
6
+ %input.path{:type=>'text',:name=>'path',:value=>@path||''}>
7
+ %select{:name=>"format"}
8
+ - Nesta::FileModel::FORMATS.each do |format|
9
+ %option{:value=>format, :selected=>(@format==format)}= format
10
+ %br
11
+ %small (ex: article-name)
12
+ #contents
13
+ - unless @path == "menu"
14
+ %label Page Body:
15
+ %br
16
+ %textarea{:name=>'contents'}= @content||''
17
+ #buttons
18
+ %input.button{ :type => "button", "value" => "Cancel!", :onclick => "top.location.href='/admin';" }
19
+ %input.button{ :type => "submit", "value" => "Save!" }
data/views/footer.haml ADDED
@@ -0,0 +1,5 @@
1
+ %footer.branding
2
+ %p
3
+ Powered by Nesta, a
4
+ = succeed "." do
5
+ %a(href="http://nestacms.com") Ruby CMS
data/views/header.haml ADDED
@@ -0,0 +1,4 @@
1
+ %header(role="banner")
2
+ %hgroup
3
+ %h1 Admin
4
+ %h2= @action
data/views/layout.haml ADDED
@@ -0,0 +1,76 @@
1
+ <!DOCTYPE html>
2
+ %html(lang="en")
3
+ %head
4
+ %title Admin
5
+ <!--[if ! lte IE 6]><!-->
6
+ %link(href="#{path_to('/css/master.css')}" media="screen" rel="stylesheet")
7
+ <!--<![endif]-->
8
+ /[if lte IE 6]
9
+ %link(rel="stylesheet" href="http://universal-ie6-css.googlecode.com/files/ie6.1.1.css" media="screen, projection")
10
+ /[if lt IE 9]
11
+ %script(src="//html5shim.googlecode.com/svn/trunk/html5.js")
12
+ - local_stylesheet_link_tag('local')
13
+ :css
14
+ #admin_links {
15
+ float:right;
16
+ }
17
+ #admin_content {
18
+ width: 100%;
19
+ }
20
+ textarea {
21
+ font-face: monospace;
22
+ font-size: 10pt;
23
+ height: 500px;
24
+ padding: 3px;
25
+ width: 600px;
26
+ border: 1px solid #999;
27
+ border: inset 1px solid #333;
28
+ -webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
29
+ -moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
30
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
31
+ }
32
+ input.path {
33
+ font-face: monospace;
34
+ font-size: 12pt;
35
+ height: 25px;
36
+ width: 500px;
37
+ padding: 3px;
38
+ border: 1px solid #999;
39
+ border: inset 1px solid #333;
40
+ -webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
41
+ -moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
42
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
43
+ }
44
+ select {
45
+ font-face: monospace;
46
+ font-size: 12pt;
47
+ height: 25px;
48
+ padding: 8px;
49
+ margin: 0 0 0 5px;
50
+ position: relative;
51
+ border: 1px solid #999;
52
+ border: inset 1px solid #333;
53
+ -webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
54
+ -moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
55
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
56
+ }
57
+ input.button {
58
+ font-size: 12pt;
59
+ width: 150px;
60
+ height: 30px;
61
+ background-color: #eee;
62
+ border: 1px solid #999;
63
+ border: inset 1px solid #333;
64
+ -webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
65
+ -moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
66
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
67
+ }
68
+ %body
69
+ #container
70
+ = admin_haml :header, :layout => false
71
+ %hr
72
+ %br
73
+ = yield
74
+ %br
75
+ %br
76
+ = admin_haml :footer, :layout => false
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nesta-plugin-admin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joshua Mervine
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nesta
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.11
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.9.11
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: An admin interface for Nesta.
47
+ email:
48
+ - joshua@mervine.net
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE
56
+ - README.md
57
+ - Rakefile
58
+ - doc/Nesta.html
59
+ - doc/Nesta/AdminScreens.html
60
+ - doc/Nesta/App.html
61
+ - doc/Nesta/Config.html
62
+ - doc/Nesta/Page.html
63
+ - doc/Nesta/Plugin.html
64
+ - doc/Nesta/Plugin/Admin.html
65
+ - doc/Nesta/Plugin/Admin/Helpers.html
66
+ - doc/_index.html
67
+ - doc/class_list.html
68
+ - doc/css/common.css
69
+ - doc/css/full_list.css
70
+ - doc/css/style.css
71
+ - doc/file.README.html
72
+ - doc/file_list.html
73
+ - doc/frames.html
74
+ - doc/index.html
75
+ - doc/js/app.js
76
+ - doc/js/full_list.js
77
+ - doc/js/jquery.js
78
+ - doc/method_list.html
79
+ - doc/top-level-namespace.html
80
+ - lib/nesta-plugin-admin.rb
81
+ - lib/nesta-plugin-admin/init.rb
82
+ - lib/nesta-plugin-admin/version.rb
83
+ - nesta-plugin-admin.gemspec
84
+ - spec_helper.rb
85
+ - views/admin.haml
86
+ - views/edit.haml
87
+ - views/footer.haml
88
+ - views/header.haml
89
+ - views/layout.haml
90
+ homepage: ''
91
+ licenses: []
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 1.8.24
111
+ signing_key:
112
+ specification_version: 3
113
+ summary: An admin interface for Nesta focusing around adding, removing and editing
114
+ pages.
115
+ test_files: []
116
+ has_rdoc: