trestle-auth 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +165 -0
  7. data/README.md +31 -0
  8. data/Rakefile +6 -0
  9. data/app/assets/javascripts/trestle/auth.js +0 -0
  10. data/app/assets/stylesheets/trestle/auth/_form.scss +114 -0
  11. data/app/assets/stylesheets/trestle/auth/_layout.scss +20 -0
  12. data/app/assets/stylesheets/trestle/auth/userbox.scss +49 -0
  13. data/app/assets/stylesheets/trestle/auth.scss +9 -0
  14. data/app/controllers/trestle/auth/sessions_controller.rb +24 -0
  15. data/app/helpers/trestle/auth/user_helper.rb +13 -0
  16. data/app/views/layouts/trestle/auth.html.erb +37 -0
  17. data/app/views/trestle/auth/_userbox.html.erb +17 -0
  18. data/app/views/trestle/auth/sessions/new.html.erb +38 -0
  19. data/config/initializers/trestle.rb +9 -0
  20. data/config/locale/en.yml +8 -0
  21. data/config/routes.rb +7 -0
  22. data/lib/generators/trestle/auth/admin/admin_generator.rb +22 -0
  23. data/lib/generators/trestle/auth/admin/templates/admin.rb.erb +33 -0
  24. data/lib/generators/trestle/auth/install/install_generator.rb +95 -0
  25. data/lib/generators/trestle/auth/model/model_generator.rb +19 -0
  26. data/lib/trestle/auth/configuration/rememberable.rb +30 -0
  27. data/lib/trestle/auth/configuration.rb +36 -0
  28. data/lib/trestle/auth/controller_methods.rb +77 -0
  29. data/lib/trestle/auth/engine.rb +15 -0
  30. data/lib/trestle/auth/model_methods/rememberable.rb +28 -0
  31. data/lib/trestle/auth/model_methods.rb +21 -0
  32. data/lib/trestle/auth/null_user.rb +13 -0
  33. data/lib/trestle/auth/version.rb +5 -0
  34. data/lib/trestle/auth.rb +16 -0
  35. data/trestle-auth.gemspec +27 -0
  36. metadata +148 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 80c40a35773f90ba2b88c6c7af72ffe90adcb9c5
4
+ data.tar.gz: 930feb5ddb650ada9bbfe02c6cca9b065dcc92e5
5
+ SHA512:
6
+ metadata.gz: af280f95145ceafa64841d50e3efe63d311f027297ebc72d5bc1e46e4f80406b786baaa5a780acd380239e749f3be87576d481098d09f197c94b2e61b895e1ff
7
+ data.tar.gz: 1eaf8e6473f391122c785e33692c03a9effc59ceb716a0c380344e25176a6c672fe4aa7ebe7aada5ec420d1a2587635914eb607a4cf129add8d726e6818d3cb3
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in trestle-auth.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Trestle Authentication (trestle-auth)
2
+
3
+ > Authentication plugin for the Trestle admin framework
4
+
5
+ <img src="https://trestle.io/images/Trestle-Auth.png" width="50%" />
6
+
7
+
8
+ ## Getting Started
9
+
10
+ These instructions assume you have a working Trestle application. To integrate trestle-auth, first add it to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'trestle-auth'
14
+ ```
15
+
16
+ Run `bundle install`, and then run the install generator to set up configuration options, user model and user admin resource.
17
+
18
+ $ rails generate trestle:auth:install
19
+ $ rake db:migrate
20
+
21
+ Then create an initial admin user from the rails console:
22
+
23
+ $ rails console
24
+ > User.create(email: "admin@example.com", password: "password", first_name: "Admin", last_name: "User")
25
+
26
+ After restarting your Rails server, any attempt to access a page within your admin will redirect you to the login page.
27
+
28
+
29
+ ## License
30
+
31
+ The gem is available as open source under the terms of the [LGPLv3 License](https://opensource.org/licenses/LGPL-3.0).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
File without changes
@@ -0,0 +1,114 @@
1
+ a {
2
+ color: rgba(white, 0.75);
3
+ &:hover { color: white; }
4
+ }
5
+
6
+ .auth-header {
7
+ text-align: center;
8
+ margin-bottom: 20px;
9
+
10
+ img {
11
+ max-width: 100%;
12
+ }
13
+ }
14
+
15
+ .remember-me {
16
+ display: block;
17
+ font-weight: normal;
18
+ color: rgba(white, 0.75);
19
+ background: rgba(black, 0.075);
20
+ border-radius: 5px;
21
+ padding: 10px 15px;
22
+ font-size: 13px;
23
+ cursor: pointer;
24
+
25
+ input {
26
+ margin-right: 10px;
27
+ }
28
+
29
+ &:hover {
30
+ background: rgba(black, 0.1);
31
+ }
32
+ }
33
+
34
+ .form-control, .input-group-addon {
35
+ background: rgba(white, 0.1);
36
+ border: none;
37
+ }
38
+
39
+ .form-control {
40
+ box-shadow: none;
41
+
42
+ color: white;
43
+
44
+ height: auto;
45
+ padding: 12px 5px;
46
+
47
+ font-size: 16px;
48
+
49
+ &:focus {
50
+ outline-color: transparent;
51
+ outline-style: none;
52
+ box-shadow: none;
53
+ }
54
+
55
+ &::placeholder {
56
+ color: rgba(white, 0.5);
57
+ }
58
+
59
+ &:-webkit-autofill {
60
+ -webkit-text-fill-color: white;
61
+
62
+ &, &:hover, &:focus, &:active {
63
+ transition: background-color 9999999s ease-in-out 0s;
64
+ }
65
+ }
66
+ }
67
+
68
+ .input-group-addon {
69
+ color: rgba(white, 0.5);
70
+
71
+ &:first-child {
72
+ padding-right: 5px;
73
+ }
74
+ }
75
+
76
+ .btn {
77
+ box-shadow: rgba(black, 0.1) 0 0 2px;
78
+ padding: 12px;
79
+ font-size: 16px;
80
+ }
81
+
82
+ .btn-primary {
83
+ outline: none;
84
+
85
+ &:hover {
86
+ background-color: darken($btn-primary-bg, 2.5%);
87
+ border-color: darken($btn-primary-border, 5%);
88
+ }
89
+
90
+ &:focus, &:active {
91
+ background-color: darken($btn-primary-bg, 5%);
92
+ border-color: darken($btn-primary-border, 10%);
93
+ }
94
+
95
+ &:active:focus {
96
+ outline: none !important;
97
+ background-color: darken($btn-primary-bg, 10%);
98
+ border-color: darken($btn-primary-border, 15%);
99
+ }
100
+ }
101
+
102
+ .form-footer {
103
+ font-size: 12px;
104
+ }
105
+
106
+ .forgot-password {
107
+ float: right;
108
+ padding: 10px 5px;
109
+ }
110
+
111
+ .alert-danger {
112
+ background: $theme-bg-texture-url fixed, $alert-danger-bg;
113
+ color: white;
114
+ }
@@ -0,0 +1,20 @@
1
+ html, body {
2
+ height: 100%;
3
+ }
4
+
5
+ body {
6
+ -webkit-font-smoothing: antialiased;
7
+
8
+ margin: 0;
9
+ overflow: hidden;
10
+
11
+ color: white;
12
+ background: $theme-bg;
13
+
14
+ display: flex;
15
+ }
16
+
17
+ .container {
18
+ margin: auto;
19
+ width: 320px;
20
+ }
@@ -0,0 +1,49 @@
1
+ @import "trestle/support";
2
+
3
+ .userbox {
4
+ margin-top: 2px;
5
+ margin-bottom: 2px;
6
+
7
+ > a {
8
+ color: $text-color;
9
+
10
+ display: block;
11
+ padding: 2px 0;
12
+
13
+ font-size: 14px;
14
+ font-weight: normal;
15
+ line-height: 40px;
16
+
17
+ &:hover, &:focus {
18
+ text-decoration: none;
19
+ }
20
+ }
21
+
22
+ .avatar {
23
+ vertical-align: top;
24
+ margin-left: 6px;
25
+ }
26
+
27
+ .name {
28
+ color: $text-color;
29
+ }
30
+ }
31
+
32
+ @include mobile {
33
+ .userbox {
34
+ position: relative;
35
+ z-index: 5;
36
+
37
+ > a, .name {
38
+ color: white;
39
+ }
40
+
41
+ .name {
42
+ display: none;
43
+ }
44
+
45
+ .avatar {
46
+ border: 1px solid rgba(white, 0.25);
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,9 @@
1
+ // User-defined variables
2
+ @import "trestle/support";
3
+
4
+ // 3rd party dependencies
5
+ @import "trestle/bootstrap";
6
+ @import "trestle/font-awesome";
7
+
8
+ @import "auth/layout";
9
+ @import "auth/form";
@@ -0,0 +1,24 @@
1
+ class Trestle::Auth::SessionsController < Trestle::ApplicationController
2
+ layout 'trestle/auth'
3
+
4
+ skip_before_action :require_authenticated_user
5
+
6
+ def new
7
+ end
8
+
9
+ def create
10
+ if user = Trestle.config.auth.authenticate(params)
11
+ login!(user)
12
+ remember_me! if Trestle.config.auth.remember.enabled && params[:remember_me] == "1"
13
+ redirect_to previous_location || Trestle.config.path
14
+ else
15
+ flash[:error] = t("admin.auth.error", default: "Incorrect login details.")
16
+ redirect_to action: :new
17
+ end
18
+ end
19
+
20
+ def destroy
21
+ logout!
22
+ redirect_to login_url
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ module Trestle::Auth::UserHelper
2
+ def format_user_name(user)
3
+ if user.respond_to?(:first_name) && user.respond_to?(:last_name)
4
+ safe_join([user.first_name, content_tag(:strong, user.last_name)], " ")
5
+ else
6
+ display(user)
7
+ end
8
+ end
9
+
10
+ def avatar_for(user)
11
+ avatar { instance_exec(user, &Trestle.config.auth.avatar) } if Trestle.config.auth.avatar
12
+ end
13
+ end
@@ -0,0 +1,37 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset='utf-8'>
5
+ <meta content='width=device-width, initial-scale=1' name='viewport'>
6
+ <meta content='IE=edge,chrome=1' http-equiv='X-UA-Compatible'>
7
+
8
+ <meta content='no-cache' name='turbolinks-cache-control'>
9
+
10
+ <%= csrf_meta_tags %>
11
+
12
+ <title><%= Trestle.config.site_title %></title>
13
+
14
+ <%= stylesheet_link_tag "trestle/auth", 'data-turbolinks-track': 'reload' %>
15
+
16
+ <%= javascript_include_tag "turbolinks" if defined?(Turbolinks) %>
17
+ <%= javascript_include_tag "trestle/auth", 'data-turbolinks-track': 'reload' %>
18
+ </head>
19
+
20
+ <body>
21
+ <main class="container">
22
+ <header class="auth-header">
23
+ <h1>
24
+ <% if Trestle.config.site_logo -%>
25
+ <%= image_tag(Trestle.config.site_logo, alt: Trestle.config.site_title) %>
26
+ <% elsif Trestle.config.site_logo_small -%>
27
+ <%= image_tag(Trestle.config.site_logo_small, alt: Trestle.config.site_title) %>
28
+ <% else -%>
29
+ <%= Trestle.config.site_title %>
30
+ <% end -%>
31
+ </h1>
32
+ </header>
33
+
34
+ <%= yield %>
35
+ </main>
36
+ </body>
37
+ </html>
@@ -0,0 +1,17 @@
1
+ <div class="userbox pull-right dropdown">
2
+ <%= link_to "#", class: 'dropdown-toggle', data: { toggle: 'dropdown' } do %>
3
+ <span class="name">
4
+ <%= format_user_name(current_user) %>
5
+ <span class="caret"></span>
6
+ </span>
7
+
8
+ <%= avatar_for(current_user) %>
9
+ <% end %>
10
+
11
+ <ul class="dropdown-menu dropdown-menu-right">
12
+ <% if Trestle.config.auth.user_admin && user_admin = Trestle.lookup(Trestle.config.auth.user_admin) -%>
13
+ <li><%= link_to t("admin.auth.my_account", default: "My Account"), user_admin.path(:show, id: current_user), class: "dropdown-item" %></li>
14
+ <% end -%>
15
+ <li><%= link_to t("admin.auth.logout", default: "Log out"), trestle.logout_path, class: "dropdown-item" %></li>
16
+ </ul>
17
+ </div>
@@ -0,0 +1,38 @@
1
+ <%= form_tag login_path, class: "login-form" do %>
2
+ <%= hook("auth.login.heading") %>
3
+
4
+ <% if flash[:error] -%>
5
+ <div class="alert alert-danger">
6
+ <p><%= flash[:error] %></p>
7
+ </div>
8
+ <% end -%>
9
+
10
+ <div class="form-group">
11
+ <div class="input-group">
12
+ <span class="input-group-addon"><i class="fa fa-user fa-fw"></i></span>
13
+ <%= text_field_tag Trestle.config.auth.authenticate_with, "", placeholder: Trestle.config.auth.authenticate_with.to_s.humanize, class: "form-control" %>
14
+ </div>
15
+ </div>
16
+
17
+ <div class="form-group">
18
+ <div class="input-group">
19
+ <span class="input-group-addon"><i class="fa fa-lock fa-fw"></i></span>
20
+ <%= password_field_tag :password, "", placeholder: "Password", class: "form-control" %>
21
+ </div>
22
+ </div>
23
+
24
+ <%= hook("auth.login.form") %>
25
+
26
+ <% if Trestle.config.auth.remember.enabled %>
27
+ <div class="form-group">
28
+ <label class="remember-me">
29
+ <%= check_box_tag :remember_me %>
30
+ <%= t("admin.auth.remember_me", default: "Remember me") %>
31
+ </label>
32
+ </div>
33
+ <% end %>
34
+
35
+ <div class="form-group">
36
+ <%= submit_tag t("admin.auth.login", default: "Login"), class: "btn btn-primary btn-block" %>
37
+ </div>
38
+ <% end %>
@@ -0,0 +1,9 @@
1
+ Trestle.configure do |config|
2
+ config.hook("stylesheets") do
3
+ stylesheet_link_tag("trestle/auth/userbox")
4
+ end
5
+
6
+ config.hook("view.header") do
7
+ render "trestle/auth/userbox"
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ en:
2
+ admin:
3
+ auth:
4
+ my_account: My Account
5
+ login: Login
6
+ logout: Logout
7
+ error: Incorrect login details.
8
+ remember_me: Remember me
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ Trestle::Engine.routes.draw do
2
+ controller "trestle/auth/sessions" do
3
+ get 'login' => :new, as: :login
4
+ post 'login' => :create
5
+ get 'logout' => :destroy, as: :logout
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ module Trestle
2
+ module Auth
3
+ module Generators
4
+ class AdminGenerator < ::Rails::Generators::Base
5
+ desc "Creates a Trestle admin for managing Administrators"
6
+
7
+ argument :model, type: :string, default: "Administrator"
8
+
9
+ source_root File.expand_path("../templates", __FILE__)
10
+
11
+ def create_admin
12
+ template "admin.rb.erb", File.join('app/admin/auth', "#{model.underscore.pluralize}_admin.rb")
13
+ end
14
+
15
+ protected
16
+ def plural_name
17
+ model.demodulize.underscore.pluralize
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,33 @@
1
+ Trestle.resource(:<%= plural_name %>, model: Trestle.config.auth.user_class, scope: Auth) do
2
+ menu do
3
+ group :configuration, priority: :last do
4
+ item :<%= plural_name %>, icon: "fa fa-users"
5
+ end
6
+ end
7
+
8
+ table do
9
+ column :avatar, header: false do |administrator|
10
+ avatar_for(administrator)
11
+ end
12
+ column :email, link: true
13
+ column :first_name
14
+ column :last_name
15
+ actions do |a|
16
+ a.delete unless a.instance == current_user
17
+ end
18
+ end
19
+
20
+ form do |administrator|
21
+ text_field :email
22
+
23
+ row do
24
+ col(sm: 6) { text_field :first_name }
25
+ col(sm: 6) { text_field :last_name }
26
+ end
27
+
28
+ row do
29
+ col(sm: 6) { password_field :password }
30
+ col(sm: 6) { password_field :password_confirmation }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,95 @@
1
+ module Trestle
2
+ module Auth
3
+ module Generators
4
+ class InstallGenerator < ::Rails::Generators::Base
5
+ desc "Installs trestle-auth"
6
+
7
+ argument :model, type: :string, default: "Administrator"
8
+
9
+ def insert_configuration
10
+ inject_into_file "config/initializers/trestle.rb", before: /^end/ do
11
+ <<-RUBY.strip_heredoc.indent(2)
12
+
13
+ # == Authentication Options
14
+ #
15
+ # Specify the user class to be used by trestle-auth.
16
+ #
17
+ config.auth.user_class = -> { #{model} }
18
+
19
+ # Specify the scope for valid admin users.
20
+ # Defaults to config.auth.user_class (unscoped).
21
+ #
22
+ # config.auth.user_scope = -> { User.where(admin: true) }
23
+
24
+ # Specify the Trestle admin for managing administrator users.
25
+ #
26
+ config.auth.user_admin = -> { :"auth/#{model.underscore.pluralize}" }
27
+
28
+ # Specify the parameter (along with a password) to be used to
29
+ # authenticate an administrator. Defaults to :email.
30
+ #
31
+ # config.auth.authenticate_with = :login
32
+
33
+ # Customize the method for authenticating a user given login parameters.
34
+ # The block should return an instance of the auth user class, or nil.
35
+ #
36
+ # config.auth.authenticate = ->(params) {
37
+ # User.authenticate(params[:login], params[:password])
38
+ # }
39
+
40
+ # Customize the rendering of user avatars. Can be disabled by setting to false.
41
+ # Defaults to the Gravatar based on the user's email address.
42
+ #
43
+ # config.auth.avatar = ->(user) {
44
+ # image_tag(user.avatar_url, alt: user.name)
45
+ # }
46
+
47
+ # Customize the method for determining the user's locale.
48
+ # Defaults to user.locale (if the method is defined).
49
+ #
50
+ # config.auth.locale = ->(user) {
51
+ # user.locale if user.respond_to?(:locale)
52
+ # }
53
+
54
+ # Enable or disable remember me functionality. Defaults to true.
55
+ #
56
+ # config.auth.remember.enabled = false
57
+
58
+ # Specify remember me expiration time. Defaults to 2 weeks.
59
+ #
60
+ # config.auth.remember.for = 30.days
61
+
62
+ # Customize the method for authenticating a user given a remember token.
63
+ #
64
+ # config.auth.remember.authenticate = ->(token) {
65
+ # User.authenticate_with_remember_token(token)
66
+ # }
67
+
68
+ # Customize the method for remembering a user.
69
+ #
70
+ # config.auth.remember.remember_me, ->(user) { user.remember_me! }
71
+
72
+ # Customize the method for forgetting a user.
73
+ #
74
+ # config.auth.remember.forget_me, ->(user) { user.forget_me! }
75
+
76
+ # Customize the method for generating the remember cookie.
77
+ #
78
+ # config.auth.remember.cookie, ->(user) {
79
+ # { value: user.remember_token, expires: user.remember_token_expires_at }
80
+ # }
81
+ RUBY
82
+ end
83
+ end
84
+
85
+ def generate_model
86
+ generate "trestle:auth:model", model
87
+ end
88
+
89
+ def generate_admin
90
+ generate "trestle:auth:admin", model
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,19 @@
1
+ module Trestle
2
+ module Auth
3
+ module Generators
4
+ class ModelGenerator < ::Rails::Generators::Base
5
+ desc "Creates an Administrator model for use with trestle-auth"
6
+
7
+ argument :name, type: :string, default: "Administrator"
8
+
9
+ def create_model
10
+ generate "model", "#{name} email:string password_digest:string first_name:string last_name:string remember_token:string remember_token_expires_at:datetime"
11
+ end
12
+
13
+ def inject_model_methods
14
+ inject_into_file "app/models/#{name.underscore}.rb", " include Trestle::Auth::ModelMethods\n include Trestle::Auth::ModelMethods::Rememberable\n", before: /^end/
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module Trestle
2
+ module Auth
3
+ class Configuration
4
+ class Rememberable
5
+ include Configurable
6
+
7
+ option :enabled, true
8
+
9
+ option :for, 2.weeks
10
+
11
+ option :authenticate, ->(token) {
12
+ scope = Trestle.config.auth.user_scope
13
+ scope.authenticate_with_remember_token(token)
14
+ }
15
+
16
+ option :remember_me, ->(user) {
17
+ user.remember_me!
18
+ }
19
+
20
+ option :forget_me, ->(user) {
21
+ user.forget_me!
22
+ }
23
+
24
+ option :cookie, ->(user) {
25
+ { value: user.remember_token, expires: user.remember_token_expires_at }
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,36 @@
1
+ module Trestle
2
+ module Auth
3
+ class Configuration
4
+ extend ActiveSupport::Autoload
5
+
6
+ autoload :Rememberable
7
+
8
+ include Configurable
9
+
10
+ option :user_class, -> { ::Administrator }
11
+ option :user_scope, -> { Trestle.config.auth.user_class }
12
+ option :user_admin
13
+
14
+ option :authenticate_with, :email
15
+
16
+ option :authenticate, ->(params) {
17
+ scope = Trestle.config.auth.user_scope
18
+
19
+ scope.authenticate(
20
+ params[Trestle.config.auth.authenticate_with],
21
+ params[:password]
22
+ )
23
+ }
24
+
25
+ option :avatar, ->(user) {
26
+ gravatar(user.email)
27
+ }, evaluate: false
28
+
29
+ option :locale, ->(user) {
30
+ user.locale if user.respond_to?(:locale)
31
+ }
32
+
33
+ option :remember, Rememberable.new
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,77 @@
1
+ module Trestle
2
+ module Auth
3
+ module ControllerMethods
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ helper_method :current_user, :logged_in?
8
+
9
+ before_action :require_authenticated_user
10
+ around_action :set_locale
11
+ end
12
+
13
+ protected
14
+ def current_user
15
+ @current_user ||= begin
16
+ if session[:trestle_user]
17
+ Trestle.config.auth.user_scope.find_by(id: session[:trestle_user])
18
+ elsif Trestle.config.auth.remember.enabled && token = cookies.signed[:trestle_remember_token]
19
+ user = Trestle.config.auth.remember.authenticate(token)
20
+ login!(user) if user
21
+ user
22
+ end
23
+ end
24
+ end
25
+
26
+ def login!(user)
27
+ session[:trestle_user] = user.id
28
+ @current_user = user
29
+ end
30
+
31
+ def logout!
32
+ forget_me!
33
+ session.delete(:trestle_user)
34
+ @current_user = nil
35
+ end
36
+
37
+ def logged_in?
38
+ !!current_user
39
+ end
40
+
41
+ def store_location
42
+ session[:trestle_return_to] = request.fullpath
43
+ end
44
+
45
+ def previous_location
46
+ session.delete(:trestle_return_to)
47
+ end
48
+
49
+ def require_authenticated_user
50
+ logged_in? || login_required!
51
+ end
52
+
53
+ def login_required!
54
+ store_location
55
+ redirect_to trestle.login_url
56
+ false
57
+ end
58
+
59
+ def remember_me!
60
+ Trestle.config.auth.remember.remember_me(current_user)
61
+ cookies.signed[:trestle_remember_token] = Trestle.config.auth.remember.cookie(current_user)
62
+ end
63
+
64
+ def forget_me!
65
+ Trestle.config.auth.remember.forget_me(current_user) if logged_in?
66
+ cookies.delete(:trestle_remember_token)
67
+ end
68
+
69
+ def set_locale
70
+ self.locale = Trestle.config.auth.locale(current_user) || I18n.default_locale if logged_in?
71
+ yield
72
+ ensure
73
+ self.locale = I18n.default_locale
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,15 @@
1
+ module Trestle
2
+ module Auth
3
+ class Engine < ::Rails::Engine
4
+ config.assets.precompile << "trestle/auth.css" << "trestle/auth.js" << "trestle/auth/userbox.scss"
5
+
6
+ initializer "trestle.auth.helpers" do
7
+ Trestle::Engine.paths["app/helpers"].concat(paths["app/helpers"].existent)
8
+ end
9
+
10
+ config.to_prepare do
11
+ Trestle::ApplicationController.send(:include, Trestle::Auth::ControllerMethods)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ module Trestle
2
+ module Auth
3
+ module ModelMethods
4
+ module Rememberable
5
+ extend ActiveSupport::Concern
6
+
7
+ def remember_me!
8
+ update(remember_token: SecureRandom.urlsafe_base64(15), remember_token_expires_at: Time.now + Trestle.config.auth.remember.for)
9
+ end
10
+
11
+ def forget_me!
12
+ update(remember_token: nil, remember_token_expires_at: nil)
13
+ end
14
+
15
+ def remember_token_expired?
16
+ remember_token_expires_at.nil? || Time.now > remember_token_expires_at
17
+ end
18
+
19
+ module ClassMethods
20
+ def authenticate_with_remember_token(token)
21
+ user = find_by(remember_token: token)
22
+ user if user && !user.remember_token_expired?
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ module Trestle
2
+ module Auth
3
+ module ModelMethods
4
+ extend ActiveSupport::Concern
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Rememberable
8
+
9
+ included do
10
+ has_secure_password
11
+ end
12
+
13
+ module ClassMethods
14
+ def authenticate(identifier, password)
15
+ user = find_by(Trestle.config.auth.authenticate_with => identifier) || NullUser.new
16
+ user.authenticate(password)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module Trestle
2
+ module Auth
3
+ class NullUser
4
+ def authenticate(*)
5
+ BCrypt::Password.new(self.class.password).is_password?("incorrect")
6
+ end
7
+
8
+ def self.password
9
+ @password ||= BCrypt::Password.create("password", cost: BCrypt::Engine.cost)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ module Trestle
2
+ module Auth
3
+ VERSION = "0.2.0"
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ require "trestle/auth/version"
2
+
3
+ module Trestle
4
+ module Auth
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Configuration
8
+ autoload :ControllerMethods
9
+ autoload :ModelMethods
10
+ autoload :NullUser
11
+ end
12
+
13
+ Configuration.option :auth, Auth::Configuration.new
14
+ end
15
+
16
+ require "trestle/auth/engine" if defined?(Rails)
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'trestle/auth/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "trestle-auth"
8
+ spec.version = Trestle::Auth::VERSION
9
+
10
+ spec.authors = ["Sam Pohlenz"]
11
+ spec.email = ["sam@sampohlenz.com"]
12
+
13
+ spec.summary = "Authentication plugin for the Trestle admin framework"
14
+ spec.description = "Authentication plugin for the Trestle admin framework."
15
+ spec.homepage = "https://www.trestle.io"
16
+ spec.license = "LGPL-3.0"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "trestle", "~> 0.8"
22
+ spec.add_dependency "bcrypt", "~> 3.1.7"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.12"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trestle-auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Sam Pohlenz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: trestle
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bcrypt
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.1.7
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 3.1.7
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ description: Authentication plugin for the Trestle admin framework.
84
+ email:
85
+ - sam@sampohlenz.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - LICENSE
95
+ - README.md
96
+ - Rakefile
97
+ - app/assets/javascripts/trestle/auth.js
98
+ - app/assets/stylesheets/trestle/auth.scss
99
+ - app/assets/stylesheets/trestle/auth/_form.scss
100
+ - app/assets/stylesheets/trestle/auth/_layout.scss
101
+ - app/assets/stylesheets/trestle/auth/userbox.scss
102
+ - app/controllers/trestle/auth/sessions_controller.rb
103
+ - app/helpers/trestle/auth/user_helper.rb
104
+ - app/views/layouts/trestle/auth.html.erb
105
+ - app/views/trestle/auth/_userbox.html.erb
106
+ - app/views/trestle/auth/sessions/new.html.erb
107
+ - config/initializers/trestle.rb
108
+ - config/locale/en.yml
109
+ - config/routes.rb
110
+ - lib/generators/trestle/auth/admin/admin_generator.rb
111
+ - lib/generators/trestle/auth/admin/templates/admin.rb.erb
112
+ - lib/generators/trestle/auth/install/install_generator.rb
113
+ - lib/generators/trestle/auth/model/model_generator.rb
114
+ - lib/trestle/auth.rb
115
+ - lib/trestle/auth/configuration.rb
116
+ - lib/trestle/auth/configuration/rememberable.rb
117
+ - lib/trestle/auth/controller_methods.rb
118
+ - lib/trestle/auth/engine.rb
119
+ - lib/trestle/auth/model_methods.rb
120
+ - lib/trestle/auth/model_methods/rememberable.rb
121
+ - lib/trestle/auth/null_user.rb
122
+ - lib/trestle/auth/version.rb
123
+ - trestle-auth.gemspec
124
+ homepage: https://www.trestle.io
125
+ licenses:
126
+ - LGPL-3.0
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 2.6.12
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Authentication plugin for the Trestle admin framework
148
+ test_files: []