tennpipes-su 3.6.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|