tennpipes-su 3.6.6
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.
- checksums.yaml +7 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +70 -0
- data/Rakefile +22 -0
- data/lib/tennpipes-su.rb +35 -0
- data/lib/tennpipes-su/access_control.rb +191 -0
- data/lib/tennpipes-su/bootstrap-less/alerts.less +67 -0
- data/lib/tennpipes-su/bootstrap-less/badges.less +55 -0
- data/lib/tennpipes-su/bootstrap-less/bootstrap.less +49 -0
- data/lib/tennpipes-su/bootstrap-less/breadcrumbs.less +26 -0
- data/lib/tennpipes-su/bootstrap-less/button-groups.less +226 -0
- data/lib/tennpipes-su/bootstrap-less/buttons.less +155 -0
- data/lib/tennpipes-su/bootstrap-less/carousel.less +232 -0
- data/lib/tennpipes-su/bootstrap-less/close.less +33 -0
- data/lib/tennpipes-su/bootstrap-less/code.less +63 -0
- data/lib/tennpipes-su/bootstrap-less/component-animations.less +29 -0
- data/lib/tennpipes-su/bootstrap-less/dropdowns.less +213 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/bordered-pulled.less +16 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/core.less +12 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/fixed-width.less +6 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/font-awesome.less +17 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/icons.less +412 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/larger.less +13 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/list.less +19 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/mixins.less +20 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/path.less +14 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/rotated-flipped.less +9 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/spinning.less +30 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/stacked.less +20 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/variables.less +381 -0
- data/lib/tennpipes-su/bootstrap-less/forms.less +419 -0
- data/lib/tennpipes-su/bootstrap-less/glyphicons.less +233 -0
- data/lib/tennpipes-su/bootstrap-less/grid.less +100 -0
- data/lib/tennpipes-su/bootstrap-less/input-groups.less +157 -0
- data/lib/tennpipes-su/bootstrap-less/jumbotron.less +44 -0
- data/lib/tennpipes-su/bootstrap-less/labels.less +64 -0
- data/lib/tennpipes-su/bootstrap-less/list-group.less +110 -0
- data/lib/tennpipes-su/bootstrap-less/media.less +56 -0
- data/lib/tennpipes-su/bootstrap-less/mixins.less +926 -0
- data/lib/tennpipes-su/bootstrap-less/modals.less +138 -0
- data/lib/tennpipes-su/bootstrap-less/navbar.less +616 -0
- data/lib/tennpipes-su/bootstrap-less/navs.less +242 -0
- data/lib/tennpipes-su/bootstrap-less/normalize.less +423 -0
- data/lib/tennpipes-su/bootstrap-less/pager.less +55 -0
- data/lib/tennpipes-su/bootstrap-less/pagination.less +88 -0
- data/lib/tennpipes-su/bootstrap-less/panels.less +230 -0
- data/lib/tennpipes-su/bootstrap-less/popovers.less +133 -0
- data/lib/tennpipes-su/bootstrap-less/print.less +101 -0
- data/lib/tennpipes-su/bootstrap-less/progress-bars.less +80 -0
- data/lib/tennpipes-su/bootstrap-less/responsive-utilities.less +93 -0
- data/lib/tennpipes-su/bootstrap-less/scaffolding.less +134 -0
- data/lib/tennpipes-su/bootstrap-less/tables.less +233 -0
- data/lib/tennpipes-su/bootstrap-less/tennpipes-su.less +18 -0
- data/lib/tennpipes-su/bootstrap-less/theme.less +247 -0
- data/lib/tennpipes-su/bootstrap-less/thumbnails.less +36 -0
- data/lib/tennpipes-su/bootstrap-less/tooltip.less +95 -0
- data/lib/tennpipes-su/bootstrap-less/type.less +296 -0
- data/lib/tennpipes-su/bootstrap-less/utilities.less +56 -0
- data/lib/tennpipes-su/bootstrap-less/variables.less +827 -0
- data/lib/tennpipes-su/bootstrap-less/wells.less +29 -0
- data/lib/tennpipes-su/generators/actions.rb +78 -0
- data/lib/tennpipes-su/generators/admin_app.rb +169 -0
- data/lib/tennpipes-su/generators/admin_page.rb +68 -0
- data/lib/tennpipes-su/generators/orm.rb +172 -0
- data/lib/tennpipes-su/generators/templates/account/activerecord.rb.tt +41 -0
- data/lib/tennpipes-su/generators/templates/account/couchrest.rb.tt +67 -0
- data/lib/tennpipes-su/generators/templates/account/datamapper.rb.tt +56 -0
- data/lib/tennpipes-su/generators/templates/account/dynamoid.rb.tt +55 -0
- data/lib/tennpipes-su/generators/templates/account/minirecord.rb.tt +44 -0
- data/lib/tennpipes-su/generators/templates/account/mongoid.rb.tt +54 -0
- data/lib/tennpipes-su/generators/templates/account/mongomapper.rb.tt +47 -0
- data/lib/tennpipes-su/generators/templates/account/ohm.rb.tt +70 -0
- data/lib/tennpipes-su/generators/templates/account/seeds.rb.tt +29 -0
- data/lib/tennpipes-su/generators/templates/account/sequel.rb.tt +53 -0
- data/lib/tennpipes-su/generators/templates/app.rb.tt +42 -0
- data/lib/tennpipes-su/generators/templates/app/controllers/base.rb.tt +5 -0
- data/lib/tennpipes-su/generators/templates/app/controllers/sessions.rb.tt +29 -0
- data/lib/tennpipes-su/generators/templates/assets/images/favicon.ico +0 -0
- data/lib/tennpipes-su/generators/templates/assets/images/font/FontAwesome.otf +0 -0
- data/lib/tennpipes-su/generators/templates/assets/images/font/fontawesome-webfont.eot +0 -0
- data/lib/tennpipes-su/generators/templates/assets/images/font/fontawesome-webfont.svg +414 -0
- data/lib/tennpipes-su/generators/templates/assets/images/font/fontawesome-webfont.ttf +0 -0
- data/lib/tennpipes-su/generators/templates/assets/images/font/fontawesome-webfont.woff +0 -0
- data/lib/tennpipes-su/generators/templates/assets/images/logo.png +0 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/application.js +118 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/affix.js +137 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/alert.js +88 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/bootstrap.min.js +6 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/button.js +107 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/carousel.js +205 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/collapse.js +170 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/dropdown.js +147 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/modal.js +243 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/popover.js +110 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/scrollspy.js +153 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/tab.js +125 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/tooltip.js +399 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/transition.js +48 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/jquery-1.11.0.min.js +4 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/application.css +353 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/bootstrap.css +4 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/fonts/FontAwesome.otf +0 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/fonts/fontawesome-webfont.eot +0 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/fonts/fontawesome-webfont.svg +414 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/fonts/fontawesome-webfont.ttf +0 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/fonts/fontawesome-webfont.woff +0 -0
- data/lib/tennpipes-su/generators/templates/erb/app/base/index.erb.tt +15 -0
- data/lib/tennpipes-su/generators/templates/erb/app/errors/403.erb.tt +3 -0
- data/lib/tennpipes-su/generators/templates/erb/app/errors/404.erb.tt +3 -0
- data/lib/tennpipes-su/generators/templates/erb/app/errors/500.erb.tt +3 -0
- data/lib/tennpipes-su/generators/templates/erb/app/layouts/application.erb.tt +64 -0
- data/lib/tennpipes-su/generators/templates/erb/app/layouts/error.erb.tt +23 -0
- data/lib/tennpipes-su/generators/templates/erb/app/sessions/new.erb.tt +44 -0
- data/lib/tennpipes-su/generators/templates/erb/page/_form.erb.tt +18 -0
- data/lib/tennpipes-su/generators/templates/erb/page/edit.erb.tt +10 -0
- data/lib/tennpipes-su/generators/templates/erb/page/index.erb.tt +81 -0
- data/lib/tennpipes-su/generators/templates/erb/page/new.erb.tt +9 -0
- data/lib/tennpipes-su/generators/templates/haml/app/base/index.haml.tt +12 -0
- data/lib/tennpipes-su/generators/templates/haml/app/errors/403.haml.tt +3 -0
- data/lib/tennpipes-su/generators/templates/haml/app/errors/404.haml.tt +3 -0
- data/lib/tennpipes-su/generators/templates/haml/app/errors/500.haml.tt +3 -0
- data/lib/tennpipes-su/generators/templates/haml/app/layouts/application.haml.tt +49 -0
- data/lib/tennpipes-su/generators/templates/haml/app/layouts/error.haml.tt +18 -0
- data/lib/tennpipes-su/generators/templates/haml/app/sessions/new.haml.tt +38 -0
- data/lib/tennpipes-su/generators/templates/haml/page/_form.haml.tt +16 -0
- data/lib/tennpipes-su/generators/templates/haml/page/edit.haml.tt +8 -0
- data/lib/tennpipes-su/generators/templates/haml/page/index.haml.tt +58 -0
- data/lib/tennpipes-su/generators/templates/haml/page/new.haml.tt +7 -0
- data/lib/tennpipes-su/generators/templates/page/controller.rb.tt +92 -0
- data/lib/tennpipes-su/generators/templates/slim/app/base/index.slim.tt +12 -0
- data/lib/tennpipes-su/generators/templates/slim/app/errors/403.slim.tt +3 -0
- data/lib/tennpipes-su/generators/templates/slim/app/errors/404.slim.tt +3 -0
- data/lib/tennpipes-su/generators/templates/slim/app/errors/500.slim.tt +3 -0
- data/lib/tennpipes-su/generators/templates/slim/app/layouts/application.slim.tt +48 -0
- data/lib/tennpipes-su/generators/templates/slim/app/layouts/error.slim.tt +19 -0
- data/lib/tennpipes-su/generators/templates/slim/app/sessions/new.slim.tt +37 -0
- data/lib/tennpipes-su/generators/templates/slim/page/_form.slim.tt +16 -0
- data/lib/tennpipes-su/generators/templates/slim/page/edit.slim.tt +8 -0
- data/lib/tennpipes-su/generators/templates/slim/page/index.slim.tt +56 -0
- data/lib/tennpipes-su/generators/templates/slim/page/new.slim.tt +7 -0
- data/lib/tennpipes-su/helpers/authentication_helpers.rb +108 -0
- data/lib/tennpipes-su/helpers/view_helpers.rb +87 -0
- data/lib/tennpipes-su/locale/admin/cs.yml +56 -0
- data/lib/tennpipes-su/locale/admin/da.yml +56 -0
- data/lib/tennpipes-su/locale/admin/de.yml +56 -0
- data/lib/tennpipes-su/locale/admin/en.yml +56 -0
- data/lib/tennpipes-su/locale/admin/es.yml +56 -0
- data/lib/tennpipes-su/locale/admin/fr.yml +56 -0
- data/lib/tennpipes-su/locale/admin/hu.yml +56 -0
- data/lib/tennpipes-su/locale/admin/it.yml +56 -0
- data/lib/tennpipes-su/locale/admin/ja.yml +57 -0
- data/lib/tennpipes-su/locale/admin/lv.yml +56 -0
- data/lib/tennpipes-su/locale/admin/nl.yml +56 -0
- data/lib/tennpipes-su/locale/admin/no.yml +56 -0
- data/lib/tennpipes-su/locale/admin/pl.yml +56 -0
- data/lib/tennpipes-su/locale/admin/pt_br.yml +56 -0
- data/lib/tennpipes-su/locale/admin/ro.yml +56 -0
- data/lib/tennpipes-su/locale/admin/ru.yml +57 -0
- data/lib/tennpipes-su/locale/admin/sv.yml +56 -0
- data/lib/tennpipes-su/locale/admin/tr.yml +56 -0
- data/lib/tennpipes-su/locale/admin/uk.yml +56 -0
- data/lib/tennpipes-su/locale/admin/zh_cn.yml +56 -0
- data/lib/tennpipes-su/locale/admin/zh_tw.yml +56 -0
- data/lib/tennpipes-su/locale/orm/cs.yml +12 -0
- data/lib/tennpipes-su/locale/orm/da.yml +12 -0
- data/lib/tennpipes-su/locale/orm/de.yml +12 -0
- data/lib/tennpipes-su/locale/orm/en.yml +12 -0
- data/lib/tennpipes-su/locale/orm/es.yml +12 -0
- data/lib/tennpipes-su/locale/orm/fr.yml +12 -0
- data/lib/tennpipes-su/locale/orm/hu.yml +12 -0
- data/lib/tennpipes-su/locale/orm/it.yml +12 -0
- data/lib/tennpipes-su/locale/orm/ja.yml +12 -0
- data/lib/tennpipes-su/locale/orm/lv.yml +12 -0
- data/lib/tennpipes-su/locale/orm/nl.yml +12 -0
- data/lib/tennpipes-su/locale/orm/no.yml +12 -0
- data/lib/tennpipes-su/locale/orm/pl.yml +38 -0
- data/lib/tennpipes-su/locale/orm/pt_br.yml +12 -0
- data/lib/tennpipes-su/locale/orm/ro.yml +12 -0
- data/lib/tennpipes-su/locale/orm/ru.yml +12 -0
- data/lib/tennpipes-su/locale/orm/sv.yml +12 -0
- data/lib/tennpipes-su/locale/orm/tr.yml +12 -0
- data/lib/tennpipes-su/locale/orm/uk.yml +12 -0
- data/lib/tennpipes-su/locale/orm/zh_cn.yml +12 -0
- data/lib/tennpipes-su/locale/orm/zh_tw.yml +12 -0
- data/test/fixtures/sequel.rb +72 -0
- data/test/generators/test_account_model_generator.rb +108 -0
- data/test/generators/test_admin_app_generator.rb +218 -0
- data/test/generators/test_admin_page_generator.rb +140 -0
- data/test/helper.rb +47 -0
- data/test/test_admin_application.rb +271 -0
- data/test/test_locale.rb +25 -0
- metadata +298 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 2f16940e31b9ad4b9b92fd7e6948d28e7f1964ef
|
|
4
|
+
data.tar.gz: 0f5eacef6b66f385b8b03d6ff8cc2042162b895d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 37fc640cacbcd194b278da8e2434b2683e7b4548c9822b2bcbeadbbbaf57930300436c00c2b169d8199c9bcd8a7f949deda63764b0168735b81c8ffb43cb5158
|
|
7
|
+
data.tar.gz: bfe1b70f59e5363062f1bf81acec7f0a818b6e0619349e778490cf4b083be09a1c25f682103b3dd6348e04ed271eaebda140309b38a36e93c23173450b765e19
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2011 Tennpipes
|
|
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.rdoc
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
= Admin Dashboard and Authentication (tennpipes-su)
|
|
2
|
+
|
|
3
|
+
=== Overview
|
|
4
|
+
|
|
5
|
+
Tennpipes has a beautiful Admin management dashboard with these features:
|
|
6
|
+
|
|
7
|
+
Orm Agnostic:: Data Adapters for Datamapper, Activerecord, Sequel, Mongomapper, Mongoid, Couchrest, Dynamoid
|
|
8
|
+
Template Agnostic:: Erb, Erubis and Haml Renderer
|
|
9
|
+
Authentication:: Support for Account authentication, Account Permission management
|
|
10
|
+
Scaffold:: You can simply create a new "admin interface" by providing a Model
|
|
11
|
+
Access Control:: Supports authentication and role permissions for your application
|
|
12
|
+
|
|
13
|
+
=== Admin Dashboard Usage
|
|
14
|
+
|
|
15
|
+
For a complete look at usage of the Admin dashboard functionality, be sure to check out the
|
|
16
|
+
{Tennpipes Admin}[http://www.tennpipesrb.com/guides/tennpipes-su] guide.
|
|
17
|
+
|
|
18
|
+
Create a new project:
|
|
19
|
+
|
|
20
|
+
$ tennpipes-init project demo
|
|
21
|
+
$ cd demo
|
|
22
|
+
|
|
23
|
+
Create the admin subapplication:
|
|
24
|
+
|
|
25
|
+
demo$ tennpipes-init admin
|
|
26
|
+
|
|
27
|
+
Next, follow the admin setup steps:
|
|
28
|
+
|
|
29
|
+
* configure your <tt>config/database.rb</tt> to connect to the correct data.
|
|
30
|
+
* run <tt>tennpipes rake dm:migrate</tt> # or ar:migrate if you use activerecord
|
|
31
|
+
* run <tt>tennpipes rake seed</tt>
|
|
32
|
+
|
|
33
|
+
Your admin panel now is ready and you can start your server with <tt>tennpipes start</tt> and point your browser to <tt>/admin</tt>!
|
|
34
|
+
|
|
35
|
+
To create a new "scaffold" you need to provide only a Model name to the command:
|
|
36
|
+
|
|
37
|
+
demo$ tennpipes-init model post --skip-migration # edit your post.rb model and add some fields
|
|
38
|
+
demo$ tennpipes-init rake dm:auto:migrate
|
|
39
|
+
demo$ tennpipes-init admin_page post
|
|
40
|
+
demo$ tennpipes start # and go to http://localhost:3000/admin
|
|
41
|
+
|
|
42
|
+
That's all!!
|
|
43
|
+
|
|
44
|
+
=== Admin Access Control
|
|
45
|
+
|
|
46
|
+
Tennpipes Admin use a model Account for manage role, membership and permissions.
|
|
47
|
+
|
|
48
|
+
For an ecommerce website, usually certain actions require permissions and authentication. This is supported
|
|
49
|
+
by the admin access control features:
|
|
50
|
+
|
|
51
|
+
class EcommerceSite < Tennpipes::Application
|
|
52
|
+
register Tennpipes::Admin::AccessControl
|
|
53
|
+
enable :store_location
|
|
54
|
+
set :login_page, "/login"
|
|
55
|
+
|
|
56
|
+
access_control.roles_for :any do |role|
|
|
57
|
+
role.protect "/customer/orders"
|
|
58
|
+
role.protect "/cart/checkout"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
In this example +if+ we visit URLs that start with /+customer+/+orders+ or /+cart/checkout+ we will be redirected
|
|
63
|
+
to our :+login_page+ "/login". Once we are correctly logged in we can visit these pages.
|
|
64
|
+
|
|
65
|
+
For a more complete look at using the Admin panel functionality and access features, be sure to check out the
|
|
66
|
+
{Tennpipes Admin}[http://www.tennpipesrb.com/guides/tennpipes-su] guide.
|
|
67
|
+
|
|
68
|
+
== Copyright
|
|
69
|
+
|
|
70
|
+
Copyright (c) 2011-2013 Tennpipes. See LICENSE for details.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../gem_rake_helper')
|
|
2
|
+
|
|
3
|
+
namespace :bootstrap do
|
|
4
|
+
desc 'Compile bootstrap assets'
|
|
5
|
+
task :compile do
|
|
6
|
+
puts "Implement"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
desc 'Compile css'
|
|
10
|
+
task :css do
|
|
11
|
+
require 'less'
|
|
12
|
+
src = File.join(File.dirname(__FILE__), 'lib', 'tennpipes-su', 'bootstrap-less', 'tennpipes-su.less')
|
|
13
|
+
out = File.join(File.dirname(__FILE__), 'lib', 'tennpipes-su', 'generators', 'templates', 'assets', 'stylesheets', 'bootstrap.css')
|
|
14
|
+
css = Less::Parser.new(:paths => [File.dirname(src)]).parse(File.read(src)).to_css(:compress => true)
|
|
15
|
+
File.open(out, 'w') { |file| file.write css }
|
|
16
|
+
puts "Generated #{out}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
desc 'Compile js'
|
|
20
|
+
task :js do
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/tennpipes-su.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'active_support/core_ext/array/conversions'
|
|
2
|
+
require 'tennpipes-base'
|
|
3
|
+
require 'tennpipes-helper'
|
|
4
|
+
|
|
5
|
+
FileSet.glob_require('tennpipes-su/*.rb', __FILE__)
|
|
6
|
+
FileSet.glob_require('tennpipes-su/{helpers,utils}/*.rb', __FILE__)
|
|
7
|
+
|
|
8
|
+
module Tennpipes
|
|
9
|
+
##
|
|
10
|
+
# Tennpipes::Admin is beautiful Ajax Admin, with these features:
|
|
11
|
+
#
|
|
12
|
+
# Orm Agnostic:: Adapters for datamapper, activerecord, mongomapper, couchdb (now only: datamapper and activerecord), ohm
|
|
13
|
+
# Authentication:: Support for Account authentication, Account Permission management
|
|
14
|
+
# Scaffold:: You can simply create a new "admin interface" simply providing a Model
|
|
15
|
+
# Ajax Uploads:: You can upload file, manage them and attach them to any model in a quick and simple way (coming soon)
|
|
16
|
+
#
|
|
17
|
+
module Admin
|
|
18
|
+
class << self
|
|
19
|
+
def registered(app)
|
|
20
|
+
# Load Tennpipes::Admin locales
|
|
21
|
+
I18n.load_path += Dir["#{File.dirname(__FILE__)}/tennpipes-su/locale/**/*.yml"]
|
|
22
|
+
end
|
|
23
|
+
alias :included :registered
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# Now we need to add admin generators to tennpipes-init
|
|
30
|
+
#
|
|
31
|
+
begin
|
|
32
|
+
require 'tennpipes-init'
|
|
33
|
+
Tennpipes::Generators.load_paths << Dir[File.dirname(__FILE__) + '/tennpipes-su/generators/{actions,orm,admin_app,admin_page}.rb']
|
|
34
|
+
rescue LoadError
|
|
35
|
+
end
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
|
2
|
+
|
|
3
|
+
module Tennpipes
|
|
4
|
+
module Admin
|
|
5
|
+
class AccessControlError < StandardError
|
|
6
|
+
end
|
|
7
|
+
##
|
|
8
|
+
# This module enables access control functionality within a Tennpipes application.
|
|
9
|
+
#
|
|
10
|
+
module AccessControl
|
|
11
|
+
class << self
|
|
12
|
+
##
|
|
13
|
+
# Method used by Tennpipes::Application when we register the extension.
|
|
14
|
+
#
|
|
15
|
+
def registered(app)
|
|
16
|
+
app.register Tennpipes::Admin unless app.extensions.include?(Tennpipes::Admin)
|
|
17
|
+
app.set :session_id, "_tennpipes_#{File.basename(Tennpipes.root)}_#{app.app_name}".to_sym unless app.respond_to?(:session_id)
|
|
18
|
+
app.set :admin_model, 'Account' unless app.respond_to?(:admin_model)
|
|
19
|
+
app.helpers Tennpipes::Admin::Helpers::AuthenticationHelpers
|
|
20
|
+
app.helpers Tennpipes::Admin::Helpers::ViewHelpers
|
|
21
|
+
app.before { login_required }
|
|
22
|
+
app.send(:cattr_accessor, :access_control)
|
|
23
|
+
app.send(:access_control=, Tennpipes::Admin::AccessControl::Base.new)
|
|
24
|
+
end
|
|
25
|
+
alias :included :registered
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# This base access control class where roles are defined as are authorizations.
|
|
30
|
+
#
|
|
31
|
+
class Base
|
|
32
|
+
def initialize
|
|
33
|
+
@roles, @authorizations, @project_modules = [], [], []
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# We map project modules for a given role or roles.
|
|
38
|
+
#
|
|
39
|
+
def roles_for(*roles, &block)
|
|
40
|
+
raise Tennpipes::Admin::AccessControlError, "Role #{role} must be present and must be a symbol!" if roles.any? { |r| !r.kind_of?(Symbol) } || roles.empty?
|
|
41
|
+
raise Tennpipes::Admin::AccessControlError, "You can't merge :any with other roles" if roles.size > 1 && roles.any? { |r| r == :any }
|
|
42
|
+
|
|
43
|
+
@roles += roles
|
|
44
|
+
@authorizations << Authorization.new(*roles, &block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Return an array of roles.
|
|
49
|
+
#
|
|
50
|
+
def roles
|
|
51
|
+
@roles.uniq.reject { |r| r == :any }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# Return an array of project_modules.
|
|
56
|
+
#
|
|
57
|
+
def project_modules(account)
|
|
58
|
+
role = account.role.to_sym rescue :any
|
|
59
|
+
authorizations = @authorizations.find_all { |auth| auth.roles.include?(role) }
|
|
60
|
+
authorizations.flat_map(&:project_modules).uniq
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# Return true if the given account is allowed to see the given path.
|
|
65
|
+
#
|
|
66
|
+
# @example Hiding a disallowed link from a user.
|
|
67
|
+
#
|
|
68
|
+
# # File: config/apps.rb
|
|
69
|
+
# # [...]
|
|
70
|
+
# Tennpipes.mount('Admin').to('/admin')
|
|
71
|
+
#
|
|
72
|
+
# # File: admin/app.rb
|
|
73
|
+
# class Admin < Tennpipes::Application
|
|
74
|
+
# # [...]
|
|
75
|
+
# register Tennpipes::Admin::AccessControl
|
|
76
|
+
# # [...]
|
|
77
|
+
#
|
|
78
|
+
# # Goals:
|
|
79
|
+
# # * Admins can manage widgets and accounts.
|
|
80
|
+
# # * Workers can only manage widgets.
|
|
81
|
+
#
|
|
82
|
+
# access_control.roles_for :admin do |role|
|
|
83
|
+
# role.project_module :accounts, '/accounts'
|
|
84
|
+
# role.project_module :widgets, '/widgets'
|
|
85
|
+
# end
|
|
86
|
+
#
|
|
87
|
+
# access_control.roles_for :worker do |role|
|
|
88
|
+
# role.project_module :widgets, '/widgets'
|
|
89
|
+
# end
|
|
90
|
+
# end
|
|
91
|
+
#
|
|
92
|
+
# # File: admin/views/layouts/application.haml
|
|
93
|
+
# # NOTE The un-mounted path is used ('/accounts' instead of '/admin/accounts')
|
|
94
|
+
# - if access_control.allowed?(current_account, '/accounts')
|
|
95
|
+
# # Admins see the "Profile" link, but Workers do not
|
|
96
|
+
# = link_to 'Profile', url(:accounts, :edit, :id => current_account.id)
|
|
97
|
+
#
|
|
98
|
+
def allowed?(account=nil, path=nil)
|
|
99
|
+
path = "/" if path.blank?
|
|
100
|
+
role = account.role.to_sym rescue nil
|
|
101
|
+
authorizations = @authorizations.find_all { |auth| auth.roles.include?(:any) }
|
|
102
|
+
allowed_paths = authorizations.map(&:allowed).flatten.uniq
|
|
103
|
+
denied_paths = authorizations.map(&:denied).flatten.uniq
|
|
104
|
+
if account
|
|
105
|
+
denied_paths.clear
|
|
106
|
+
# explicit authorizations for the role associated with the given account
|
|
107
|
+
authorizations = @authorizations.find_all { |auth| auth.roles.include?(role) }
|
|
108
|
+
allowed_paths += authorizations.map(&:allowed).flatten.uniq
|
|
109
|
+
# other explicit authorizations
|
|
110
|
+
authorizations = @authorizations.find_all { |auth| !auth.roles.include?(role) && !auth.roles.include?(:any) }
|
|
111
|
+
denied_paths += authorizations.map(&:allowed).flatten.uniq # remove paths explicitly allowed for other roles
|
|
112
|
+
denied_paths += authorizations.map(&:denied).flatten.uniq # remove paths explicitly denied to other roles
|
|
113
|
+
end
|
|
114
|
+
return true if allowed_paths.any? { |p| path =~ /^#{p}/ }
|
|
115
|
+
return false if denied_paths.any? { |p| path =~ /^#{p}/ }
|
|
116
|
+
true
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
###
|
|
121
|
+
# Project Authorization Class.
|
|
122
|
+
#
|
|
123
|
+
class Authorization
|
|
124
|
+
attr_reader :allowed, :denied, :project_modules, :roles
|
|
125
|
+
|
|
126
|
+
def initialize(*roles, &block)
|
|
127
|
+
@roles = roles
|
|
128
|
+
@allowed = []
|
|
129
|
+
@denied = []
|
|
130
|
+
@project_modules = []
|
|
131
|
+
yield self
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
##
|
|
135
|
+
# Allow a specified path.
|
|
136
|
+
#
|
|
137
|
+
def allow(path)
|
|
138
|
+
@allowed << path unless @allowed.include?(path)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
##
|
|
142
|
+
# Protect access from.
|
|
143
|
+
#
|
|
144
|
+
def protect(path)
|
|
145
|
+
@denied << path unless @denied.include?(path)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
##
|
|
149
|
+
# Create a project module.
|
|
150
|
+
#
|
|
151
|
+
def project_module(name, path, options={})
|
|
152
|
+
allow(path)
|
|
153
|
+
@project_modules << ProjectModule.new(name, path, options)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
##
|
|
158
|
+
# Project Module class.
|
|
159
|
+
#
|
|
160
|
+
class ProjectModule
|
|
161
|
+
attr_reader :name, :options
|
|
162
|
+
|
|
163
|
+
def initialize(name, path, options={})
|
|
164
|
+
@name, @path, @options = name, path, options
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
##
|
|
168
|
+
# Returns the name of the project module humanize them for you.
|
|
169
|
+
#
|
|
170
|
+
def human_name
|
|
171
|
+
@name.to_s.humanize
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
##
|
|
175
|
+
# Return the path of the project module. If a prefix given will be pre pended.
|
|
176
|
+
#
|
|
177
|
+
# @example
|
|
178
|
+
# # => /accounts/new
|
|
179
|
+
# project_module.path
|
|
180
|
+
# # => /admin/accounts
|
|
181
|
+
# project_module.path("/admin")
|
|
182
|
+
#
|
|
183
|
+
def path(prefix=nil)
|
|
184
|
+
path = prefix ? File.join(prefix, @path) : @path
|
|
185
|
+
path = File.join(ENV['RACK_BASE_URI'].to_s, path) if ENV['RACK_BASE_URI']
|
|
186
|
+
path
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Alerts
|
|
3
|
+
// --------------------------------------------------
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// Base styles
|
|
7
|
+
// -------------------------
|
|
8
|
+
|
|
9
|
+
.alert {
|
|
10
|
+
padding: @alert-padding;
|
|
11
|
+
margin-bottom: @line-height-computed;
|
|
12
|
+
border: 1px solid transparent;
|
|
13
|
+
border-radius: @alert-border-radius;
|
|
14
|
+
|
|
15
|
+
// Headings for larger alerts
|
|
16
|
+
h4 {
|
|
17
|
+
margin-top: 0;
|
|
18
|
+
// Specified for the h4 to prevent conflicts of changing @headings-color
|
|
19
|
+
color: inherit;
|
|
20
|
+
}
|
|
21
|
+
// Provide class for links that match alerts
|
|
22
|
+
.alert-link {
|
|
23
|
+
font-weight: @alert-link-font-weight;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Improve alignment and spacing of inner content
|
|
27
|
+
> p,
|
|
28
|
+
> ul {
|
|
29
|
+
margin-bottom: 0;
|
|
30
|
+
}
|
|
31
|
+
> p + p {
|
|
32
|
+
margin-top: 5px;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Dismissable alerts
|
|
37
|
+
//
|
|
38
|
+
// Expand the right padding and account for the close button's positioning.
|
|
39
|
+
|
|
40
|
+
.alert-dismissable {
|
|
41
|
+
padding-right: (@alert-padding + 20);
|
|
42
|
+
|
|
43
|
+
// Adjust close link position
|
|
44
|
+
.close {
|
|
45
|
+
position: relative;
|
|
46
|
+
top: -2px;
|
|
47
|
+
right: -21px;
|
|
48
|
+
color: inherit;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Alternate styles
|
|
53
|
+
//
|
|
54
|
+
// Generate contextual modifier classes for colorizing the alert.
|
|
55
|
+
|
|
56
|
+
.alert-success {
|
|
57
|
+
.alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);
|
|
58
|
+
}
|
|
59
|
+
.alert-info {
|
|
60
|
+
.alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);
|
|
61
|
+
}
|
|
62
|
+
.alert-warning {
|
|
63
|
+
.alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);
|
|
64
|
+
}
|
|
65
|
+
.alert-danger {
|
|
66
|
+
.alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);
|
|
67
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Badges
|
|
3
|
+
// --------------------------------------------------
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// Base classes
|
|
7
|
+
.badge {
|
|
8
|
+
display: inline-block;
|
|
9
|
+
min-width: 10px;
|
|
10
|
+
padding: 3px 7px;
|
|
11
|
+
font-size: @font-size-small;
|
|
12
|
+
font-weight: @badge-font-weight;
|
|
13
|
+
color: @badge-color;
|
|
14
|
+
line-height: @badge-line-height;
|
|
15
|
+
vertical-align: baseline;
|
|
16
|
+
white-space: nowrap;
|
|
17
|
+
text-align: center;
|
|
18
|
+
background-color: @badge-bg;
|
|
19
|
+
border-radius: @badge-border-radius;
|
|
20
|
+
|
|
21
|
+
// Empty badges collapse automatically (not available in IE8)
|
|
22
|
+
&:empty {
|
|
23
|
+
display: none;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Quick fix for badges in buttons
|
|
27
|
+
.btn & {
|
|
28
|
+
position: relative;
|
|
29
|
+
top: -1px;
|
|
30
|
+
}
|
|
31
|
+
.btn-xs & {
|
|
32
|
+
top: 0;
|
|
33
|
+
padding: 1px 5px;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Hover state, but only for links
|
|
38
|
+
a.badge {
|
|
39
|
+
&:hover,
|
|
40
|
+
&:focus {
|
|
41
|
+
color: @badge-link-hover-color;
|
|
42
|
+
text-decoration: none;
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Account for counters in navs
|
|
48
|
+
a.list-group-item.active > .badge,
|
|
49
|
+
.nav-pills > .active > a > .badge {
|
|
50
|
+
color: @badge-active-color;
|
|
51
|
+
background-color: @badge-active-bg;
|
|
52
|
+
}
|
|
53
|
+
.nav-pills > li > a > .badge {
|
|
54
|
+
margin-left: 3px;
|
|
55
|
+
}
|