pollett 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +81 -0
  4. data/Rakefile +25 -0
  5. data/app/controllers/concerns/pollett/controller.rb +37 -0
  6. data/app/controllers/pollett/application_controller.rb +4 -0
  7. data/app/controllers/pollett/keys_controller.rb +5 -0
  8. data/app/controllers/pollett/sessions_controller.rb +5 -0
  9. data/app/controllers/pollett/users_controller.rb +5 -0
  10. data/app/mailers/pollett/mailer.rb +5 -0
  11. data/app/models/concerns/pollett/user.rb +40 -0
  12. data/app/models/pollett/context.rb +5 -0
  13. data/app/models/pollett/key.rb +5 -0
  14. data/app/models/pollett/session.rb +5 -0
  15. data/app/serializers/pollett/key_serializer.rb +5 -0
  16. data/app/serializers/pollett/session_serializer.rb +5 -0
  17. data/app/serializers/user_serializer.rb +3 -0
  18. data/app/services/pollett/authenticate_user.rb +5 -0
  19. data/app/services/pollett/change_password.rb +5 -0
  20. data/app/services/pollett/create_session.rb +5 -0
  21. data/app/services/pollett/register_user.rb +5 -0
  22. data/app/services/pollett/reset_password.rb +5 -0
  23. data/app/views/pollett/mailer/reset.text.erb +5 -0
  24. data/app/views/pollett/mailer/welcome.text.erb +1 -0
  25. data/config/locales/en.yml +14 -0
  26. data/config/routes.rb +11 -0
  27. data/db/migrate/20150226024506_create_pollett_contexts.rb +21 -0
  28. data/lib/generators/pollett/install/install_generator.rb +123 -0
  29. data/lib/generators/pollett/install/templates/db/migrate/add_pollett_to_users.rb +21 -0
  30. data/lib/generators/pollett/install/templates/db/migrate/create_users.rb +15 -0
  31. data/lib/generators/pollett/install/templates/initializer.rb +3 -0
  32. data/lib/generators/pollett/install/templates/user.rb +3 -0
  33. data/lib/pollett.rb +20 -0
  34. data/lib/pollett/concerns.rb +5 -0
  35. data/lib/pollett/concerns/controllers.rb +3 -0
  36. data/lib/pollett/concerns/controllers/keys_controller.rb +37 -0
  37. data/lib/pollett/concerns/controllers/sessions_controller.rb +43 -0
  38. data/lib/pollett/concerns/controllers/users_controller.rb +28 -0
  39. data/lib/pollett/concerns/mailers.rb +1 -0
  40. data/lib/pollett/concerns/mailers/mailer.rb +24 -0
  41. data/lib/pollett/concerns/models.rb +3 -0
  42. data/lib/pollett/concerns/models/context.rb +42 -0
  43. data/lib/pollett/concerns/models/key.rb +13 -0
  44. data/lib/pollett/concerns/models/session.rb +20 -0
  45. data/lib/pollett/concerns/serializers.rb +2 -0
  46. data/lib/pollett/concerns/serializers/context_serializer.rb +21 -0
  47. data/lib/pollett/concerns/serializers/user_serializer.rb +16 -0
  48. data/lib/pollett/concerns/services.rb +5 -0
  49. data/lib/pollett/concerns/services/authenticate_user.rb +21 -0
  50. data/lib/pollett/concerns/services/change_password.rb +21 -0
  51. data/lib/pollett/concerns/services/create_session.rb +27 -0
  52. data/lib/pollett/concerns/services/register_user.rb +29 -0
  53. data/lib/pollett/concerns/services/reset_password.rb +27 -0
  54. data/lib/pollett/configuration.rb +34 -0
  55. data/lib/pollett/engine.rb +12 -0
  56. data/lib/pollett/rspec.rb +6 -0
  57. data/lib/pollett/testing/request_helper.rb +106 -0
  58. data/lib/pollett/version.rb +3 -0
  59. data/spec/dummy/README.rdoc +28 -0
  60. data/spec/dummy/Rakefile +6 -0
  61. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  62. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  63. data/spec/dummy/app/controllers/application_controller.rb +12 -0
  64. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  65. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  66. data/spec/dummy/app/models/user.rb +3 -0
  67. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  68. data/spec/dummy/app/views/layouts/mailer.text.erb +6 -0
  69. data/spec/dummy/bin/bundle +3 -0
  70. data/spec/dummy/bin/rails +4 -0
  71. data/spec/dummy/bin/rake +4 -0
  72. data/spec/dummy/bin/setup +29 -0
  73. data/spec/dummy/config.ru +4 -0
  74. data/spec/dummy/config/application.rb +32 -0
  75. data/spec/dummy/config/boot.rb +5 -0
  76. data/spec/dummy/config/database.yml +85 -0
  77. data/spec/dummy/config/environment.rb +5 -0
  78. data/spec/dummy/config/environments/development.rb +41 -0
  79. data/spec/dummy/config/environments/production.rb +79 -0
  80. data/spec/dummy/config/environments/test.rb +42 -0
  81. data/spec/dummy/config/initializers/active_model_serializers.rb +1 -0
  82. data/spec/dummy/config/initializers/assets.rb +11 -0
  83. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  84. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  85. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  86. data/spec/dummy/config/initializers/inflections.rb +16 -0
  87. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  88. data/spec/dummy/config/initializers/session_store.rb +3 -0
  89. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  90. data/spec/dummy/config/locales/en.yml +23 -0
  91. data/spec/dummy/config/routes.rb +3 -0
  92. data/spec/dummy/config/secrets.yml +22 -0
  93. data/spec/dummy/db/migrate/20150226030314_enable_uuid_extension.rb +5 -0
  94. data/spec/dummy/db/migrate/20150226030315_create_users.rb +15 -0
  95. data/spec/dummy/db/migrate/20150226030316_create_pollett_contexts.pollett.rb +22 -0
  96. data/spec/dummy/db/schema.rb +49 -0
  97. data/spec/dummy/log/development.log +1315 -0
  98. data/spec/dummy/log/test.log +181283 -0
  99. data/spec/dummy/public/404.html +67 -0
  100. data/spec/dummy/public/422.html +67 -0
  101. data/spec/dummy/public/500.html +66 -0
  102. data/spec/dummy/public/favicon.ico +0 -0
  103. data/spec/factories/pollett_context.rb +5 -0
  104. data/spec/factories/pollett_key.rb +5 -0
  105. data/spec/factories/pollett_session.rb +5 -0
  106. data/spec/factories/user.rb +7 -0
  107. data/spec/mailers/pollett/mailer_spec.rb +73 -0
  108. data/spec/rails_helper.rb +19 -0
  109. data/spec/requests/keys_spec.rb +67 -0
  110. data/spec/requests/sessions_spec.rb +176 -0
  111. data/spec/requests/user_spec.rb +41 -0
  112. data/spec/spec_helper.rb +9 -0
  113. data/spec/support/email_helper.rb +9 -0
  114. metadata +323 -0
@@ -0,0 +1,21 @@
1
+ class AddPollettToUsers < ActiveRecord::Migration
2
+ def up
3
+ change_table :users do |t|
4
+ <% config[:new_columns].values.each do |column| -%>
5
+ <%= column %>
6
+ <% end -%>
7
+ end
8
+
9
+ <% config[:new_indexes].values.each do |index| -%>
10
+ <%= index %>
11
+ <% end -%>
12
+ end
13
+
14
+ def down
15
+ change_table :users do |t|
16
+ <% if config[:new_columns].any? -%>
17
+ t.remove <%= new_columns.keys.map { |column| ":#{column}" }.join(",") %>
18
+ <% end -%>
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def change
3
+ create_table :users, id: :uuid do |t|
4
+ t.string :name, null: false
5
+ t.string :email, null: false
6
+ t.string :password_digest, null: false
7
+ t.string :reset_token
8
+
9
+ t.timestamps null: false
10
+ end
11
+
12
+ add_index :users, :email, unique: true
13
+ add_index :users, :reset_token, unique: true
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ Pollett.configure do |config|
2
+ config.reset_url = ->(token) { "https://example.com/#{token}/reset" }
3
+ end
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ include Pollett::User
3
+ end
data/lib/pollett.rb ADDED
@@ -0,0 +1,20 @@
1
+ require "active_model_serializers"
2
+ require "servitore"
3
+
4
+ require "pollett/concerns"
5
+ require "pollett/configuration"
6
+ require "pollett/engine"
7
+
8
+ module Pollett
9
+ Unauthorized = Class.new(StandardError)
10
+
11
+ TOKEN_LENGTH = 32
12
+
13
+ def self.generate_token(length = TOKEN_LENGTH)
14
+ SecureRandom.urlsafe_base64(length)
15
+ end
16
+
17
+ def self.reset_url(token)
18
+ config.reset_url.call(token)
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ require "pollett/concerns/controllers"
2
+ require "pollett/concerns/mailers"
3
+ require "pollett/concerns/models"
4
+ require "pollett/concerns/serializers"
5
+ require "pollett/concerns/services"
@@ -0,0 +1,3 @@
1
+ require "pollett/concerns/controllers/users_controller"
2
+ require "pollett/concerns/controllers/sessions_controller"
3
+ require "pollett/concerns/controllers/keys_controller"
@@ -0,0 +1,37 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Controllers
4
+ module KeysController
5
+ extend ActiveSupport::Concern
6
+
7
+ def index
8
+ render_list(scoped)
9
+ end
10
+
11
+ def create
12
+ key = current_user.keys.create!(safe_params)
13
+ render json: key, status: :created
14
+ end
15
+
16
+ def show
17
+ key = scoped.find(params[:id])
18
+ render json: key, status: :ok
19
+ end
20
+
21
+ def destroy
22
+ scoped.find(params[:id]).revoke!
23
+ head :no_content
24
+ end
25
+
26
+ private
27
+ def safe_params
28
+ params.permit(:client)
29
+ end
30
+
31
+ def scoped
32
+ current_user.keys.active
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,43 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Controllers
4
+ module SessionsController
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ skip_authentication only: [:create, :forgot]
9
+ end
10
+
11
+ def index
12
+ render_list(scoped)
13
+ end
14
+
15
+ def show
16
+ session = scoped.find(params[:id])
17
+ render json: session, status: :ok
18
+ end
19
+
20
+ def create
21
+ session = CreateSession.call(params)
22
+ activate_context(session)
23
+ render json: session, status: :created
24
+ end
25
+
26
+ def forgot
27
+ ResetPassword.call(params)
28
+ render json: { status: :accepted }, status: :accepted
29
+ end
30
+
31
+ def destroy
32
+ scoped.find(params[:id]).revoke!
33
+ head :no_content
34
+ end
35
+
36
+ private
37
+ def scoped
38
+ current_user.sessions.active
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,28 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Controllers
4
+ module UsersController
5
+ extend ActiveSupport::Concern
6
+
7
+ def show
8
+ render json: current_user, status: :ok
9
+ end
10
+
11
+ def update
12
+ current_user.update!(safe_params)
13
+ render json: current_user, status: :ok
14
+ end
15
+
16
+ def destroy
17
+ current_user.destroy
18
+ head :no_content
19
+ end
20
+
21
+ private
22
+ def safe_params
23
+ params.permit(:name, :email, :password)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1 @@
1
+ require "pollett/concerns/mailers/mailer"
@@ -0,0 +1,24 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Mailers
4
+ module Mailer
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ default from: Pollett.config.from_email if Pollett.config.from_email
9
+ end
10
+
11
+ def welcome(user)
12
+ @user = user
13
+ mail(to: user.email)
14
+ end
15
+
16
+ def reset(user)
17
+ @user = user
18
+ @url = Pollett.reset_url(user.reset_token)
19
+ mail(to: user.email)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ require "pollett/concerns/models/context"
2
+ require "pollett/concerns/models/session"
3
+ require "pollett/concerns/models/key"
@@ -0,0 +1,42 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Models
4
+ module Context
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ belongs_to :user, class_name: Pollett.config.user_model_name
9
+
10
+ scope :active, -> { where("((type = 'Pollett::Session' AND accessed_at >= ?) OR (type = 'Pollett::Key')) AND revoked_at IS NULL", Pollett.config.timeout.ago) }
11
+ end
12
+
13
+ module ClassMethods
14
+ def authenticate(id)
15
+ active.find_by(id: id)
16
+ end
17
+ end
18
+
19
+ def revoked
20
+ revoked_at?
21
+ end
22
+
23
+ def active
24
+ !revoked
25
+ end
26
+
27
+ def access(request)
28
+ update({
29
+ accessed_at: current_time_from_proper_timezone,
30
+ ip: request.remote_ip,
31
+ user_agent: request.user_agent
32
+ })
33
+ end
34
+
35
+ def revoke!
36
+ self.revoked_at ||= current_time_from_proper_timezone
37
+ save!
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,13 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Models
4
+ module Key
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ validates :client, presence: true
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Models
4
+ module Session
5
+ extend ActiveSupport::Concern
6
+
7
+ CLIENT = "App"
8
+
9
+ included do
10
+ before_create :set_client
11
+ end
12
+
13
+ private
14
+ def set_client
15
+ self.client = CLIENT
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,2 @@
1
+ require "pollett/concerns/serializers/user_serializer"
2
+ require "pollett/concerns/serializers/context_serializer"
@@ -0,0 +1,21 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Serializers
4
+ module ContextSerializer
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attributes :client,
9
+ :active,
10
+ :ip,
11
+ :user_agent,
12
+ :accessed_at,
13
+ :created_at,
14
+ :updated_at
15
+
16
+ belongs_to :user
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Serializers
4
+ module UserSerializer
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attributes :created_at,
9
+ :updated_at,
10
+ :name,
11
+ :email
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ require "pollett/concerns/services/authenticate_user"
2
+ require "pollett/concerns/services/change_password"
3
+ require "pollett/concerns/services/create_session"
4
+ require "pollett/concerns/services/register_user"
5
+ require "pollett/concerns/services/reset_password"
@@ -0,0 +1,21 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Services
4
+ module AuthenticateUser
5
+ extend ActiveSupport::Concern
6
+
7
+ include Servitore::Service
8
+
9
+ included do
10
+ param_reader :email, :password
11
+ end
12
+
13
+ def call
14
+ Pollett.config.user_model.find_by_normalized_email(email).tap do |u|
15
+ raise Unauthorized unless u && u.authenticate(password)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Services
4
+ module ChangePassword
5
+ extend ActiveSupport::Concern
6
+
7
+ include Servitore::Service
8
+
9
+ included do
10
+ param_reader :token, :password
11
+ end
12
+
13
+ def call
14
+ Pollett.config.user_model.find_by!(reset_token: token).tap do |u|
15
+ u.update!(password: password, reset_token: nil)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Services
4
+ module CreateSession
5
+ extend ActiveSupport::Concern
6
+
7
+ include Servitore::Service
8
+
9
+ def call
10
+ user = service.call(_params)
11
+ user.sessions.create!
12
+ end
13
+
14
+ private
15
+ def service
16
+ @service ||= if _params.key?(:name)
17
+ Pollett::RegisterUser
18
+ elsif _params.key?(:token)
19
+ Pollett::ChangePassword
20
+ else
21
+ Pollett::AuthenticateUser
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ module Pollett
2
+ module Concerns
3
+ module Services
4
+ module RegisterUser
5
+ extend ActiveSupport::Concern
6
+
7
+ include Servitore::Service
8
+
9
+ PERMITTED = [:name, :email, :password]
10
+
11
+ def call
12
+ Pollett.config.user_model.create!(safe_params).tap do |user|
13
+ deliver_email(user) if Pollett.config.send_welcome_email
14
+ end
15
+ end
16
+
17
+ private
18
+ def safe_params
19
+ permitted = Pollett.config.whitelist | PERMITTED
20
+ _params.permit(*permitted)
21
+ end
22
+
23
+ def deliver_email(user)
24
+ Mailer.welcome(user).deliver_later
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end