caboose-cms 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +4 -0
- data/Rakefile +40 -0
- data/app/assets/javascripts/caboose/application.js +36 -0
- data/app/assets/javascripts/caboose/login.js +21 -0
- data/app/assets/javascripts/caboose/permissions.js +0 -0
- data/app/assets/javascripts/caboose/roles.js +35 -0
- data/app/assets/javascripts/caboose/users.js +38 -0
- data/app/assets/stylesheets/caboose/application.css +15 -0
- data/app/assets/stylesheets/caboose/caboose.css +28 -0
- data/app/controllers/caboose/admin_controller.rb +19 -0
- data/app/controllers/caboose/application_controller.rb +109 -0
- data/app/controllers/caboose/login_controller.rb +40 -0
- data/app/controllers/caboose/logout_controller.rb +9 -0
- data/app/controllers/caboose/pages_controller.rb +304 -0
- data/app/controllers/caboose/permissions_controller.rb +83 -0
- data/app/controllers/caboose/roles_controller.rb +109 -0
- data/app/controllers/caboose/users_controller.rb +117 -0
- data/app/helpers/caboose/application_helper.rb +4 -0
- data/app/helpers/caboose/permissions_helper.rb +4 -0
- data/app/models/caboose/approval_request.rb +13 -0
- data/app/models/caboose/asset.rb +23 -0
- data/app/models/caboose/caboose_plugin.rb +15 -0
- data/app/models/caboose/menu_block.rb +6 -0
- data/app/models/caboose/page.rb +329 -0
- data/app/models/caboose/page_bar_generator.rb +157 -0
- data/app/models/caboose/page_permission.rb +7 -0
- data/app/models/caboose/permission.rb +14 -0
- data/app/models/caboose/role.rb +50 -0
- data/app/models/caboose/std_class.rb +8 -0
- data/app/models/caboose/user.rb +47 -0
- data/app/views/caboose/admin/index.html.erb +5 -0
- data/app/views/caboose/application/show.html.erb +2 -0
- data/app/views/caboose/extras/error.html.erb +2 -0
- data/app/views/caboose/extras/error404.html.erb +0 -0
- data/app/views/caboose/login/index.html.erb +26 -0
- data/app/views/caboose/pages/edit.html.erb +45 -0
- data/app/views/caboose/pages/index.html.erb +34 -0
- data/app/views/caboose/pages/new.html.erb +23 -0
- data/app/views/caboose/pages/show.html.erb +2 -0
- data/app/views/caboose/pages/update_pic.html.erb +16 -0
- data/app/views/caboose/pages/update_resume.html.erb +14 -0
- data/app/views/caboose/permissions/edit.html.erb +6 -0
- data/app/views/caboose/permissions/index.html.erb +25 -0
- data/app/views/caboose/permissions/new.html.erb +5 -0
- data/app/views/caboose/permissions/show.html.erb +15 -0
- data/app/views/caboose/roles/edit.html.erb +36 -0
- data/app/views/caboose/roles/index.html.erb +17 -0
- data/app/views/caboose/roles/new.html.erb +16 -0
- data/app/views/caboose/roles/show.html.erb +20 -0
- data/app/views/caboose/users/edit.html.erb +45 -0
- data/app/views/caboose/users/index.html.erb +34 -0
- data/app/views/caboose/users/new.html.erb +22 -0
- data/app/views/caboose/users/update_pic.html.erb +16 -0
- data/app/views/caboose/users/update_resume.html.erb +14 -0
- data/app/views/layouts/caboose/application.html.erb +24 -0
- data/app/views/layouts/caboose/caboose.html.erb +24 -0
- data/app/views/layouts/caboose/error404.html.erb +2 -0
- data/app/views/layouts/caboose/station.html.erb +28 -0
- data/config/routes.rb +48 -0
- data/db/migrate/20130421000000_drop_all_caboose.rb +16 -0
- data/db/migrate/20130422000000_create_caboose.rb +147 -0
- data/lib/caboose.rb +26 -0
- data/lib/caboose/engine.rb +24 -0
- data/lib/caboose/version.rb +3 -0
- data/lib/tasks/caboose_tasks.rake +4 -0
- data/test/caboose_test.rb +7 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +25 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +15 -0
- metadata +241 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Caboose'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
Bundler::GemHelper.install_tasks
|
29
|
+
|
30
|
+
require 'rake/testtask'
|
31
|
+
|
32
|
+
Rake::TestTask.new(:test) do |t|
|
33
|
+
t.libs << 'lib'
|
34
|
+
t.libs << 'test'
|
35
|
+
t.pattern = 'test/**/*_test.rb'
|
36
|
+
t.verbose = false
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
task :default => :test
|
@@ -0,0 +1,36 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// the compiled file.
|
9
|
+
//
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
12
|
+
//
|
13
|
+
//= require caboose_before
|
14
|
+
//= require jquery
|
15
|
+
//= require jquery_ujs
|
16
|
+
//= require jquery-ui
|
17
|
+
//= require class
|
18
|
+
//= require model/model
|
19
|
+
//= require model/attribute
|
20
|
+
//= require model/form
|
21
|
+
//= require model/form/embedded
|
22
|
+
//= require model/attribute/checkbox-multiple
|
23
|
+
//= require model/attribute/checkbox
|
24
|
+
//= require model/attribute/date-time
|
25
|
+
//= require model/attribute/file
|
26
|
+
//= require model/attribute/hidden
|
27
|
+
//= require model/attribute/image
|
28
|
+
//= require model/attribute/password
|
29
|
+
//= require model/attribute/radio
|
30
|
+
//= require model/attribute/rich-text
|
31
|
+
//= require model/attribute/select
|
32
|
+
//= require model/attribute/texarea
|
33
|
+
//= require model/attribute/textjs
|
34
|
+
//= require model/attribute/time
|
35
|
+
//= require model/attribute/video
|
36
|
+
//= require caboose_after
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
function login()
|
3
|
+
{
|
4
|
+
$('#message').html("<p class='loading'>Logging in...</p>");
|
5
|
+
|
6
|
+
$.ajax({
|
7
|
+
url: '/login',
|
8
|
+
type: 'post',
|
9
|
+
data: $('#login_form').serialize(),
|
10
|
+
success: function(resp) {
|
11
|
+
if (resp.error)
|
12
|
+
$('#message').html("<p class='note error'>" + resp.error + "</p>");
|
13
|
+
else if (resp.redirect != false)
|
14
|
+
window.location = resp.redirect;
|
15
|
+
},
|
16
|
+
error: function() {
|
17
|
+
$('#message').html("<p class='note error'>Error</p>");
|
18
|
+
}
|
19
|
+
});
|
20
|
+
}
|
21
|
+
|
File without changes
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
Caboose.Role = function(){};
|
3
|
+
|
4
|
+
Caboose.Role.add = function()
|
5
|
+
{
|
6
|
+
$('#message').html("<p class='loading'>Adding role...</p>");
|
7
|
+
|
8
|
+
$.ajax({
|
9
|
+
url: '/roles',
|
10
|
+
type: 'post',
|
11
|
+
data: $('#new_role_form').serialize(),
|
12
|
+
success: Caboose.ajax_success,
|
13
|
+
error: Caboose.ajax_error
|
14
|
+
});
|
15
|
+
};
|
16
|
+
|
17
|
+
Caboose.Role.delete = function(role_id, confirm)
|
18
|
+
{
|
19
|
+
if (!confirm)
|
20
|
+
{
|
21
|
+
Caboose.confirm({
|
22
|
+
message: "Are you sure you want to delete the role? This can't be undone.",
|
23
|
+
yes: function() { Caboose.Role.delete(role_id, true) }
|
24
|
+
});
|
25
|
+
return;
|
26
|
+
}
|
27
|
+
$('#message').html("<p class='loading'>Deleting role...</p>");
|
28
|
+
|
29
|
+
$.ajax({
|
30
|
+
url: '/roles/' + role_id,
|
31
|
+
type: 'delete',
|
32
|
+
success: Caboose.ajax_success,
|
33
|
+
error: Caboose.ajax_error
|
34
|
+
});
|
35
|
+
};
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
Nine
|
4
|
+
Caboose.User = function(){};
|
5
|
+
|
6
|
+
Caboose.User.add = function()
|
7
|
+
{
|
8
|
+
$('#message').html("<p class='loading'>Adding user...</p>");
|
9
|
+
|
10
|
+
$.ajax({
|
11
|
+
url: '/users',
|
12
|
+
type: 'post',
|
13
|
+
data: $('#new_user_form').serialize(),
|
14
|
+
success: Caboose.ajax_success,
|
15
|
+
error: Caboose.ajax_error
|
16
|
+
});
|
17
|
+
};
|
18
|
+
|
19
|
+
Caboose.User.delete = function(user_id, confirm)
|
20
|
+
{
|
21
|
+
if (!confirm)
|
22
|
+
{
|
23
|
+
Caboose.confirm({
|
24
|
+
message: "Are you sure you want to delete the user? This can't be undone.",
|
25
|
+
yes: function() { Caboose.User.delete(user_id, true) }
|
26
|
+
});
|
27
|
+
return;
|
28
|
+
}
|
29
|
+
$('#message').html("<p class='loading'>Deleting user...</p>");
|
30
|
+
|
31
|
+
$.ajax({
|
32
|
+
url: '/users/' + user_id,
|
33
|
+
type: 'delete',
|
34
|
+
success: Caboose.ajax_success,
|
35
|
+
error: Caboose.ajax_error
|
36
|
+
});
|
37
|
+
};
|
38
|
+
*/
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require caboose_before
|
12
|
+
*= require model
|
13
|
+
*= require caboose/caboose
|
14
|
+
*= require caboose_after
|
15
|
+
*/
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
body {
|
3
|
+
font-family: Helvetica, Tahoma, Arial;
|
4
|
+
}
|
5
|
+
|
6
|
+
#wrapper {
|
7
|
+
width: 960px;
|
8
|
+
}
|
9
|
+
|
10
|
+
.page_links {
|
11
|
+
|
12
|
+
}
|
13
|
+
|
14
|
+
.page_links a {
|
15
|
+
display: inline-block;
|
16
|
+
padding: 4px 8px;
|
17
|
+
border: #efefef 1px solid;
|
18
|
+
}
|
19
|
+
|
20
|
+
.page_links .middle_links a {
|
21
|
+
|
22
|
+
}
|
23
|
+
|
24
|
+
.page_links span.current_page {
|
25
|
+
display: inline-block;
|
26
|
+
padding: 4px 8px;
|
27
|
+
font-weight: bold;
|
28
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module Caboose
|
3
|
+
class AdminController < ApplicationController
|
4
|
+
|
5
|
+
# GET /admin
|
6
|
+
def index
|
7
|
+
return if !user_is_allowed('admin', 'view')
|
8
|
+
|
9
|
+
@mods = [
|
10
|
+
{ 'href' => '/admin/users' , 'text' => 'Users' },
|
11
|
+
{ 'href' => '/admin/roles' , 'text' => 'Roles' },
|
12
|
+
{ 'href' => '/admin/permissions' , 'text' => 'Permissions' }
|
13
|
+
]
|
14
|
+
@mods = Caboose.plugin_hook('admin_nav', @mods)
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Caboose
|
2
|
+
class ApplicationController < ActionController::Base
|
3
|
+
|
4
|
+
protect_from_forgery
|
5
|
+
before_filter :before_before_action
|
6
|
+
|
7
|
+
def before_before_action
|
8
|
+
|
9
|
+
# Try to find the page
|
10
|
+
@page = Page.page_with_uri(request.fullpath)
|
11
|
+
|
12
|
+
session['use_redirect_urls'] = true if session['use_redirect_urls'].nil?
|
13
|
+
|
14
|
+
@crumb_trail = Caboose::Page.crumb_trail(@page)
|
15
|
+
@subnav = {}
|
16
|
+
@actions = {}
|
17
|
+
@tasks = {}
|
18
|
+
@page_tasks = {}
|
19
|
+
@is_real_page = false
|
20
|
+
|
21
|
+
# Sets an instance variable of the logged in user
|
22
|
+
@logged_in_user = logged_in_user
|
23
|
+
|
24
|
+
before_action
|
25
|
+
end
|
26
|
+
|
27
|
+
# To be overridden by the child controllers
|
28
|
+
def before_action
|
29
|
+
end
|
30
|
+
|
31
|
+
# Logs in a user
|
32
|
+
def login_user(user)
|
33
|
+
session["app_user"] = user
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns whether or not a user is logged in
|
37
|
+
def logged_in?
|
38
|
+
#return true if !session["app_user"].nil? && session["app_user"].id != -1
|
39
|
+
validate_token
|
40
|
+
return true if !session["app_user"].nil? && session["app_user"].id != -1
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
|
44
|
+
# Checks to see if a token is given. If so, it tries to validate the token
|
45
|
+
# and log the user in.
|
46
|
+
def validate_token
|
47
|
+
token = params[:token]
|
48
|
+
return false if token.nil?
|
49
|
+
|
50
|
+
user = User.validate_token(token)
|
51
|
+
return false if user.nil?
|
52
|
+
|
53
|
+
login_user(user)
|
54
|
+
return true
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns the currently logged in user
|
58
|
+
def logged_in_user
|
59
|
+
if (!logged_in?)
|
60
|
+
return User.find(User::LOGGED_OUT_USER_ID)
|
61
|
+
end
|
62
|
+
#return nil if !logged_in?
|
63
|
+
return session["app_user"]
|
64
|
+
end
|
65
|
+
|
66
|
+
# Checks to see if a user has permission to perform the given action
|
67
|
+
# on the given resource.
|
68
|
+
# Redirects to login if not logged in.
|
69
|
+
# Redirects to error page with message if not allowed.
|
70
|
+
def user_is_allowed(resource, action)
|
71
|
+
if (!logged_in?)
|
72
|
+
redirect_to "/login?return_url=" + URI.encode(request.fullpath)
|
73
|
+
return
|
74
|
+
end
|
75
|
+
|
76
|
+
@user = logged_in_user
|
77
|
+
if (!@user.is_allowed(resource, action))
|
78
|
+
@error = "You don't have permission to " + action + " " + resource
|
79
|
+
render :template => "caboose/extras/error"
|
80
|
+
return false
|
81
|
+
end
|
82
|
+
|
83
|
+
return true
|
84
|
+
end
|
85
|
+
|
86
|
+
# Removes a given parameter from a URL querystring
|
87
|
+
def reject_param(url, param)
|
88
|
+
arr = url.split('?')
|
89
|
+
return url if (arr.count == 1)
|
90
|
+
qs = arr[1].split('&').reject { |pair| pair.split(/[=;]/).first == param }
|
91
|
+
url2 = arr[0]
|
92
|
+
url2 += "?" + qs.join('&') if qs.count > 0
|
93
|
+
return url2
|
94
|
+
end
|
95
|
+
|
96
|
+
#def auth_or_error(message)
|
97
|
+
# if (!logged_in?)
|
98
|
+
# redirect_to "/login?return_url=#{request.request_uri}" and return false
|
99
|
+
# end
|
100
|
+
# redirect_to "/error?message=#{message}"
|
101
|
+
#end
|
102
|
+
|
103
|
+
def var(key)
|
104
|
+
v = Var.where(:key => key).first
|
105
|
+
return "" if v.nil?
|
106
|
+
return v.val
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Caboose
|
2
|
+
class LoginController < Caboose::ApplicationController
|
3
|
+
|
4
|
+
# GET /login
|
5
|
+
def index
|
6
|
+
@return_url = params[:return_url].nil? ? "/" : params[:return_url];
|
7
|
+
redirect_to @return_url if logged_in?
|
8
|
+
end
|
9
|
+
|
10
|
+
# POST /login
|
11
|
+
def login
|
12
|
+
|
13
|
+
@resp = StdClass.new('error' => '', 'redirect' => '')
|
14
|
+
@return_url = params[:return_url].nil? ? "/" : params[:return_url]
|
15
|
+
|
16
|
+
if (logged_in?)
|
17
|
+
@resp.error = "Already logged in"
|
18
|
+
else
|
19
|
+
@username = params[:username]
|
20
|
+
@password = params[:password]
|
21
|
+
|
22
|
+
if (@username.nil? || @password.nil? || @password.strip.length == 0)
|
23
|
+
@resp.error = "Invalid credentials"
|
24
|
+
else
|
25
|
+
|
26
|
+
@password = Digest::SHA1.hexdigest(Caboose::salt + @password)
|
27
|
+
user = User.where(:username => @username, :password => @password).first
|
28
|
+
|
29
|
+
if (user.nil?)
|
30
|
+
@resp.error = "Invalid credentials"
|
31
|
+
else
|
32
|
+
login_user(user)
|
33
|
+
@resp.redirect = @return_url
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
render json: @resp
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,304 @@
|
|
1
|
+
|
2
|
+
module Caboose
|
3
|
+
class PagesController < ApplicationController
|
4
|
+
|
5
|
+
def before_action
|
6
|
+
@page = Page.page_with_uri('/admin')
|
7
|
+
end
|
8
|
+
|
9
|
+
# GET /pages
|
10
|
+
def index
|
11
|
+
end
|
12
|
+
|
13
|
+
# GET /pages/:id
|
14
|
+
def show
|
15
|
+
|
16
|
+
# Find the page with an exact URI match
|
17
|
+
page = Page.page_with_uri(request.fullpath, false)
|
18
|
+
Caboose.log(page)
|
19
|
+
|
20
|
+
if (!page)
|
21
|
+
asset
|
22
|
+
return
|
23
|
+
end
|
24
|
+
|
25
|
+
user = logged_in_user
|
26
|
+
if (!user.is_allowed(page, 'view'))
|
27
|
+
if (user.id == User.LOGGED_OUT_USER_ID)
|
28
|
+
redirect_to "/login?return_url=" + URI.encode(request.fullpath)
|
29
|
+
return
|
30
|
+
else
|
31
|
+
page.title = 'Access Denied'
|
32
|
+
page.content = "<p class='note error'>You do not have access to view this page.</p>"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
if (session['use_redirect_urls'] && !page.redirect_url.nil? && page.redirect_url.strip.length > 0)
|
37
|
+
redirect_to page.redirect_url
|
38
|
+
return
|
39
|
+
end
|
40
|
+
|
41
|
+
page.content = Caboose.plugin_hook('page_content', page.content)
|
42
|
+
@page = page
|
43
|
+
@user = user
|
44
|
+
is_admin = @user.is_allowed('all', 'all')
|
45
|
+
|
46
|
+
@crumb_trail = Caboose::Page.crumb_trail(@page)
|
47
|
+
@subnav = Caboose::Page.subnav(@page, session['use_redirect_urls'], @user)
|
48
|
+
@actions = Caboose::Page.permissible_actions(@user.id, @page.id)
|
49
|
+
@tasks = {}
|
50
|
+
@page_tasks = {}
|
51
|
+
|
52
|
+
if (@actions.include?('edit') || is_admin)
|
53
|
+
@page_tasks["/pages/#{@page.id}/sitemap"] = 'Site Map This Page'
|
54
|
+
@page_tasks["/pages/#{@page.id}/edit"] = 'Edit Page Content'
|
55
|
+
@page_tasks["/pages/#{@page.id}/edit-settings"] = 'Edit Page Settings'
|
56
|
+
end
|
57
|
+
if (@user.is_allowed('pages', 'add') || is_admin)
|
58
|
+
@page_tasks["/pages/new?parent_id=#{@page.id}"] = 'New Page'
|
59
|
+
end
|
60
|
+
|
61
|
+
#@subnav.links = @tasks.collect {|href, task| {'href' => href, 'text' => task, 'is_current' => uri == href}}
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
def asset
|
66
|
+
|
67
|
+
uri = uri.to_s.gsub(/^(.*?)\?.*?$/, '\1')
|
68
|
+
uri.chop! if uri.end_with?('/')
|
69
|
+
uri[0] = '' if uri.starts_with?('/')
|
70
|
+
|
71
|
+
page = Page.page_with_uri(File.dirname(uri), false)
|
72
|
+
if (page.nil? || !page)
|
73
|
+
render :file => "caboose/extras/error404", :layout => "caboose/error404"
|
74
|
+
return
|
75
|
+
end
|
76
|
+
|
77
|
+
asset = Asset.where(:page_id => page.id, :filename => File.basename(uri)).first
|
78
|
+
if (asset.nil?)
|
79
|
+
render :file => "caboose/extras/error404", :layout => "caboose/error404"
|
80
|
+
return
|
81
|
+
end
|
82
|
+
|
83
|
+
user = logged_in_user
|
84
|
+
if (!Page.is_allowed(user, asset.page_id, 'view'))
|
85
|
+
render "caboose/pages/asset_no_permission"
|
86
|
+
return
|
87
|
+
end
|
88
|
+
|
89
|
+
Caboose.log(Caboose::assets_path, 'Caboose::assets_path')
|
90
|
+
path = Caboose::assets_path.join("#{asset.id}.#{asset.extension}")
|
91
|
+
Caboose.log("Sending asset #{path}")
|
92
|
+
#send_file(path)
|
93
|
+
#send_file(path, :filename => "your_document.pdf", :type => "application/pdf")
|
94
|
+
|
95
|
+
#
|
96
|
+
#$path = ASSETS_PATH ."/". $asset->id .".". $asset->extension
|
97
|
+
#
|
98
|
+
#$finfo = finfo_open(FILEINFO_MIME_TYPE) // return mime type ala mimetype extension
|
99
|
+
#$mime = finfo_file($finfo, $path)
|
100
|
+
#finfo_close($finfo)
|
101
|
+
#
|
102
|
+
#header("X-Sendfile: $path")
|
103
|
+
#header("Content-Type: $mime")
|
104
|
+
#header("Content-Disposition: inline filename=\"$asset->filename\"")
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
# GET /pages/new
|
109
|
+
def new
|
110
|
+
return if !user_is_allowed('pages', 'add')
|
111
|
+
@pages = Page.new
|
112
|
+
@parent_id = params[:parent_id].nil? ? params[:parent_id] : -1
|
113
|
+
render :layout => 'caboose/caboose'
|
114
|
+
end
|
115
|
+
|
116
|
+
# GET /pages/1/edit
|
117
|
+
def edit
|
118
|
+
return if !user_is_allowed('pages', 'edit')
|
119
|
+
@page = Page.find(params[:id])
|
120
|
+
render :layout => 'caboose/caboose'
|
121
|
+
end
|
122
|
+
|
123
|
+
# POST /pages
|
124
|
+
def create
|
125
|
+
return if !user_is_allowed('pages', 'add')
|
126
|
+
|
127
|
+
resp = Caboose::StdClass.new({
|
128
|
+
'error' => nil,
|
129
|
+
'redirect' => nil
|
130
|
+
})
|
131
|
+
|
132
|
+
parent_id = params[:parent_id]
|
133
|
+
title = params[:title]
|
134
|
+
|
135
|
+
if (title.strip.length == 0)
|
136
|
+
resp.error = "A page title is required."
|
137
|
+
elsif (!logged_in_user.is_allowed('all', 'all') &&
|
138
|
+
!Page.page_ids_with_permission(logged_in_user, 'edit' ).include?(parent_id) &&
|
139
|
+
!Page.page_ids_with_permission(logged_in_user, 'approve').include?(parent_id))
|
140
|
+
resp.error = "You don't have permission to add a page there."
|
141
|
+
end
|
142
|
+
if (!resp.error.nil?)
|
143
|
+
render json: resp
|
144
|
+
return
|
145
|
+
end
|
146
|
+
|
147
|
+
parent = Caboose::Page.find(parent_id)
|
148
|
+
|
149
|
+
page = Caboose::Page.new
|
150
|
+
page.title = title
|
151
|
+
page.parent_id = parent_id
|
152
|
+
page.hide = true
|
153
|
+
page.content_format = Caboose::Page::CONTENT_FORMAT_HTML
|
154
|
+
|
155
|
+
i = 0
|
156
|
+
begin
|
157
|
+
page.slug = Page.slug(page.title + (i > 0 ? " #{i}" : ""))
|
158
|
+
page.uri = parent.parent_id == -1 ? page.slug : "#{parent.uri}/#{page.slug}"
|
159
|
+
i = i+1
|
160
|
+
end while (Page.where(:uri => page.uri).count > 0 && i < 10)
|
161
|
+
|
162
|
+
page.save
|
163
|
+
|
164
|
+
# Set the new page's permissions
|
165
|
+
viewers = Caboose::PagePermission.where({ :page_id => parent.id, :action => 'view' }).pluck(:role_id)
|
166
|
+
editors = Caboose::PagePermission.where({ :page_id => parent.id, :action => 'edit' }).pluck(:role_id)
|
167
|
+
Caboose::Page.update_authorized_for_action(page.id, 'view', viewers)
|
168
|
+
Caboose::Page.update_authorized_for_action(page.id, 'edit', editors)
|
169
|
+
|
170
|
+
# Send back the response
|
171
|
+
resp.redirect = "/pages/#{page.id}/edit"
|
172
|
+
render json: resp
|
173
|
+
end
|
174
|
+
|
175
|
+
# PUT /pages/1
|
176
|
+
def update
|
177
|
+
return if !user_is_allowed('pages', 'edit')
|
178
|
+
|
179
|
+
resp = StdClass.new({'attributes' => {}})
|
180
|
+
page = Page.find(params[:id])
|
181
|
+
|
182
|
+
save = true
|
183
|
+
user = logged_in_user
|
184
|
+
params.each do |name,value|
|
185
|
+
case name
|
186
|
+
when 'parent_id'
|
187
|
+
if (page.id == value)
|
188
|
+
resp.error = "The page's parent cannot be itself."
|
189
|
+
elsif (Page.is_child(page.id, value))
|
190
|
+
resp.error = "You can't set the current page's parent to be one of its child pages."
|
191
|
+
elsif (value != page.parent_id)
|
192
|
+
p = Page.find(value)
|
193
|
+
if (!user.is_allowed(p, 'edit'))
|
194
|
+
resp.error = "You don't have access to put the current page there."
|
195
|
+
end
|
196
|
+
end
|
197
|
+
if (resp.error.length > 0)
|
198
|
+
save = false
|
199
|
+
else
|
200
|
+
parent = Page.find(value)
|
201
|
+
Page.update_parent(page.id, value)
|
202
|
+
resp.attributes['parent_id'] = { 'text' => parent.title }
|
203
|
+
end
|
204
|
+
|
205
|
+
when 'title', 'menu_title', 'alias', 'redirect_url', 'hide',
|
206
|
+
'content_format', 'custom_css', 'custom_js', 'layout',
|
207
|
+
'seo_title', 'meta_description', 'fb_description', 'gp_description', 'canonical_url'
|
208
|
+
|
209
|
+
page[name.to_sym] = value
|
210
|
+
|
211
|
+
when 'meta_robots'
|
212
|
+
if (value.include?('index') && value.include?('noindex'))
|
213
|
+
resp.error = "You can't have both index and noindex"
|
214
|
+
save = false
|
215
|
+
elsif (value.include?('follow') && value.include?('nofollow'))
|
216
|
+
resp.error = "You can't have both follow and nofollow"
|
217
|
+
save = false
|
218
|
+
else
|
219
|
+
page.meta_robots = value.join(', ')
|
220
|
+
resp.attributes['meta_robots'] = { 'text' => page.meta_robots }
|
221
|
+
end
|
222
|
+
|
223
|
+
when 'content'
|
224
|
+
page.content = value.strip.gsub(/<meta.*?>/, '').gsub(/<link.*?>/, '').gsub(/\<\!--[\S\s]*?--\>/, '')
|
225
|
+
|
226
|
+
when 'slug'
|
227
|
+
page.slug = Page.slug(value.strip.length > 0 ? value : page.title)
|
228
|
+
resp.attributes['slug'] = { 'value' => page.slug }
|
229
|
+
|
230
|
+
when 'custom_sort_children'
|
231
|
+
if (value == 0)
|
232
|
+
page.children.each do |p|
|
233
|
+
p.sort_order = 1
|
234
|
+
p.save
|
235
|
+
end
|
236
|
+
end
|
237
|
+
page.custom_sort_children = value
|
238
|
+
|
239
|
+
when 'viewers'
|
240
|
+
Page.update_authorized_for_action(page.id, 'view', value)
|
241
|
+
when 'editors'
|
242
|
+
Page.update_authorized_for_action(page.id, 'edit', value)
|
243
|
+
when 'approvers'
|
244
|
+
Page.update_authorized_for_action(page.id, 'approve', value)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
resp.success = save && page.save
|
249
|
+
render json: resp
|
250
|
+
end
|
251
|
+
|
252
|
+
# DELETE /pages/1
|
253
|
+
def destroy
|
254
|
+
return if !user_is_allowed('pages', 'delete')
|
255
|
+
user = Page.find(params[:id])
|
256
|
+
user.destroy
|
257
|
+
|
258
|
+
resp = StdClass.new({
|
259
|
+
'redirect' => '/pages'
|
260
|
+
})
|
261
|
+
render json: resp
|
262
|
+
end
|
263
|
+
|
264
|
+
def sitemap_options
|
265
|
+
parent_id = params[:parent_id]
|
266
|
+
top_page = Page.index_page
|
267
|
+
p = !parent_id.nil? ? Page.find(parent_id) : top_page
|
268
|
+
options = []
|
269
|
+
sitemap_helper(top_page, options)
|
270
|
+
|
271
|
+
render json: options
|
272
|
+
end
|
273
|
+
|
274
|
+
def sitemap_helper(page, options, prefix = '')
|
275
|
+
options << { 'value' => page.id, 'text' => prefix + page.title }
|
276
|
+
page.children.each do |kid|
|
277
|
+
sitemap_helper(kid, options, prefix + ' - ')
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def robots_options
|
282
|
+
options = [
|
283
|
+
{ 'value' => 'index' , 'text' => 'index' },
|
284
|
+
{ 'value' => 'noindex' , 'text' => 'noindex' },
|
285
|
+
{ 'value' => 'follow' , 'text' => 'follow' },
|
286
|
+
{ 'value' => 'nofollow' , 'text' => 'nofollow' },
|
287
|
+
{ 'value' => 'nosnippet' , 'text' => 'nosnippet' },
|
288
|
+
{ 'value' => 'noodp' , 'text' => 'noodp' },
|
289
|
+
{ 'value' => 'noarchive' , 'text' => 'noarchive' }
|
290
|
+
]
|
291
|
+
render json: options
|
292
|
+
end
|
293
|
+
|
294
|
+
def content_format_options
|
295
|
+
options = [
|
296
|
+
{ 'value' => 'html', 'text' => 'html' },
|
297
|
+
{ 'value' => 'text', 'text' => 'text' },
|
298
|
+
{ 'value' => 'ruby', 'text' => 'ruby' }
|
299
|
+
]
|
300
|
+
render json: options
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
304
|
+
end
|