tyrant 0.0.1 → 0.0.2
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 +4 -4
- data/Gemfile +2 -0
- data/README.md +47 -16
- data/lib/tyrant.rb +4 -0
- data/lib/tyrant/authenticatable.rb +76 -0
- data/lib/tyrant/railtie.rb +16 -0
- data/lib/tyrant/session.rb +24 -0
- data/lib/tyrant/sign_up.rb +53 -0
- data/lib/tyrant/version.rb +1 -1
- data/tyrant.gemspec +8 -3
- metadata +77 -4
- data/bin/console +0 -14
- data/bin/setup +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0686d74d8af9df770a7c8eedd729b6e375e0bed2
|
4
|
+
data.tar.gz: f079966822ca11c34637655e8d520b96941f664e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b46e96e5e3c37e22069bd40c05633940ccd00974c0a6805f7805c793b518271e080c35b44c9107404c5577d1f3039554cf85546e2bd0d458c3c90d9d4b83a2f9
|
7
|
+
data.tar.gz: a716baf50d9fa237adc43eb47d0ec6da6e01dfeb0b565df26de551eb6a64ff11fffc7828c0820256ef6bc5d1a9e93968186b36f3b4f86fa1a8b405c5fce661de
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,38 +1,69 @@
|
|
1
1
|
# Tyrant
|
2
2
|
|
3
|
-
|
3
|
+
_"Freedom choked in dread we live, since tyrant was enthroned."_
|
4
4
|
|
5
|
-
|
5
|
+
Tyrant implements all common steps of authorization workflows using overridable _operations_. It allows a quick setup of sign in, sign up, forgot password, etc. Tryrant works well in Rails, but plays well with any Ruby environment.
|
6
6
|
|
7
|
-
|
7
|
+
Operations are provided for the following steps.
|
8
8
|
|
9
|
-
|
9
|
+
* SignIn
|
10
|
+
* Confirmed
|
11
|
+
* Hammer protection (3x wrong blabla)
|
12
|
+
* Sticky (Remember me)
|
13
|
+
* SignUp
|
14
|
+
* SignOut
|
15
|
+
* ResetPassword
|
16
|
+
* Forgot pw
|
17
|
+
|
18
|
+
|
19
|
+
## Operations
|
20
|
+
|
21
|
+
trb instead of pushing into controller
|
22
|
+
|
23
|
+
|
24
|
+
Tyrant exposes its public API using operations.
|
25
|
+
|
26
|
+
Operations are the pivotal element in the [Trailblazer architecture](https://github.com/apotonick/trailblazer). When it comes to customization, Tyrant doesn't rely on a "hopefully complete" configuration language as Devise does it.
|
27
|
+
|
28
|
+
Tyrant allows you to customize with Ruby. You can override entire workflow steps (operations), forms and validations (contracts) or methods using simple object-orientation and a clean API.
|
29
|
+
|
30
|
+
|
31
|
+
This means you can easily use them in Rails controllers.
|
10
32
|
|
11
33
|
```ruby
|
12
|
-
|
34
|
+
class SessionController < ApplicationController
|
35
|
+
def sign_in
|
36
|
+
run Tyrant::SignIn
|
37
|
+
end
|
13
38
|
```
|
14
39
|
|
15
|
-
|
40
|
+
You can also run the public API in any other Ruby environment, e.g. a console or a Roda action.
|
16
41
|
|
17
|
-
|
42
|
+
```ruby
|
43
|
+
Tyrant::SignIn.run(params)
|
44
|
+
```
|
18
45
|
|
19
|
-
|
46
|
+
Tyrant provides forms for all workflow steps. using Reform objects that are embedded into the operations.
|
20
47
|
|
21
|
-
$ gem install tyrant
|
22
48
|
|
23
|
-
|
49
|
+
=> Customize with inheritance, or override. Or just don't use the operation and write your own "step".
|
24
50
|
|
25
|
-
TODO: Write usage instructions here
|
26
51
|
|
27
|
-
##
|
52
|
+
## Installation
|
28
53
|
|
29
|
-
|
54
|
+
Add this line to your application's Gemfile:
|
30
55
|
|
31
|
-
|
56
|
+
```ruby
|
57
|
+
gem 'tyrant'
|
58
|
+
```
|
59
|
+
|
60
|
+
## Rails
|
32
61
|
|
33
|
-
|
62
|
+
Tyrant comes with a railtie to provide you an initializer. In Rails, add this to an initializer.
|
34
63
|
|
35
|
-
|
64
|
+
```ruby
|
65
|
+
require "tyrant/railtie"
|
66
|
+
```
|
36
67
|
|
37
68
|
|
38
69
|
## License
|
data/lib/tyrant.rb
CHANGED
@@ -0,0 +1,76 @@
|
|
1
|
+
require "disposable/twin/struct"
|
2
|
+
|
3
|
+
module Tyrant
|
4
|
+
# Encapsulates authentication management logic for a particular user.
|
5
|
+
class Authenticatable < Disposable::Twin
|
6
|
+
feature Default
|
7
|
+
feature Sync # FIXME: really?
|
8
|
+
|
9
|
+
property :auth_meta_data, default: Hash.new do
|
10
|
+
include Struct
|
11
|
+
property :confirmation_token
|
12
|
+
property :confirmed_at
|
13
|
+
property :confirmation_created_at
|
14
|
+
property :password_digest
|
15
|
+
end
|
16
|
+
|
17
|
+
module Confirm
|
18
|
+
def confirmable!
|
19
|
+
auth_meta_data.confirmation_token = "asdfasdfasfasfasdfasdf"
|
20
|
+
auth_meta_data.confirmation_created_at = DateTime.now
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
# without token, this decides whether the user model can be activated (e.g. via "set a password").
|
25
|
+
# with token, this additionally tests if the token is correct.
|
26
|
+
def confirmable?(token=false)
|
27
|
+
persisted_token = auth_meta_data.confirmation_token
|
28
|
+
|
29
|
+
# TODO: add expiry etc.
|
30
|
+
return false unless (persisted_token.is_a?(String) and persisted_token.size > 0)
|
31
|
+
|
32
|
+
return compare_token(token) unless token==false
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
# alias_method :confirmed?, :confirmable?
|
37
|
+
def confirmed?
|
38
|
+
not auth_meta_data.confirmed_at.nil?
|
39
|
+
end
|
40
|
+
|
41
|
+
def confirmed!(confirmed_at=DateTime.now)
|
42
|
+
auth_meta_data.confirmation_token = nil
|
43
|
+
auth_meta_data.confirmed_at = confirmed_at # TODO: test optional arg.
|
44
|
+
end
|
45
|
+
|
46
|
+
def confirmation_token
|
47
|
+
auth_meta_data.confirmation_token
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def compare_token(token)
|
52
|
+
token == auth_meta_data.confirmation_token
|
53
|
+
end
|
54
|
+
end # Confirm
|
55
|
+
include Confirm
|
56
|
+
|
57
|
+
|
58
|
+
require "bcrypt"
|
59
|
+
module Digest
|
60
|
+
def digest
|
61
|
+
return unless auth_meta_data.password_digest
|
62
|
+
BCrypt::Password.new(auth_meta_data.password_digest)
|
63
|
+
end
|
64
|
+
|
65
|
+
def digest!(password)
|
66
|
+
auth_meta_data.password_digest = BCrypt::Password.create(password)
|
67
|
+
end
|
68
|
+
|
69
|
+
def digest?(password)
|
70
|
+
digest == password
|
71
|
+
end
|
72
|
+
end
|
73
|
+
include Digest
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Tyrant
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
require "warden"
|
4
|
+
|
5
|
+
# DISCUSS: it will be configurable what user class etc. and might be moved to Ops.
|
6
|
+
config.app_middleware.use Warden::Manager do |config|
|
7
|
+
Warden::Manager.serialize_into_session do |user|
|
8
|
+
user.id
|
9
|
+
end
|
10
|
+
|
11
|
+
Warden::Manager.serialize_from_session do |id|
|
12
|
+
User.find_by(id: id)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Tyrant
|
2
|
+
# HTTP/Warden session-specific behavior.
|
3
|
+
class Session
|
4
|
+
def initialize(warden)
|
5
|
+
@warden = warden
|
6
|
+
end
|
7
|
+
|
8
|
+
def current_user
|
9
|
+
@warden.user
|
10
|
+
end
|
11
|
+
|
12
|
+
def signed_in?
|
13
|
+
@warden.user
|
14
|
+
end
|
15
|
+
|
16
|
+
def sign_in!(user)
|
17
|
+
@warden.set_user(user)
|
18
|
+
end
|
19
|
+
|
20
|
+
def sign_out!
|
21
|
+
@warden.logout
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "trailblazer/operation"
|
2
|
+
require "active_model"
|
3
|
+
require "reform/form/active_model/validations" # TODO: this will get replaced with Lotus.
|
4
|
+
require "reform/form/validation/unique_validator.rb"
|
5
|
+
module Tyrant
|
6
|
+
# SignUp will come and implement to-be-confirmed sign up.
|
7
|
+
class SignUp < Trailblazer::Operation
|
8
|
+
class Confirmed < Trailblazer::Operation
|
9
|
+
include CRUD
|
10
|
+
model User, :create
|
11
|
+
|
12
|
+
contract do
|
13
|
+
include Reform::Form::ActiveModel::Validations
|
14
|
+
|
15
|
+
property :email
|
16
|
+
property :password, virtual: true
|
17
|
+
property :confirm_password, virtual: true
|
18
|
+
|
19
|
+
validates :email, :password, :confirm_password, presence: true
|
20
|
+
# validates :email, email: true, unique: true
|
21
|
+
validate :password_ok?
|
22
|
+
|
23
|
+
private
|
24
|
+
# TODO: more, like minimum 6 chars, etc.
|
25
|
+
def password_ok?
|
26
|
+
return unless email and password
|
27
|
+
errors.add(:password, "Passwords don't match") if password != confirm_password
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
# sucessful signup:
|
33
|
+
# * hash password, set confirmed
|
34
|
+
# * hash password, set unconfirmed with token etc.
|
35
|
+
|
36
|
+
# * no password, unconfirmed, needs password.
|
37
|
+
def process(params)
|
38
|
+
validate(params[:user]) do |contract|
|
39
|
+
update!
|
40
|
+
|
41
|
+
contract.save # save User with email.
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def update!
|
46
|
+
auth = Tyrant::Authenticatable.new(contract.model)
|
47
|
+
auth.digest!(contract.password) # contract.auth_meta_data.password_digest = ..
|
48
|
+
auth.confirmed!
|
49
|
+
auth.sync
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/tyrant/version.rb
CHANGED
data/tyrant.gemspec
CHANGED
@@ -13,9 +13,6 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = "http://github.com/apotonick/tyrant"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
|
-
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
17
|
-
# delete this section to allow pushing this gem to any host.
|
18
|
-
|
19
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
17
|
spec.bindir = "exe"
|
21
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -24,4 +21,12 @@ Gem::Specification.new do |spec|
|
|
24
21
|
spec.add_development_dependency "bundler", "~> 1.10"
|
25
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
23
|
spec.add_development_dependency "minitest"
|
24
|
+
|
25
|
+
spec.add_development_dependency "activemodel"
|
26
|
+
|
27
|
+
spec.add_dependency "trailblazer"
|
28
|
+
spec.add_dependency "reform", "~> 2.0"
|
29
|
+
spec.add_dependency "disposable", ">= 0.1.11"
|
30
|
+
|
31
|
+
spec.add_dependency "bcrypt"
|
27
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tyrant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,76 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activemodel
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: trailblazer
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: reform
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: disposable
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.1.11
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.1.11
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: bcrypt
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
55
125
|
description: Agnostic authorization component for Trailblazer.
|
56
126
|
email:
|
57
127
|
- apotonick@gmail.com
|
@@ -65,9 +135,11 @@ files:
|
|
65
135
|
- LICENSE.txt
|
66
136
|
- README.md
|
67
137
|
- Rakefile
|
68
|
-
- bin/console
|
69
|
-
- bin/setup
|
70
138
|
- lib/tyrant.rb
|
139
|
+
- lib/tyrant/authenticatable.rb
|
140
|
+
- lib/tyrant/railtie.rb
|
141
|
+
- lib/tyrant/session.rb
|
142
|
+
- lib/tyrant/sign_up.rb
|
71
143
|
- lib/tyrant/version.rb
|
72
144
|
- tyrant.gemspec
|
73
145
|
homepage: http://github.com/apotonick/tyrant
|
@@ -95,3 +167,4 @@ signing_key:
|
|
95
167
|
specification_version: 4
|
96
168
|
summary: Agnostic authorization for Trailblazer.
|
97
169
|
test_files: []
|
170
|
+
has_rdoc:
|
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "tyrant"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start
|