anadea-identity 0.1.0
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/MIT-LICENSE +20 -0
- data/README.md +174 -0
- data/Rakefile +10 -0
- data/app/assets/images/facebook.png +0 -0
- data/app/assets/images/google_oauth2.png +0 -0
- data/app/assets/images/twitter.png +0 -0
- data/app/controllers/identity/base_controller.rb +5 -0
- data/app/controllers/identity/omniauth_callbacks_controller.rb +24 -0
- data/app/controllers/identity/users_controller.rb +58 -0
- data/app/models/identity/role.rb +16 -0
- data/app/models/identity/user.rb +47 -0
- data/app/views/devise/confirmations/new.html.erb +23 -0
- data/app/views/devise/mailer/confirmation_instructions.html.erb +6 -0
- data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
- data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
- data/app/views/devise/passwords/edit.html.erb +28 -0
- data/app/views/devise/passwords/new.html.erb +21 -0
- data/app/views/devise/registrations/edit.html.erb +34 -0
- data/app/views/devise/registrations/new.html.erb +28 -0
- data/app/views/devise/sessions/new.html.erb +31 -0
- data/app/views/devise/shared/_links.erb +25 -0
- data/app/views/devise/unlocks/new.html.erb +20 -0
- data/app/views/identity/users/edit.html.erb +70 -0
- data/app/views/identity/users/index.html.erb +55 -0
- data/config/locales/ca.yml +59 -0
- data/config/locales/de.yml +110 -0
- data/config/locales/en.yml +111 -0
- data/config/locales/es-AR.yml +51 -0
- data/config/locales/es-ES.yml +59 -0
- data/config/locales/es.yml +51 -0
- data/config/locales/fr.yml +51 -0
- data/config/locales/hu.yml +59 -0
- data/config/locales/it.yml +51 -0
- data/config/locales/nl.yml +59 -0
- data/config/locales/pl.yml +57 -0
- data/config/locales/pt-BR.yml +51 -0
- data/config/locales/ru.yml +56 -0
- data/config/locales/tr.yml +51 -0
- data/config/locales/zh-CN.yml +57 -0
- data/config/locales/zh-TW.yml +57 -0
- data/config/routes.rb +5 -0
- data/db/migrate/20150402142437_devise_create_identity_users.rb +42 -0
- data/db/migrate/20150402152859_rolify_create_identity_roles.rb +19 -0
- data/lib/anadea/identity.rb +1 -0
- data/lib/generators/identity/locales_generator.rb +8 -0
- data/lib/generators/identity/views_generator.rb +8 -0
- data/lib/identity.rb +50 -0
- data/lib/identity/admin/user.rb +89 -0
- data/lib/identity/devise_config.rb +31 -0
- data/lib/identity/engine.rb +21 -0
- data/lib/identity/version.rb +3 -0
- data/lib/identity/view_helper.rb +22 -0
- data/lib/tasks/whoami_tasks.rake +4 -0
- metadata +157 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b90fe456fe3459656452c7191052e3cf7b9e72bd
|
4
|
+
data.tar.gz: 7942ef52f965589850dc1e2d9b1be489aaf96fac
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 351d14c0435915e9e1324bbca2b9e53dbcda6764044e16b8138de4d24e2ca44bbf7525e343623104243ab18a0145b38028e2d62a0cd27a7718373bd413f46b8a
|
7
|
+
data.tar.gz: d072c2f56d804f4174305d38f4bc1bb3a412359b66a0d739e92742bd7f1a917a8f9d392e7d4c9c190eaa501c74cd81d60f3ed3ceeffe61e19571795de94ca112
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 Anadea
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
# Identity
|
2
|
+
|
3
|
+
Аутентификация и авторизация для Rails приложения.
|
4
|
+
|
5
|
+
## Установка
|
6
|
+
|
7
|
+
Добавьте строчку в Gemfile приложения:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'anadea-identity'
|
11
|
+
```
|
12
|
+
|
13
|
+
и запустите в консоли:
|
14
|
+
|
15
|
+
```console
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Сгенерируйте миграции:
|
20
|
+
|
21
|
+
```console
|
22
|
+
$ rake identity_engine:install:migrations
|
23
|
+
```
|
24
|
+
|
25
|
+
проверьте их и запустите:
|
26
|
+
|
27
|
+
```console
|
28
|
+
$ rake db:migrate
|
29
|
+
```
|
30
|
+
|
31
|
+
## Использование
|
32
|
+
|
33
|
+
### Аутентификация
|
34
|
+
|
35
|
+
Проверьте маршруты: `rake routes`. Вы увидите набор маршрутов, подобных тем, что
|
36
|
+
даёт [Devise](https://github.com/plataformatec/devise). Собственно, Identity и
|
37
|
+
есть не слишком толстая обёртка поверх Devise.
|
38
|
+
|
39
|
+
У вас работает логин (через форму email/пароль), регистрация (через форму
|
40
|
+
email/пароль/подтверждение пароля), восстановление пароля и многое другое.
|
41
|
+
|
42
|
+
### Модель User
|
43
|
+
|
44
|
+
Вызов `current_user` в контроллере вернёт `Identity::User`, соответствующий
|
45
|
+
таблице `identity_users`. Не нужно добавлять в эту модель методы и не нужно
|
46
|
+
добавлять в эту таблицу колонки, кроме тех, которые используются Devise или
|
47
|
+
Identity. Эту модель следует считать публичным интерфейсом, предоставляеым гемом.
|
48
|
+
|
49
|
+
Рекомендуется заводить модели типа `Profile` или `Account` которые будут
|
50
|
+
"принадлежать" (`belong_to :user, class_name: "Identity::User"`) этой модели
|
51
|
+
и ссылаться на неё с помощью внешнего ключа.
|
52
|
+
|
53
|
+
### Авторизация
|
54
|
+
|
55
|
+
Модель `Identity::User` расширена ролями с помощью
|
56
|
+
[Rolify](https://github.com/RolifyCommunity/rolify). В частности, у вас есть
|
57
|
+
говорящие за себя методы:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
user.add_role :manager
|
61
|
+
user.remove_role :manager
|
62
|
+
user.has_role? :manager
|
63
|
+
|
64
|
+
Identity::User.with_role :manager
|
65
|
+
```
|
66
|
+
|
67
|
+
У вас есть многое другое – смотрите документацию Rolify.
|
68
|
+
|
69
|
+
Используйте эти методы в вызовах вашего авторизационного фреймворка, такого, как
|
70
|
+
[CanCanCan](https://github.com/CanCanCommunity/cancancan).
|
71
|
+
|
72
|
+
### Админка
|
73
|
+
|
74
|
+
Чтобы получить админку по пользователям, подключите
|
75
|
+
[ActiveAdmin](https://github.com/activeadmin/activeadmin) и сгенерируйте
|
76
|
+
конфигурационный файл без генерации пользователей (`--skip-users`).
|
77
|
+
|
78
|
+
### Конфигурация
|
79
|
+
|
80
|
+
Создайте руби-файл в `config/initializers` со следующим содержимым:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
Identity.setup do |config|
|
84
|
+
config.devise_modules += [:confirmable]
|
85
|
+
# и много других конфигурационных опций
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
#### Доступные опции
|
90
|
+
|
91
|
+
Вы всегда можете узнать полный список конфигурацинных опций и их значения по
|
92
|
+
умолчанию, ознакомившись [с исходным кодом](lib/identity.rb).
|
93
|
+
|
94
|
+
* `config.devise_modules` – модули Devise, которые вы используете. Например,
|
95
|
+
выключение `registerable` приведёт к невозможности зарегистрироваться, в том
|
96
|
+
числе, исчезнет соответствующая ссылка, а включение `confirmable` приведёт к
|
97
|
+
тому, что приложение станет требовать подтверждение адреса электронной почты,
|
98
|
+
при условии, что в таблице `identity_users` есть соответствующие колонки
|
99
|
+
(по умолчанию нет).
|
100
|
+
|
101
|
+
Вы можете как модифицировать этот массив, так и полностью его переопределить:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
config.devise_modules += [:confirmable]
|
105
|
+
config.devise_modules = [:database_authenticatable, :omniauthable, ...]
|
106
|
+
```
|
107
|
+
|
108
|
+
По умолчанию включены модули database_authenticatable, registerable,
|
109
|
+
recoverable, rememberable, trackable и validatable. Если включить хотя бы один
|
110
|
+
omniauth provider, автоматически подключится omniauthable. За подробным их
|
111
|
+
описанием обратитесь в документацию Devise.
|
112
|
+
|
113
|
+
* `config.layout` – макет (layout), используемый формами логина, регистрации и
|
114
|
+
прочего. По умолчанию используется главный макет вашего приложения –
|
115
|
+
`"application"`.
|
116
|
+
|
117
|
+
* `config.auth_routes` – если задать `false`, маршруты подключены не будут и вы
|
118
|
+
можете сами подключить их.
|
119
|
+
|
120
|
+
* `config.admin_role` – "главная" роль в приложении. Роль, которой можно
|
121
|
+
управлять из предлаемой гемом админки, и роль, которая по умолчанию является
|
122
|
+
допуском в эту админку.
|
123
|
+
|
124
|
+
Вы также можете использовать любые конфигурационные опции самого Devise.
|
125
|
+
Они будут переданы Devise в точности. Например:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
config.parent_controller = "ApplicationController"
|
129
|
+
```
|
130
|
+
|
131
|
+
За подробным списком того, что можно сконфигурировать в Devise, обратитесь к его
|
132
|
+
документации.
|
133
|
+
|
134
|
+
#### Сделанные кастомизации в конфигурации Devise.
|
135
|
+
|
136
|
+
Мы делаем небольшие изменения в конфигурации Devise по умолчанию. Вы можете это
|
137
|
+
увидеть в [исходном коде гема](lib/identity/devise_config.rb).
|
138
|
+
|
139
|
+
* `config.mailer_sender` – мы достаём это из переменной окружения MAIL_FROM.
|
140
|
+
* `config.sign_out_via` – GET и только GET. Это должно работать без джаваскрипта.
|
141
|
+
* `config.parent_controller` – мы не наследуемся от `ApplicationController` вашего
|
142
|
+
приложения. Devise предлагает для этого определять методы в
|
143
|
+
`ApplicationController`.Если вам нужно переопределить поведение аутентификационных
|
144
|
+
контроллеров, мы рекомендуем создать специальный базовый контроллер в
|
145
|
+
приложении и указать его в качестве `parent_controller`. Затем определять в
|
146
|
+
нём методы типа `after_sign_in_path_for`, как и предлагает Devise.
|
147
|
+
|
148
|
+
### Логин через Facebook.
|
149
|
+
|
150
|
+
Для того, чтобы включить в приложении логин через Facebook нужно:
|
151
|
+
|
152
|
+
* подключить `gem 'omniauth-facebook'` в своем Gemfile.
|
153
|
+
* указать `config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET']`
|
154
|
+
в `config/initializers/identity.rb`.
|
155
|
+
* создать приложение в Facebook можно с помощью [инструкции](https://getsocio.com/Help/How_to_set_up_Facebook_Application).
|
156
|
+
|
157
|
+
### Логин через Twitter.
|
158
|
+
|
159
|
+
Для того, чтобы включить в приложении логин через Twitter нужно:
|
160
|
+
|
161
|
+
* подключить `gem 'omniauth-twitter'` в своем Gemfile.
|
162
|
+
* указать `config.omniauth :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']`
|
163
|
+
в `config/initializers/identity.rb`.
|
164
|
+
* создать приложение в Twitter можно [здесь](https://apps.twitter.com/).
|
165
|
+
|
166
|
+
### Логин через Google.
|
167
|
+
|
168
|
+
Для того, чтобы включить в приложении логин через Google нужно:
|
169
|
+
|
170
|
+
* подключить `gem 'omniauth-google-oauth2'` в своем Gemfile.
|
171
|
+
* указать `config.omniauth :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET']`
|
172
|
+
в `config/initializers/identity.rb`.
|
173
|
+
* создать приложение в Google можно [здесь](https://console.developers.google.com/project).
|
174
|
+
* для создания приложения можно воспользоваться [инструкцией](https://developers.google.com/identity/protocols/OpenIDConnect#appsetup)
|
data/Rakefile
ADDED
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Identity
|
2
|
+
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
3
|
+
def facebook
|
4
|
+
omniauth_login('Facebook')
|
5
|
+
end
|
6
|
+
|
7
|
+
def twitter
|
8
|
+
omniauth_login('Twitter')
|
9
|
+
end
|
10
|
+
|
11
|
+
def google_oauth2
|
12
|
+
omniauth_login('Google')
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def omniauth_login(title)
|
18
|
+
@user = Identity::User.from_omniauth!(request.env["omniauth.auth"])
|
19
|
+
|
20
|
+
set_flash_message(:notice, :success, :kind => title) if is_navigational_format?
|
21
|
+
sign_in_and_redirect @user, :event => :authentication
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Identity
|
2
|
+
class UsersController < ActionController::Base
|
3
|
+
layout Identity.admin_layout
|
4
|
+
before_action :ensure_allowed!
|
5
|
+
helper_method :resource, :resources
|
6
|
+
|
7
|
+
def index
|
8
|
+
@resources = User.search_and_order(params[:search], params[:page])
|
9
|
+
end
|
10
|
+
|
11
|
+
def show
|
12
|
+
redirect_to edit_identity_user_path(params[:id])
|
13
|
+
end
|
14
|
+
|
15
|
+
def edit
|
16
|
+
@resource = find_user
|
17
|
+
end
|
18
|
+
|
19
|
+
def update
|
20
|
+
@resource = find_user
|
21
|
+
if @resource.admin_update(user_params, current?(@resource))
|
22
|
+
@resource.skip_reconfirmation! if @resource.respond_to?(:skip_reconfirmation!)
|
23
|
+
@resource.save
|
24
|
+
redirect_to [Identity.admin_namespace, :users], notice: "#{@resource.email} updated."
|
25
|
+
else
|
26
|
+
render :edit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :resource, :resources
|
33
|
+
|
34
|
+
def ensure_allowed!
|
35
|
+
unless Identity.admin_guard[current_user, self]
|
36
|
+
raise ActionController::RoutingError.new('Nothing here, move around')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def devise_mapping
|
41
|
+
request.env["devise.mapping"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def current?(user)
|
45
|
+
user.id == current_user.id
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_user
|
49
|
+
User.find params[:id]
|
50
|
+
end
|
51
|
+
|
52
|
+
def user_params
|
53
|
+
params.require(:identity_user).permit(
|
54
|
+
:email, :password, :password_confirmation, :active, Identity.admin_role
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "rolify"
|
2
|
+
|
3
|
+
module Identity
|
4
|
+
class Role < ActiveRecord::Base
|
5
|
+
self.table_name = 'identity_roles'
|
6
|
+
|
7
|
+
has_and_belongs_to_many :users, :join_table => :identity_users_identity_roles
|
8
|
+
belongs_to :resource, :polymorphic => true
|
9
|
+
|
10
|
+
validates :resource_type,
|
11
|
+
:inclusion => { :in => Rolify.resource_types },
|
12
|
+
:allow_nil => true
|
13
|
+
|
14
|
+
scopify
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "devise"
|
2
|
+
require "rolify"
|
3
|
+
require "kaminari"
|
4
|
+
|
5
|
+
module Identity
|
6
|
+
class User < ActiveRecord::Base
|
7
|
+
self.table_name = 'identity_users'
|
8
|
+
devise *Identity.devise_modules
|
9
|
+
|
10
|
+
if Devise.omniauth_providers.any?
|
11
|
+
devise :omniauthable, omniauth_providers: Devise.omniauth_providers
|
12
|
+
end
|
13
|
+
|
14
|
+
rolify role_cname: 'Identity::Role'
|
15
|
+
|
16
|
+
def self.from_omniauth!(auth)
|
17
|
+
where(provider: auth.provider, uid: auth.uid).first_or_create! do |user|
|
18
|
+
user.email = auth.provider == "twitter" ? "#{auth.info.nickname}_email@example.com" : auth.info.email
|
19
|
+
user.password = Devise.friendly_token[0,20]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
define_singleton_method Identity.admins_method do
|
24
|
+
with_role(Identity.admin_role)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.find_first_by_auth_conditions(tainted_conditions, opts={active: true})
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.active
|
32
|
+
result = where(active: true)
|
33
|
+
result = result.where.not(confirmed_at: nil) if devise_modules.include?(:confirmable)
|
34
|
+
result
|
35
|
+
end
|
36
|
+
|
37
|
+
def role_names
|
38
|
+
roles.pluck(:name).sort.join(', ')
|
39
|
+
end
|
40
|
+
|
41
|
+
define_method Identity.admin_role do
|
42
|
+
has_role?(Identity.admin_role)
|
43
|
+
end
|
44
|
+
alias_method Identity.admin_predicate, Identity.admin_role
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="col-sm-6">
|
3
|
+
|
4
|
+
<%= bootstrap_devise_error_messages! %>
|
5
|
+
<div class="panel panel-default">
|
6
|
+
<div class="panel-heading">
|
7
|
+
<h4><%= t('.resend_confirmation_instructions', :default => 'Resend confirmation instructions') %></h4>
|
8
|
+
</div>
|
9
|
+
<div class="panel-body">
|
10
|
+
<%= form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post, role: "form" }) do |f| %>
|
11
|
+
<div class="form-group">
|
12
|
+
<%= f.label :email %>
|
13
|
+
<%= f.email_field :email, autofocus: true, class: "form-control" %>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<%= f.submit t('.resend_confirmation_instructions', :default => 'Resend confirmation instructions'), class: "btn btn-primary" %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<%= render "devise/shared/links" %>
|
22
|
+
</div>
|
23
|
+
</div>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<p><%= t('.greeting', :recipient => @resource.email, :default => "Welcome #{@resource.email}!") %></p>
|
2
|
+
|
3
|
+
<p><%= t('.instruction', :default => "You can confirm your account email through the link below:") %></p>
|
4
|
+
|
5
|
+
<p><%= link_to t('.action', :default => "Confirm my account"),
|
6
|
+
confirmation_url(@resource, :confirmation_token => @token, locale: I18n.locale) %></p>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<p><%= t('.greeting', :recipient => @resource.email, :default => "Hello #{@resource.email}!") %></p>
|
2
|
+
|
3
|
+
<p><%= t('.instruction', :default => "Someone has requested a link to change your password, and you can do this through the link below.") %></p>
|
4
|
+
|
5
|
+
<p><%= link_to t('.action', :default => "Change my password"), edit_password_url(@resource, :reset_password_token => @token, locale: I18n.locale) %></p>
|
6
|
+
|
7
|
+
<p><%= t('.instruction_2', :default => "If you didn't request this, please ignore this email.") %></p>
|
8
|
+
<p><%= t('.instruction_3', :default => "Your password won't change until you access the link above and create a new one.") %></p>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<p><%= t('.greeting', :recipient => @resource.email, :default => "Hello #{@resource.email}!") %></p>
|
2
|
+
|
3
|
+
<p><%= t('.message', :default => "Your account has been locked due to an excessive amount of unsuccessful sign in attempts.") %></p>
|
4
|
+
|
5
|
+
<p><%= t('.instruction', :default => "Click the link below to unlock your account:") %></p>
|
6
|
+
|
7
|
+
<p><%= link_to t('.action', :default => "Unlock my account"), unlock_url(@resource, :unlock_token => @resource.unlock_token, locale: I18n.locale) %></p>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="col-sm-6">
|
3
|
+
<%= bootstrap_devise_error_messages! %>
|
4
|
+
<div class="panel panel-default">
|
5
|
+
<div class="panel-heading">
|
6
|
+
<h4><%= t('.change_your_password', :default => 'Change your password') %></h4>
|
7
|
+
</div>
|
8
|
+
<div class="panel-body">
|
9
|
+
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put, role: "form" }) do |f| %>
|
10
|
+
<%= f.hidden_field :reset_password_token %>
|
11
|
+
|
12
|
+
<div class="form-group">
|
13
|
+
<%= f.label :password, t('.new_password', :default => 'New password') %>
|
14
|
+
<%= f.password_field :password, autofocus: true, class: "form-control" %>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div class="form-group">
|
18
|
+
<%= f.label :password_confirmation, t('.confirm_new_password', :default => 'Confirm new password') %>
|
19
|
+
<%= f.password_field :password_confirmation, class: "form-control" %>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<%= f.submit t('.change_my_password', :default => 'Change my password'), class: "btn btn-primary" %>
|
23
|
+
<% end %>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
<%= render "devise/shared/links" %>
|
27
|
+
</div>
|
28
|
+
</div>
|