caboose-cms 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +4 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/javascripts/caboose/application.js +36 -0
  5. data/app/assets/javascripts/caboose/login.js +21 -0
  6. data/app/assets/javascripts/caboose/permissions.js +0 -0
  7. data/app/assets/javascripts/caboose/roles.js +35 -0
  8. data/app/assets/javascripts/caboose/users.js +38 -0
  9. data/app/assets/stylesheets/caboose/application.css +15 -0
  10. data/app/assets/stylesheets/caboose/caboose.css +28 -0
  11. data/app/controllers/caboose/admin_controller.rb +19 -0
  12. data/app/controllers/caboose/application_controller.rb +109 -0
  13. data/app/controllers/caboose/login_controller.rb +40 -0
  14. data/app/controllers/caboose/logout_controller.rb +9 -0
  15. data/app/controllers/caboose/pages_controller.rb +304 -0
  16. data/app/controllers/caboose/permissions_controller.rb +83 -0
  17. data/app/controllers/caboose/roles_controller.rb +109 -0
  18. data/app/controllers/caboose/users_controller.rb +117 -0
  19. data/app/helpers/caboose/application_helper.rb +4 -0
  20. data/app/helpers/caboose/permissions_helper.rb +4 -0
  21. data/app/models/caboose/approval_request.rb +13 -0
  22. data/app/models/caboose/asset.rb +23 -0
  23. data/app/models/caboose/caboose_plugin.rb +15 -0
  24. data/app/models/caboose/menu_block.rb +6 -0
  25. data/app/models/caboose/page.rb +329 -0
  26. data/app/models/caboose/page_bar_generator.rb +157 -0
  27. data/app/models/caboose/page_permission.rb +7 -0
  28. data/app/models/caboose/permission.rb +14 -0
  29. data/app/models/caboose/role.rb +50 -0
  30. data/app/models/caboose/std_class.rb +8 -0
  31. data/app/models/caboose/user.rb +47 -0
  32. data/app/views/caboose/admin/index.html.erb +5 -0
  33. data/app/views/caboose/application/show.html.erb +2 -0
  34. data/app/views/caboose/extras/error.html.erb +2 -0
  35. data/app/views/caboose/extras/error404.html.erb +0 -0
  36. data/app/views/caboose/login/index.html.erb +26 -0
  37. data/app/views/caboose/pages/edit.html.erb +45 -0
  38. data/app/views/caboose/pages/index.html.erb +34 -0
  39. data/app/views/caboose/pages/new.html.erb +23 -0
  40. data/app/views/caboose/pages/show.html.erb +2 -0
  41. data/app/views/caboose/pages/update_pic.html.erb +16 -0
  42. data/app/views/caboose/pages/update_resume.html.erb +14 -0
  43. data/app/views/caboose/permissions/edit.html.erb +6 -0
  44. data/app/views/caboose/permissions/index.html.erb +25 -0
  45. data/app/views/caboose/permissions/new.html.erb +5 -0
  46. data/app/views/caboose/permissions/show.html.erb +15 -0
  47. data/app/views/caboose/roles/edit.html.erb +36 -0
  48. data/app/views/caboose/roles/index.html.erb +17 -0
  49. data/app/views/caboose/roles/new.html.erb +16 -0
  50. data/app/views/caboose/roles/show.html.erb +20 -0
  51. data/app/views/caboose/users/edit.html.erb +45 -0
  52. data/app/views/caboose/users/index.html.erb +34 -0
  53. data/app/views/caboose/users/new.html.erb +22 -0
  54. data/app/views/caboose/users/update_pic.html.erb +16 -0
  55. data/app/views/caboose/users/update_resume.html.erb +14 -0
  56. data/app/views/layouts/caboose/application.html.erb +24 -0
  57. data/app/views/layouts/caboose/caboose.html.erb +24 -0
  58. data/app/views/layouts/caboose/error404.html.erb +2 -0
  59. data/app/views/layouts/caboose/station.html.erb +28 -0
  60. data/config/routes.rb +48 -0
  61. data/db/migrate/20130421000000_drop_all_caboose.rb +16 -0
  62. data/db/migrate/20130422000000_create_caboose.rb +147 -0
  63. data/lib/caboose.rb +26 -0
  64. data/lib/caboose/engine.rb +24 -0
  65. data/lib/caboose/version.rb +3 -0
  66. data/lib/tasks/caboose_tasks.rake +4 -0
  67. data/test/caboose_test.rb +7 -0
  68. data/test/dummy/README.rdoc +261 -0
  69. data/test/dummy/Rakefile +7 -0
  70. data/test/dummy/app/assets/javascripts/application.js +15 -0
  71. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  72. data/test/dummy/app/controllers/application_controller.rb +3 -0
  73. data/test/dummy/app/helpers/application_helper.rb +2 -0
  74. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  75. data/test/dummy/config.ru +4 -0
  76. data/test/dummy/config/application.rb +59 -0
  77. data/test/dummy/config/boot.rb +10 -0
  78. data/test/dummy/config/database.yml +25 -0
  79. data/test/dummy/config/environment.rb +5 -0
  80. data/test/dummy/config/environments/development.rb +37 -0
  81. data/test/dummy/config/environments/production.rb +67 -0
  82. data/test/dummy/config/environments/test.rb +37 -0
  83. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  84. data/test/dummy/config/initializers/inflections.rb +15 -0
  85. data/test/dummy/config/initializers/mime_types.rb +5 -0
  86. data/test/dummy/config/initializers/secret_token.rb +7 -0
  87. data/test/dummy/config/initializers/session_store.rb +8 -0
  88. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  89. data/test/dummy/config/locales/en.yml +5 -0
  90. data/test/dummy/config/routes.rb +4 -0
  91. data/test/dummy/db/test.sqlite3 +0 -0
  92. data/test/dummy/log/test.log +25 -0
  93. data/test/dummy/public/404.html +26 -0
  94. data/test/dummy/public/422.html +26 -0
  95. data/test/dummy/public/500.html +25 -0
  96. data/test/dummy/public/favicon.ico +0 -0
  97. data/test/dummy/script/rails +6 -0
  98. data/test/integration/navigation_test.rb +10 -0
  99. data/test/test_helper.rb +15 -0
  100. metadata +241 -0
@@ -0,0 +1,157 @@
1
+ module Caboose
2
+ class PageBarGenerator
3
+ #
4
+ # Parameters:
5
+ # params: array of key/value pairs that must include the following:
6
+ # base_url: url without querystring onto which the parameters are added.
7
+ # itemCount: Total number of items.
8
+ #
9
+ # In addition, the following parameters are not required but may be
10
+ # included in the array:
11
+ # itemsPerPage: Number of items you want to show per page. Defaults to 10 if not present.
12
+ # page: Current page number. Defaults to 0 if not present.
13
+ #
14
+ attr_accessor :params, :options
15
+
16
+ def initialize(post_get, params = nil, options = nil)
17
+
18
+ params = {} if params.nil?
19
+ options = {} if options.nil?
20
+
21
+ # Note: a few keys are required:
22
+ # base_url, page, itemCount, itemsPerPage
23
+ @params = {}
24
+ @options = {
25
+ 'sort' => '',
26
+ 'desc' => false,
27
+ 'base_url' => '',
28
+ 'page' => 0,
29
+ 'item_count' => 0,
30
+ 'items_per_page' => 10
31
+ }
32
+ params.each { |key, val| @params[key] = val }
33
+ options.each { |key, val| @options[key] = val }
34
+ @params.each { |key, val| @params[key] = post_get[key].nil? ? val : post_get[key] }
35
+ @options.each { |key, val| @options[key] = post_get[key].nil? ? val : post_get[key] }
36
+
37
+ end
38
+
39
+ def ok(val)
40
+ return false if val.nil?
41
+ return true if val.is_a? Array
42
+ return true if val.is_a? Hash
43
+ return true if val.is_a? Integer
44
+ return true if val.is_a? Fixnum
45
+ return true if val.is_a? Float
46
+ return true if val.is_a? Bignum
47
+ return true if val.is_a? TrueClass
48
+ return true if val.is_a? FalseClass
49
+ return false if val == ""
50
+ return true
51
+ end
52
+
53
+ def generate
54
+
55
+ # Check for necessary parameter values
56
+ return false if !ok(@options['base_url']) # Error: base_url is required for the page bar generator to work.
57
+ return false if !ok(@options['item_count']) # Error: itemCount is required for the page bar generator to work.
58
+
59
+ # Set default parameter values if not present
60
+ @options['items_per_page'] = 10 if @options["items_per_page"].nil?
61
+ @options['page'] = 0 if @options["page"].nil?
62
+
63
+ # Variables to make the search form work
64
+ vars = get_vars()
65
+ page = @options["page"]
66
+
67
+ # Max links to show (must be odd)
68
+ total_links = 9
69
+ prev_page = page - 1
70
+ next_page = page + 1
71
+ total_pages = (@options['item_count'].to_f / @options['items_per_page'].to_f).ceil
72
+
73
+ if (total_pages < total_links)
74
+ start = 0
75
+ stop = total_pages
76
+ else
77
+ start = page - (total_links/2).floor
78
+ start = 0 if start < 0
79
+ stop = start + total_links
80
+
81
+ if (stop > total_pages)
82
+ stop = total_pages
83
+ start = stop - total_links
84
+ start = 0 if start < 0
85
+ end
86
+ end
87
+
88
+ base_url = @params['base_url']
89
+ str = ''
90
+ str << "<p>Results Pages: showing page " + (page+1).to_s + " of #{total_pages}</p>\n"
91
+ str << "<div class='page_links'>\n"
92
+ if (page > 0)
93
+ str << "<a href='#{base_url}?#{vars}&page=#{prev_page}'>Previous</a>"
94
+ end
95
+
96
+ for i in start..(stop-1)
97
+ if (page != i)
98
+ str << "<a href='#{base_url}?#{vars}&page=#{i}'>" + (i+1).to_s + "</a>"
99
+ else
100
+ str << "<span class='current_page'>" + (i+1).to_s + "</span>"
101
+ end
102
+ end
103
+
104
+ if (page < (total_pages-1))
105
+ str << "<a href='#{base_url}?#{vars}&page=#{next_page}'>Next</a>"
106
+ end
107
+ str << "</div>\n"
108
+
109
+ return str
110
+ end
111
+
112
+ def get_vars()
113
+ vars = []
114
+ @params.each do |k,v|
115
+ vars.push("#{k}=#{v}") if !v.nil? && v.length > 0
116
+ end
117
+ return URI.escape(vars.join('&'))
118
+ end
119
+
120
+ def sortable_table_headings(cols)
121
+ vars = get_vars()
122
+ str = ''
123
+
124
+ # key = sort field, value = text to display
125
+ cols.each do |sort, text|
126
+ desc = @options['sort'] == sort ? (@options['desc'] ? 0 : 1) : 0
127
+ arrow = @options['sort'] == sort ? (@options['desc'] ? ' &uarr' : ' &darr') : ''
128
+ link = @options['base_url'] + "?#{vars}&sort=#{sort}&desc=#{desc}"
129
+ str += "<th><a href='#{link}'>#{text}#{arrow}</a></th>\n"
130
+ end
131
+ return str
132
+ end
133
+
134
+ def where
135
+ vars = {}
136
+ @params.each do |k,v|
137
+ vars[k] = v if !v.nil? && v.length > 0
138
+ end
139
+ return vars
140
+ end
141
+
142
+ def limit
143
+ return @options['items_per_page']
144
+ end
145
+
146
+ def offset
147
+ return @options['page'] * @options['items_per_page']
148
+ end
149
+
150
+ def reorder
151
+ if (!@options['sort'].nil? && @options['sort'].length > 0)
152
+ return @options['sort']
153
+ end
154
+ return "id"
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,7 @@
1
+
2
+ class Caboose::PagePermission < ActiveRecord::Base
3
+ self.table_name = "page_permissions"
4
+ belongs_to :page
5
+ belongs_to :role
6
+ attr_accessible :page_id, :role_id, :action
7
+ end
@@ -0,0 +1,14 @@
1
+
2
+ class Caboose::Permission < ActiveRecord::Base
3
+ self.table_name = "permissions"
4
+ has_and_belongs_to_many :roles
5
+ attr_accessible :action, :resource
6
+
7
+ def self.allow(role_id, resource, action)
8
+ role = Role.find(role_id)
9
+ perm = Permission.where(:resource => resource, :action => action).first
10
+ return if role.nil? || perm.nil?
11
+ role.permissions.push(perm)
12
+ role.save
13
+ end
14
+ end
@@ -0,0 +1,50 @@
1
+
2
+ class Caboose::Role < ActiveRecord::Base
3
+ self.table_name = "roles"
4
+ has_and_belongs_to_many :users
5
+ has_and_belongs_to_many :permissions
6
+ has_many :page_permissions
7
+
8
+ attr_accessible :name, :description, :parent_id
9
+ attr_accessor :children
10
+
11
+ ADMIN_ROLE_ID = 1
12
+ LOGGED_OUT_ROLE_ID = 2
13
+ LOGGED_IN_ROLE_ID = 3
14
+
15
+ def is_allowed(resource, action)
16
+
17
+ # Check for the admin permission
18
+ for perm in permissions
19
+ return true if (perm.resource == "all" && perm.action == "all")
20
+ end
21
+
22
+ if (resource.is_a?(Caboose::Page))
23
+ for perm in page_permissions
24
+ return true if (perm.page_id == resource.id && perm.action == action)
25
+ end
26
+ elsif
27
+ for perm in permissions
28
+ return true if (perm.resource == resource && perm.action == action)
29
+ end
30
+ end
31
+ return false
32
+ end
33
+
34
+ def children
35
+ Caboose::Role.where(:parent_id => id).reorder("name").all
36
+ end
37
+
38
+ #-----------------------------------------------------------------------------
39
+ # Class methods
40
+ #-----------------------------------------------------------------------------
41
+
42
+ def self.roles_with_user(user_id)
43
+ return self.where("users.id" => user_id).all(:include => :users)
44
+ end
45
+
46
+ def self.tree
47
+ return self.where(:parent_id => -1).reorder("name").all
48
+ end
49
+
50
+ end
@@ -0,0 +1,8 @@
1
+ require "ostruct"
2
+ module Caboose
3
+ class StdClass < OpenStruct
4
+ def as_json(options = nil)
5
+ @table.as_json(options)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,47 @@
1
+
2
+ class Caboose::User < ActiveRecord::Base
3
+ self.table_name = "users"
4
+ has_and_belongs_to_many :roles
5
+ has_many :workouts
6
+ attr_accessible :email, :first_name, :last_name, :username, :token, :password
7
+
8
+ LOGGED_OUT_USER_ID = 2
9
+
10
+ def is_allowed(resource, action)
11
+ for role in roles
12
+ if role.is_allowed(resource, action)
13
+ return true
14
+ end
15
+ end
16
+ return false;
17
+ end
18
+
19
+ def self.validate_token(token)
20
+ user = User.where('token' => token).first
21
+ return user
22
+ end
23
+
24
+ def add_to_role_with_name(role_name)
25
+ r = Role.where(:name => role_name).first
26
+ return false if r.nil?
27
+ return add_to_role(r.id)
28
+ end
29
+
30
+ def add_to_role(role_id)
31
+ r = Role.find(role_id)
32
+ return false if r.nil?
33
+
34
+ if (!is_member?(r.id))
35
+ roles.push r
36
+ save
37
+ end
38
+ return true
39
+ end
40
+
41
+ def is_member?(role_id)
42
+ roles.each do |r|
43
+ return true if (r.id == role_id)
44
+ end
45
+ return false
46
+ end
47
+ end
@@ -0,0 +1,5 @@
1
+ <h1>Admin</h1>
2
+
3
+ <% @mods.each do |mod| %>
4
+ <p><a href='<%= mod['href'] %>'><%= mod['text'] %></a></p>
5
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <% content_for :page_title do %><%= @page.title %><% end %>
2
+ <% content_for :page_content do %><%= @page.content %><% end %>
@@ -0,0 +1,2 @@
1
+ <h1>Error</h1>
2
+ <p class='note error'><%= @error %></p>
File without changes
@@ -0,0 +1,26 @@
1
+
2
+ <%
3
+ # Purposefully call the host app's stylesheet
4
+ %>
5
+ <%= content_for :caboose_css do %>
6
+ <%= stylesheet_link_tag "login", :media => "all" %>
7
+ <% end %>
8
+
9
+ <%
10
+ # But call caboose's javascript
11
+ %>
12
+ <%= content_for :caboose_js do %>
13
+ <%= javascript_include_tag "caboose/login" %>
14
+ <% end %>
15
+
16
+ <h1>Login</h1>
17
+
18
+ <form action='/login' method='post' id='login_form'>
19
+ <input type='hidden' name='return_url' value='<%= @return_url %>' />
20
+ <dl>
21
+ <dt>Username:</dt><dd><input type='text' name='username' style='width: 200px;' /></dd>
22
+ <dt>Password:</dt><dd><input type='password' name='password' style='width: 200px;' /></dd>
23
+ <div id='message'></div>
24
+ <p><input type='submit' value='Login' onclick='login(); return false;' /></p>
25
+ </dl>
26
+ </form>
@@ -0,0 +1,45 @@
1
+ <%
2
+
3
+ def json(obj, defaultvalue = "")
4
+ return defaultvalue.to_json if obj.nil?
5
+ return obj.to_json
6
+ end
7
+
8
+ %>
9
+ <h1>Edit Page</h1>
10
+
11
+ <div id='page_<%= @page.id %>_container'></div>
12
+
13
+ <% content_for :caboose_js do %>
14
+ <script type="text/javascript">
15
+
16
+ $(document).ready(function() {
17
+ var page = new Model({
18
+ name: 'Page',
19
+ id: <%= @page.id %>,
20
+ attributes: [
21
+ { name: 'title' , type: 'text' , value: <%= raw json(@page.title ) %> },
22
+ { name: 'content' , type: 'textarea' , value: <%= raw json(@page.content ) %> },
23
+ { name: 'parent_id' , type: 'select' , value: <%= raw json(@page.parent_id, -1 ) %>, text: <%= raw (@page.parent_id == -1 ? "[No Parent]" : @page.parent.title).to_json %>, options_url: '/pages/sitemap-options' },
24
+ { name: 'menu_title' , type: 'text' , value: <%= raw json(@page.menu_title ) %> },
25
+ { name: 'slug' , type: 'text' , value: <%= raw json(@page.slug ) %> },
26
+ { name: 'alias' , type: 'text' , value: <%= raw json(@page.alias ) %> },
27
+ { name: 'redirect_url' , type: 'text' , value: <%= raw json(@page.redirect_url ) %> },
28
+ { name: 'hide' , type: 'checkbox' , value: <%= raw @page.hide %> },
29
+ { name: 'content_format' , type: 'select' , value: <%= raw json(@page.content_format ) %> },
30
+ { name: 'custom_css' , type: 'textarea' , value: <%= raw json(@page.custom_css ) %> },
31
+ { name: 'custom_js' , type: 'textarea' , value: <%= raw json(@page.custom_js ) %> },
32
+ { name: 'layout' , type: 'text' , value: <%= raw json(@page.layout ) %> },
33
+ { name: 'custom_sort_children' , type: 'select' , value: <%= raw json(@page.custom_sort_children ) %>, text: "" },
34
+ { name: 'seo_title' , type: 'text' , value: <%= raw json(@page.seo_title ) %> },
35
+ { name: 'meta_description' , type: 'text' , value: <%= raw json(@page.meta_description ) %> },
36
+ { name: 'meta_robots' , type: 'checkbox-multiple' , value: <%= raw (@page.meta_robots.nil? ? [] : @page.meta_robots.split(', ')).to_json %>, text: <%= raw (@page.meta_robots.nil? ? "[Empty]" : @page.meta_robots).to_json %>, options_url: '/pages/robots-options' },
37
+ { name: 'canonical_url' , type: 'text' , value: <%= raw json(@page.canonical_url ) %> },
38
+ { name: 'fb_description' , type: 'text' , value: <%= raw json(@page.fb_description ) %> },
39
+ { name: 'gp_description' , type: 'text' , value: <%= raw json(@page.gp_description ) %> }
40
+ ]
41
+ });
42
+ });
43
+
44
+ </script>
45
+ <% end %>
@@ -0,0 +1,34 @@
1
+ <h1>Users</h1>
2
+
3
+ <p><a href='/users/new'>New User</a></p>
4
+
5
+ <form action='/users' method='get'>
6
+ <table cellpadding='4' cellspacing='0' border='0'>
7
+ <tr><td>First name: </td><td><input type='text' name='first_name' value='<%= @gen.params['first_name'] %>' style='width: 200px;' /></td></tr>
8
+ <tr><td>Last name: </td><td><input type='text' name='last_name' value='<%= @gen.params['last_name'] %>' style='width: 200px;' /></td></tr>
9
+ <tr><td>Username: </td><td><input type='text' name='username' value='<%= @gen.params['username'] %>' style='width: 200px;' /></td></tr>
10
+ </table><br />
11
+ <p><input type='submit' value='Search' /></p>
12
+ </form>
13
+
14
+ <table class='data'>
15
+ <tr>
16
+ <%= raw @gen.sortable_table_headings({
17
+ 'first_name' => 'First Name',
18
+ 'last_name, first_name' => 'Last Name',
19
+ 'username' => 'Username',
20
+ 'email' => 'Email'
21
+ })
22
+ %>
23
+ </tr>
24
+ <% @users.each do |user| %>
25
+ <tr onclick="window.location='/users/<%= user.id %>/edit';">
26
+ <td><%= user.first_name %></td>
27
+ <td><%= user.last_name %></td>
28
+ <td><%= user.username %></td>
29
+ <td><%= user.email %></td>
30
+ </tr>
31
+ <% end %>
32
+ </table>
33
+
34
+ <p><%= raw @gen.generate %></p>
@@ -0,0 +1,23 @@
1
+
2
+ <h1>New Page</h1>
3
+ <div id='page_new_container'></div>
4
+
5
+ <% content_for :caboose_js do %>
6
+ <script type='text/javascript'>
7
+
8
+ var page = false;
9
+ $(document).ready(function() {
10
+
11
+ page = new Model({
12
+ name: 'Page',
13
+ id: 'new',
14
+ attributes: [
15
+ { name: 'parent_id' , type: 'select' , value: <%= @parent_id %>, options_url: '/pages/sitemap-options' },
16
+ { name: 'title' , type: 'text' , value: '' }
17
+ ]
18
+ });
19
+
20
+ });
21
+
22
+ </script>
23
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <% content_for :page_title do %><%= @page.title %><% end %>
2
+ <% content_for :page_content do %><%= @page.content %><% end %>