tiny-gate 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e2bce2f666499553ac76c991fcdfc04beaee5fa0
4
+ data.tar.gz: 11605f938f0a40c913a275132e4eef9fe66a1921
5
+ SHA512:
6
+ metadata.gz: 4f5023915e8287d770247b8ab71c510c7daffd7e8cbd866d720e65bae6111794decc51d644361826fecf90d00da996bc717ae37206869cae0da8119fc9334cd5
7
+ data.tar.gz: 9c0beba8e5d0477cdc43a2db174c5b36858043c9542c688879ca28487d1b845c22314fadd4da6765275f1b038059b3c7d6d19f1c7b141bd4b411fd82531d8db0
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /gems/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /Gemfile.lock
11
+ .ruby-version
12
+ .ruby-gemset
13
+ .idea
14
+ tags*
15
+ *.pid
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.0
5
+ before_install: gem install bundler -v 1.12.5
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # v1.0.0 2018-06-17
2
+
3
+ ## BREAKING CHANGES
4
+
5
+ * Upgrade `dry-struct` to version `0.5.0`, drop support for version `0.4.0`
6
+ and lower
7
+ * `TinyGate::TestHelper::User#add_permission` must be called before requesting to server
8
+ * `TinyGate::TestHelper::User#current_permission` is first permission of signed in organization
9
+ * `UserClient.add_user` returns new user’s token instead of the whole user
10
+
11
+ [Compare 0.6.1...1.0.0](https://github.com/tinyhr/tiny-gate/compare/0.6.1...1.0.0)
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at hieuk09@gmail.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'multi_json'
5
+ gem 'webmock'
6
+ gem 'byebug'
7
+ end
8
+
9
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 TINYpulse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,165 @@
1
+ # TinyGate
2
+
3
+ This is a simple authentication client for all TINYpulse applications. This is
4
+ the gateway of everything, hence the name :P
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'tiny-gate'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ ```shell
17
+ $ bundle
18
+ ```
19
+
20
+ Or install it yourself as:
21
+
22
+ ```shell
23
+ $ gem install tiny-gate
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ### Configuration
29
+
30
+ ```ruby
31
+ require 'tiny_gate'
32
+
33
+ TinyGate::Client.configurate do |config|
34
+ config.app_id = ENV['APP_ID']
35
+ config.root_url = ENV['AUTHENTICATION_ROOT_URL']
36
+ end
37
+ ```
38
+
39
+ ### Initialize
40
+
41
+ ```ruby
42
+ require 'tiny_gate'
43
+
44
+ client = TinyGate::Client.new
45
+ # or
46
+ client = TinyGate::Client.new(ENV['AUTHENTICATION_ROOT_URL'], ENV['APP_ID'])
47
+ ```
48
+
49
+ ### Get login and logout url
50
+
51
+ ```ruby
52
+ client.login_url
53
+ client.logout
54
+ ```
55
+
56
+ ### Validate a validation ticket
57
+
58
+ ```ruby
59
+ result = client.validate(ticket: ticket)
60
+
61
+ if result.success?
62
+ login(result.global_user)
63
+ else
64
+ # send error message
65
+ end
66
+ ```
67
+
68
+ ### Check signed in status
69
+
70
+ ```ruby
71
+ client.signed_in?(token, user_id)
72
+ ```
73
+
74
+ ### Get current user
75
+
76
+ ```ruby
77
+ result = client.fetch_user(token, user_id)
78
+
79
+ if result.success?
80
+ user = result.global_user
81
+ puts user.email
82
+ puts user.id
83
+ puts user.token
84
+ puts user.active_permissions
85
+ else
86
+ # send error message
87
+ end
88
+ ```
89
+
90
+ ## Testing with Cucumber
91
+
92
+
93
+ ### Preparation
94
+
95
+ ```ruby
96
+ # Add to gemfile
97
+
98
+ group :test do
99
+ gem 'sinatra'
100
+ gem 'daemons'
101
+ end
102
+ ```
103
+
104
+ ### Interact using capybara & site_prism
105
+
106
+ ```ruby
107
+ class SignIn < SitePrism::Page
108
+ set_url "/login"
109
+
110
+ element :email_field, "input.form-control[name='session[email]']"
111
+ element :password_field, "input.form-control[name='session[password]']"
112
+ element :login_button, "button.btn-success"
113
+ end
114
+ ```
115
+
116
+ ### Create user & permission
117
+
118
+ User needs to have at least one permission before login. First permission will be used to determine current organization.
119
+
120
+ ```ruby
121
+ client.add_user(id: global_user_id, email: user_email, passsword: password)
122
+
123
+ # First permission is required
124
+ client.add_permission(
125
+ user_id: global_user_id,
126
+ role_id: global_role_id,
127
+ permission_id: global_permission_id,
128
+ organization_id: global_organization_id,
129
+ organization_name: global_organization_name, # nil if ommitted
130
+ app_id: app_id # nil if omitted
131
+ )
132
+ ```
133
+
134
+ ### Start server
135
+
136
+ ```ruby
137
+ # in env.rb
138
+
139
+ require 'tiny_gate/test_helper'
140
+
141
+ After do |scenario|
142
+ TinyGate::TestHelper.stop_server
143
+ end
144
+
145
+ AfterConfiguration do
146
+ TinyGate::TestHelper.start_server
147
+ end
148
+ ```
149
+
150
+ ## Development
151
+
152
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
153
+
154
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
155
+
156
+ ## Contributing
157
+
158
+ Bug reports and pull requests are welcome on GitHub at https://github.com/TINYhr/tiny-gate.
159
+ This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the
160
+ [Contributor Covenant](http://contributor-covenant.org) code of conduct.
161
+
162
+
163
+ ## License
164
+
165
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
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
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "tiny_gate"
5
+ require "tiny_gate/test_helper"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start
data/bin/rspec ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'rspec' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("rspec-core", "rspec")
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/tiny_gate.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'tiny_gate/version'
2
+ require 'tiny_gate/client'
3
+
4
+ module TinyGate
5
+ end
@@ -0,0 +1,78 @@
1
+ require 'dry-configurable'
2
+ require 'http'
3
+ require_relative 'types/session_response'
4
+ require_relative 'types/switch_org_response'
5
+
6
+ module TinyGate
7
+ class Client
8
+ extend Dry::Configurable
9
+
10
+ setting :root_url, ENV['AUTHENTICATION_ROOT_URL']
11
+ setting :app_id, ENV['APP_ID']
12
+ setting :callback_token, ENV['AUTHENTICATED_CALLBACK_TOKEN']
13
+
14
+ def initialize(root_url = self.class.config.root_url, app_id = self.class.config.app_id, callback_token = self.class.config.callback_token)
15
+ @root_url = root_url
16
+ @app_id = app_id
17
+ @callback_token = callback_token
18
+ end
19
+
20
+ def login_url
21
+ "#{root_url}/auth/sessions/new?app_id=#{app_id}#{callback_token_params}"
22
+ end
23
+
24
+ def logout_url
25
+ "#{root_url}/signout"
26
+ end
27
+
28
+ def validate(payload)
29
+ response = HTTP.post(validate_url, json: payload.merge(app_id: app_id))
30
+ Types::SessionResponse.new(response)
31
+ end
32
+
33
+ def signed_in?(token, user_id)
34
+ response = HTTP.post(validate_signed_in_url, json: {user_id: user_id, token: token, app_id: app_id})
35
+ response.status == 200
36
+ end
37
+
38
+ def fetch_user(token, user_id)
39
+ response = HTTP.post(me_url, json: {user_id: user_id, token: token, app_id: app_id})
40
+ Types::SessionResponse.new(response)
41
+ end
42
+
43
+ def switch_org(token, organization_id, user_id)
44
+ response = HTTP.post(switch_org_url, json: {token: token, organization_id: organization_id, user_id: user_id, app_id: app_id})
45
+ Types::SwitchOrgResponse.new(response).new_token_url
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :root_url, :app_id, :callback_token
51
+
52
+ def callback_token_params
53
+ if callback_token
54
+ "&callback_token=#{callback_token}"
55
+ end
56
+ end
57
+
58
+ def validate_url
59
+ "#{auth_base_url}/validate"
60
+ end
61
+
62
+ def validate_signed_in_url
63
+ "#{auth_base_url}/signed_in"
64
+ end
65
+
66
+ def me_url
67
+ "#{auth_base_url}/me"
68
+ end
69
+
70
+ def auth_base_url
71
+ "#{root_url}/auth/sessions"
72
+ end
73
+
74
+ def switch_org_url
75
+ "#{root_url}/auth/sessions/switch_org"
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,51 @@
1
+ require 'ostruct'
2
+ require 'securerandom'
3
+ require 'daemons'
4
+ require 'rack/handler/webrick'
5
+ require 'sinatra'
6
+ require 'tiny_gate/types'
7
+
8
+ require_relative 'test_helper/user'
9
+ require_relative 'test_helper/user_repository'
10
+ require_relative 'test_helper/user_client'
11
+ require_relative 'test_helper/application_controller'
12
+ require_relative 'test_helper/sessions_controller'
13
+ require_relative 'test_helper/users_controller'
14
+ require_relative 'test_helper/dummy_server'
15
+
16
+ module TinyGate
17
+ module TestHelper
18
+ def self.init!
19
+ TinyGate::Client.configure do |config|
20
+ config.root_url = TinyGate::TestHelper::UserClient::ROOT_URL
21
+ end
22
+ end
23
+
24
+ def self.run_server
25
+ Rack::Handler::WEBrick.run(
26
+ DummyServer,
27
+ Host: 'localhost',
28
+ Port: 31338
29
+ )
30
+ end
31
+
32
+ def self.start_server
33
+ Daemons.call(multiple: true, shush: true) do
34
+ run_server
35
+ end
36
+ sleep 1
37
+ end
38
+
39
+ def self.stop_server
40
+ return unless Daemons.group
41
+
42
+ Daemons.group.applications.each do |application|
43
+ begin
44
+ Process.kill('KILL', application.pid.pid)
45
+ Process.wait(application.pid.pid)
46
+ rescue
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ module TinyGate
2
+ module TestHelper
3
+ class ApplicationController < Sinatra::Base
4
+
5
+ configure do
6
+ set :environment, ENV['SINATRA_ENV'] || ENV['RACK_ENV']
7
+ set :root, __dir__
8
+ set :views, File.join(__dir__, 'views')
9
+ end
10
+
11
+ get '/' do
12
+ erb :'/welcome.html'
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ module TinyGate
2
+ module TestHelper
3
+ DummyServer = Rack::Builder.new do
4
+ use SessionsController
5
+ use UsersController
6
+ run ApplicationController
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,88 @@
1
+ require_relative 'user_repository'
2
+
3
+ module TinyGate
4
+ module TestHelper
5
+ class SessionsController < ApplicationController
6
+ RESULT_URL = 'http://app.lvh.me:31337/session/callback?validation_ticket=%{user_token}'
7
+
8
+ get '/auth/sessions/new' do
9
+ erb :'/sessions/new.html'
10
+ end
11
+
12
+ post '/auth/sessions' do
13
+ user = UserRepository.find_by_email(params[:session][:email])
14
+ if user && user.password == params[:session][:password]
15
+ redirect to(format(RESULT_URL, user_token: user.token))
16
+ else
17
+ "There is no user with email #{params[:session][:email]} and password: #{params[:session][:password]}"
18
+ end
19
+ end
20
+
21
+ post '/auth/sessions/validate' do
22
+ content_type :json
23
+
24
+ data = request.env['rack.input'].read
25
+ json_params = JSON.parse(data)
26
+ user = UserRepository.find_by_token(json_params['ticket'])
27
+
28
+ if user
29
+ user.data.to_json
30
+ else
31
+ status 401
32
+ { errors: 'Invalid Token' }.to_json
33
+ end
34
+ end
35
+
36
+ post '/auth/sessions/signed_in' do
37
+ data = request.env['rack.input'].read
38
+ json_params = JSON.parse(data)
39
+ user = UserRepository.find_by_id(json_params['user_id'])
40
+
41
+ if user && user.token == json_params['token']
42
+ status 200
43
+ else
44
+ status 401
45
+ body 'Invalid Token'
46
+ end
47
+ end
48
+
49
+ post '/auth/sessions/me' do
50
+ content_type :json
51
+
52
+ data = request.env['rack.input'].read
53
+ json_params = JSON.parse(data)
54
+ user = UserRepository.find_by_id(json_params['user_id'])
55
+
56
+ if user && user.token == json_params['token']
57
+ user.sign_in
58
+ user.data.to_json
59
+ else
60
+ status 401
61
+ { errors: 'Invalid Token' }.to_json
62
+ end
63
+ end
64
+
65
+ post '/auth/sessions/switch_org' do
66
+ content_type :json
67
+
68
+ data = request.env['rack.input'].read
69
+ json_params = JSON.parse(data)
70
+ user_id = json_params['user_id']
71
+ organization_id = json_params['organization_id']
72
+ user = UserRepository.find_by_id(user_id)
73
+
74
+ if user
75
+ user.sign_in(organization_id)
76
+ url = format(RESULT_URL, user_token: user.token)
77
+ else
78
+ url = ''
79
+ status 403
80
+ end
81
+ { url: url }.to_json
82
+ end
83
+
84
+ post '/signout' do
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,75 @@
1
+ module TinyGate
2
+ module TestHelper
3
+ class User
4
+ attr_reader :id, :email, :password, :first_name, :last_name, :token
5
+
6
+ def initialize(id, email, password, first_name = 'First', last_name = 'Last')
7
+ @id = id
8
+ @email = email
9
+ @password = password
10
+ @first_name = first_name
11
+ @last_name = last_name
12
+ @token = SecureRandom.hex
13
+ @permissions = Set.new
14
+ @current_organization_id = nil
15
+ end
16
+
17
+ def sign_in(organization_id = nil)
18
+ @current_organization_id = organization_id
19
+ end
20
+
21
+ def add_permission(permission_id, role_id, role_name, organization_id, organization_name = nil, app_id = nil)
22
+ @permissions << OpenStruct.new(
23
+ id: permission_id,
24
+ role_id: role_id,
25
+ role_name: role_name,
26
+ organization_id: organization_id,
27
+ organization_name: organization_name,
28
+ app_id: app_id
29
+ )
30
+ end
31
+
32
+ def data
33
+ {
34
+ id: id,
35
+ email: email,
36
+ token: token,
37
+ first_name: first_name,
38
+ last_name: last_name,
39
+ current_permission: current_permission,
40
+ active_permissions: active_permissions
41
+ }
42
+ end
43
+
44
+ private
45
+
46
+ def current_organization_id
47
+ @current_organization_id || @permissions.first.organization_id
48
+ end
49
+
50
+ def current_permission
51
+ to_hash(find_current_permission)
52
+ end
53
+
54
+ def find_current_permission
55
+ current_organization_id && @permissions.detect { |p| p.organization_id == current_organization_id }
56
+ end
57
+
58
+ def active_permissions
59
+ @permissions.map { |permission| to_hash(permission) }
60
+ end
61
+
62
+ def to_hash(permission)
63
+ {
64
+ id: permission.id,
65
+ role_id: permission.role_id,
66
+ role_name: permission.role_name,
67
+ organization_id: permission.organization_id,
68
+ organization_name: permission.organization_name,
69
+ app_id: permission.app_id,
70
+ user_id: id
71
+ }
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,36 @@
1
+ require 'http'
2
+
3
+ module TinyGate
4
+ module TestHelper
5
+ class UserClient
6
+ ROOT_URL = 'http://localhost:31338'
7
+
8
+ def initialize(url = ROOT_URL)
9
+ @url = url
10
+ end
11
+
12
+ def add_user(payload)
13
+ response = HTTP.post(add_user_url, form: payload)
14
+ response.body
15
+ end
16
+
17
+ def add_permission(payload)
18
+ HTTP.post(add_permission_url, form: payload)
19
+ end
20
+
21
+ def reset
22
+ HTTP.post("#{@url}/reset")
23
+ end
24
+
25
+ private
26
+
27
+ def add_user_url
28
+ "#{@url}/add_user"
29
+ end
30
+
31
+ def add_permission_url
32
+ "#{@url}/add_permission"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'user'
2
+
3
+ module TinyGate
4
+ module TestHelper
5
+ class UserRepository
6
+ @@users = Set.new
7
+
8
+ class << self
9
+ def add_user(id:, email:, password:, first_name: 'First', last_name: 'Last')
10
+ User.new(id, email, password, first_name, last_name).tap do |user|
11
+ @@users << user
12
+ end
13
+ end
14
+
15
+ def find_by_email(email)
16
+ @@users.find { |user| user.email == email }
17
+ end
18
+
19
+ def find_by_id(id)
20
+ @@users.find { |user| user.id.to_s == id.to_s }
21
+ end
22
+
23
+ def find_by_token(token)
24
+ @@users.find { |user| user.token == token }
25
+ end
26
+
27
+ def reset
28
+ @@users = Set.new
29
+ end
30
+
31
+ def users
32
+ @@users
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'user_repository'
2
+
3
+ module TinyGate
4
+ module TestHelper
5
+ class UsersController < ApplicationController
6
+
7
+ post '/add_user' do
8
+ user = UserRepository.add_user(
9
+ id: params[:id],
10
+ email: params[:email],
11
+ password: params[:password],
12
+ first_name: params[:first_name],
13
+ last_name: params[:last_name]
14
+ )
15
+ user.token
16
+ end
17
+
18
+ post '/add_permission' do
19
+ user = UserRepository.find_by_id(params[:user_id])
20
+ user.add_permission(
21
+ params[:permission_id],
22
+ params[:role_id],
23
+ params[:role_name],
24
+ params[:organization_id],
25
+ params[:organization_name],
26
+ params[:app_id]
27
+ )
28
+ status 200
29
+ end
30
+
31
+ post '/reset' do
32
+ UserRepository.reset
33
+ status 200
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <meta charset="utf-8" />
4
+ <title>Mock Server</title>
5
+ </head>
6
+ <body>
7
+ <div class="wrapper">
8
+ <%= yield %>
9
+ </div>
10
+ </body>
@@ -0,0 +1,7 @@
1
+ <form action="/auth/sessions" method="post">
2
+ <label for="email">Email:</label>
3
+ <input id="email" type="text" class="form-control email" name="session[email]">
4
+ <label for="password">Password:</label>
5
+ <input id="password" type="text" class="form-control password" name="session[password]">
6
+ <button type="submit" class="btn-success">Sign In</button>
7
+ </form>
@@ -0,0 +1,3 @@
1
+ <h1 style="text-align: center;">
2
+ Welcome to Mock Server!
3
+ </h1>
@@ -0,0 +1,7 @@
1
+ require 'dry-types'
2
+
3
+ module TinyGate
4
+ module Types
5
+ include Dry::Types.module
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ require 'dry-struct'
2
+ require_relative '../types'
3
+
4
+ module TinyGate
5
+ module Types
6
+ class ActivePermission < Dry::Struct
7
+ transform_keys(&:to_sym)
8
+
9
+ attribute :id, Types::Integer
10
+ attribute :app_id, Types::Integer
11
+ attribute :user_id, Types::Integer
12
+ attribute :organization_id, Types::Integer
13
+ attribute :organization_name, Types::String
14
+ attribute :role_id, Types::Integer
15
+ attribute :role_name, Types::String
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ require 'json'
2
+ require_relative 'user'
3
+
4
+ module TinyGate
5
+ module Types
6
+ class SessionResponse
7
+ attr_reader :body
8
+
9
+ def initialize(response)
10
+ @response = response
11
+ @body = JSON.parse(response.body)
12
+ end
13
+
14
+ def success?
15
+ response.status == 200
16
+ end
17
+
18
+ def global_user
19
+ Types::User[body]
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :response
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ require 'json'
2
+
3
+ module TinyGate
4
+ module Types
5
+ class SwitchOrgResponse
6
+
7
+ def initialize(response)
8
+ @response = response
9
+ @body = JSON.parse(response.body)
10
+ end
11
+
12
+ def success?
13
+ response.status == 200
14
+ end
15
+
16
+ def new_token_url
17
+ @body['url']
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :response
23
+ attr_reader :body
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ require 'dry-struct'
2
+ require_relative '../types'
3
+ require_relative 'active_permission'
4
+
5
+ module TinyGate
6
+ module Types
7
+ class User < Dry::Struct
8
+ transform_keys(&:to_sym)
9
+
10
+ attribute :id, Types::Integer
11
+ attribute :email, Types::String
12
+ attribute :first_name, Types::String
13
+ attribute :last_name, Types::String
14
+ attribute :created_at, Types::DateTime.meta(omittable: true)
15
+ attribute :avatar_url, Types::String.meta(omittable: true)
16
+ attribute :token, Types::String
17
+ attribute :admin_id, Types::Integer.meta(omittable: true)
18
+ attribute :current_permission, Types::ActivePermission.meta(omittable: true)
19
+ attribute :active_permissions, Types::Strict::Array.of(Types::ActivePermission)
20
+
21
+ def data
22
+ {
23
+ user_id: id,
24
+ token: token
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module TinyGate
2
+ VERSION = '1.0.0'
3
+ end
data/tiny-gate.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tiny_gate/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'tiny-gate'
8
+ spec.version = TinyGate::VERSION
9
+ spec.authors = ['TINYpulse']
10
+ spec.email = ['devops@tinypulse.com']
11
+
12
+ spec.summary = %q{An authentication client for all TINYpulse apps}
13
+ spec.description = %q{This is an authentication client for all TINYpulse apps which use single sign on.}
14
+ spec.homepage = 'https://github.com/TINYhr/tiny-gate'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'dry-configurable'
23
+ spec.add_dependency 'dry-struct', '~> 0.5', '>= 0.5.0'
24
+ spec.add_dependency 'http'
25
+ spec.add_dependency 'sinatra'
26
+ spec.add_dependency 'daemons'
27
+
28
+ spec.add_development_dependency 'bundler', '~> 1.12'
29
+ spec.add_development_dependency 'rake', '~> 10.0'
30
+ spec.add_development_dependency 'rspec', '~> 3.0'
31
+ spec.add_development_dependency 'rack-test', '~> 0.6.3'
32
+ end
metadata ADDED
@@ -0,0 +1,209 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tiny-gate
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - TINYpulse
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-06-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dry-configurable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: dry-struct
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.5'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 0.5.0
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '0.5'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.5.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: http
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: sinatra
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: daemons
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: bundler
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '1.12'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1.12'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rake
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '10.0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '10.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rspec
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '3.0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '3.0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: rack-test
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 0.6.3
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: 0.6.3
145
+ description: This is an authentication client for all TINYpulse apps which use single
146
+ sign on.
147
+ email:
148
+ - devops@tinypulse.com
149
+ executables: []
150
+ extensions: []
151
+ extra_rdoc_files: []
152
+ files:
153
+ - ".gitignore"
154
+ - ".rspec"
155
+ - ".travis.yml"
156
+ - CHANGELOG.md
157
+ - CODE_OF_CONDUCT.md
158
+ - Gemfile
159
+ - LICENSE.txt
160
+ - README.md
161
+ - Rakefile
162
+ - bin/console
163
+ - bin/rspec
164
+ - bin/setup
165
+ - lib/tiny_gate.rb
166
+ - lib/tiny_gate/client.rb
167
+ - lib/tiny_gate/test_helper.rb
168
+ - lib/tiny_gate/test_helper/application_controller.rb
169
+ - lib/tiny_gate/test_helper/dummy_server.rb
170
+ - lib/tiny_gate/test_helper/sessions_controller.rb
171
+ - lib/tiny_gate/test_helper/user.rb
172
+ - lib/tiny_gate/test_helper/user_client.rb
173
+ - lib/tiny_gate/test_helper/user_repository.rb
174
+ - lib/tiny_gate/test_helper/users_controller.rb
175
+ - lib/tiny_gate/test_helper/views/layout.erb
176
+ - lib/tiny_gate/test_helper/views/sessions/new.html.erb
177
+ - lib/tiny_gate/test_helper/views/welcome.html.erb
178
+ - lib/tiny_gate/types.rb
179
+ - lib/tiny_gate/types/active_permission.rb
180
+ - lib/tiny_gate/types/session_response.rb
181
+ - lib/tiny_gate/types/switch_org_response.rb
182
+ - lib/tiny_gate/types/user.rb
183
+ - lib/tiny_gate/version.rb
184
+ - tiny-gate.gemspec
185
+ homepage: https://github.com/TINYhr/tiny-gate
186
+ licenses:
187
+ - MIT
188
+ metadata: {}
189
+ post_install_message:
190
+ rdoc_options: []
191
+ require_paths:
192
+ - lib
193
+ required_ruby_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ required_rubygems_version: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ requirements: []
204
+ rubyforge_project:
205
+ rubygems_version: 2.6.14
206
+ signing_key:
207
+ specification_version: 4
208
+ summary: An authentication client for all TINYpulse apps
209
+ test_files: []