evematic 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/evematic/sessions_controller.rb +21 -0
- data/app/controllers/evematic/sso_callbacks_controller.rb +30 -0
- data/app/models/evematic/access_rule.rb +17 -0
- data/app/models/evematic/account.rb +12 -0
- data/app/models/evematic/application_record.rb +2 -4
- data/app/models/evematic/esi/alliance.rb +25 -0
- data/app/models/evematic/esi/character.rb +35 -0
- data/app/models/evematic/esi/corporation.rb +37 -0
- data/app/models/evematic/identity.rb +24 -0
- data/config/i18n-tasks.yml +5 -4
- data/config/locales/en.yml +13 -0
- data/lib/evematic/configuration/builder.rb +74 -0
- data/lib/evematic/configuration.rb +20 -0
- data/lib/evematic/controllers/helper.rb +7 -0
- data/lib/evematic/controllers/helpers/authentication.rb +90 -0
- data/lib/evematic/controllers.rb +2 -0
- data/lib/evematic/engine.rb +82 -8
- data/lib/evematic/esi/client.rb +89 -0
- data/lib/evematic/esi/helper.rb +43 -0
- data/lib/evematic/esi.rb +2 -0
- data/lib/evematic/jobs/helper.rb +3 -0
- data/lib/evematic/models/helper.rb +31 -0
- data/lib/evematic/models/mixins/access_rule.rb +43 -0
- data/lib/evematic/models/mixins/account.rb +38 -0
- data/lib/evematic/models/mixins/esi/alliance.rb +34 -0
- data/lib/evematic/models/mixins/esi/character.rb +41 -0
- data/lib/evematic/models/mixins/esi/corporation.rb +41 -0
- data/lib/evematic/models/mixins/esi/entity.rb +55 -0
- data/lib/evematic/models/mixins/esi.rb +2 -0
- data/lib/evematic/models/mixins/identity.rb +37 -0
- data/lib/evematic/models/mixins.rb +2 -0
- data/lib/evematic/models.rb +2 -0
- data/lib/evematic/routes/helper.rb +5 -0
- data/lib/evematic/routes/router.rb +10 -0
- data/lib/evematic/routes/routers/authentication.rb +14 -0
- data/lib/evematic/routes.rb +2 -0
- data/lib/evematic/version.rb +1 -1
- data/lib/evematic/views/helper.rb +2 -0
- data/lib/evematic/views.rb +2 -0
- data/lib/evematic.rb +37 -1
- metadata +182 -9
- data/config/locales/evematic.en.yml +0 -5
- data/config/routes.rb +0 -2
@@ -0,0 +1,43 @@
|
|
1
|
+
require "evematic/esi/client"
|
2
|
+
|
3
|
+
module Evematic::ESI::Helper
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def esi_delete(*args, **kwargs)
|
8
|
+
esi_client.delete(*args, **kwargs)
|
9
|
+
end
|
10
|
+
|
11
|
+
def esi_get(*args, **kwargs)
|
12
|
+
esi_client.get(*args, **kwargs)
|
13
|
+
end
|
14
|
+
|
15
|
+
def esi_post(*args, **kwargs)
|
16
|
+
esi_client.post(*args, **kwargs)
|
17
|
+
end
|
18
|
+
|
19
|
+
def esi_put(*args, **kwargs)
|
20
|
+
esi_client.put(*args, **kwargs)
|
21
|
+
end
|
22
|
+
|
23
|
+
def esi_client
|
24
|
+
@esi_client ||= Evematic::ESI::Client.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def esi_delete(*args, **kwargs)
|
29
|
+
self.class.esi_delete(*args, **kwargs)
|
30
|
+
end
|
31
|
+
|
32
|
+
def esi_get(*args, **kwargs)
|
33
|
+
self.class.esi_get(*args, **kwargs)
|
34
|
+
end
|
35
|
+
|
36
|
+
def esi_post(*args, **kwargs)
|
37
|
+
self.class.esi_post(*args, **kwargs)
|
38
|
+
end
|
39
|
+
|
40
|
+
def esi_put(*args, **kwargs)
|
41
|
+
self.class.esi_put(*args, **kwargs)
|
42
|
+
end
|
43
|
+
end
|
data/lib/evematic/esi.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Evematic::Models::Helper
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
[
|
6
|
+
:access_rule, :account, :identity,
|
7
|
+
:esi_alliance, :esi_character, :esi_corporation
|
8
|
+
].each do |name|
|
9
|
+
define_method("#{name}_class") do
|
10
|
+
Evematic.config.send(:"#{name}_class")
|
11
|
+
end
|
12
|
+
|
13
|
+
define_method("#{name}_model") do
|
14
|
+
Evematic.config.send(:"#{name}_model")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
[
|
20
|
+
:access_rule, :account, :identity,
|
21
|
+
:esi_alliance, :esi_character, :esi_corporation
|
22
|
+
].each do |name|
|
23
|
+
define_method("#{name}_class") do
|
24
|
+
self.class.send(:"#{name}_class")
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method("#{name}_model") do
|
28
|
+
self.class.send(:"#{name}_model")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Evematic::Models::Mixins::AccessRule
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
self.table_name = Evematic.config.access_rules_table
|
6
|
+
|
7
|
+
belongs_to :principal, polymorphic: true
|
8
|
+
|
9
|
+
validates :action, inclusion: {in: ["allow", "deny"]}
|
10
|
+
validates :principal_type,
|
11
|
+
inclusion: {
|
12
|
+
in: [
|
13
|
+
esi_alliance_class,
|
14
|
+
esi_character_class,
|
15
|
+
esi_corporation_class
|
16
|
+
]
|
17
|
+
}
|
18
|
+
|
19
|
+
scope :allowed, -> { where(action: "allow") }
|
20
|
+
scope :denied, -> { where(action: "deny") }
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
def allows?(character)
|
25
|
+
return false if denied.exists? { |rule| rule.matches?(character) }
|
26
|
+
|
27
|
+
return true if allowed.exists? { |rule| rule.matches?(character) }
|
28
|
+
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def matches?(character)
|
34
|
+
case principal_type
|
35
|
+
when esi_character_class
|
36
|
+
principal_id == character.id
|
37
|
+
when esi_corporation_class
|
38
|
+
principal_id == character.corporation_id
|
39
|
+
when esi_alliance_class
|
40
|
+
principal_id == character.alliance_id
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Evematic::Models::Mixins::Account
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
self.table_name = Evematic.config.accounts_table
|
6
|
+
|
7
|
+
has_one :main_identity,
|
8
|
+
-> { where(main: true) },
|
9
|
+
class_name: identity_class
|
10
|
+
|
11
|
+
has_one :main_character,
|
12
|
+
class_name: esi_character_class,
|
13
|
+
through: :main_identity,
|
14
|
+
source: :character
|
15
|
+
has_one :main_alliance,
|
16
|
+
class_name: esi_alliance_class,
|
17
|
+
through: :main_character,
|
18
|
+
source: :alliance
|
19
|
+
has_one :main_corporation,
|
20
|
+
class_name: esi_corporation_class,
|
21
|
+
through: :main_character,
|
22
|
+
source: :corporation
|
23
|
+
|
24
|
+
has_many :identities, dependent: :destroy
|
25
|
+
|
26
|
+
has_many :characters,
|
27
|
+
class_name: esi_character_class,
|
28
|
+
through: :identities
|
29
|
+
has_many :alliances,
|
30
|
+
class_name: esi_alliance_class,
|
31
|
+
through: :characters
|
32
|
+
has_many :corporations,
|
33
|
+
class_name: esi_corporation_class,
|
34
|
+
through: :characters
|
35
|
+
|
36
|
+
delegate :name, to: :main_character
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Evematic::Models::Mixins::ESI::Alliance
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
include Evematic::Models::Mixins::ESI::Entity
|
6
|
+
|
7
|
+
self.table_name = Evematic.config.esi_alliances_table
|
8
|
+
|
9
|
+
has_one :access_rule,
|
10
|
+
as: :principal,
|
11
|
+
dependent: :restrict_with_exception
|
12
|
+
|
13
|
+
has_many :corporations,
|
14
|
+
class_name: esi_corporation_class,
|
15
|
+
dependent: :restrict_with_exception
|
16
|
+
has_many :characters,
|
17
|
+
class_name: esi_character_class,
|
18
|
+
dependent: :restrict_with_exception
|
19
|
+
|
20
|
+
has_many :identities,
|
21
|
+
class_name: identity_class,
|
22
|
+
through: :characters
|
23
|
+
|
24
|
+
has_many :accounts,
|
25
|
+
class_name: account_class,
|
26
|
+
through: :identities
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def fetch_esi_attributes
|
32
|
+
esi_get("/latest/alliances/#{id}/")
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Evematic::Models::Mixins::ESI::Character
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
include Evematic::Models::Mixins::ESI::Entity
|
6
|
+
|
7
|
+
self.table_name = Evematic.config.esi_characters_table
|
8
|
+
|
9
|
+
belongs_to :alliance, class_name: esi_alliance_class, optional: true
|
10
|
+
belongs_to :corporation, class_name: esi_corporation_class
|
11
|
+
|
12
|
+
has_one :access_rule,
|
13
|
+
as: :principal,
|
14
|
+
dependent: :restrict_with_exception
|
15
|
+
|
16
|
+
has_one :identity,
|
17
|
+
class_name: identity_class,
|
18
|
+
dependent: :restrict_with_exception
|
19
|
+
|
20
|
+
has_one :account,
|
21
|
+
class_name: account_class,
|
22
|
+
through: :identity
|
23
|
+
|
24
|
+
before_validation :ensure_alliance
|
25
|
+
before_validation :ensure_corporation
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def fetch_esi_attributes
|
31
|
+
esi_get("/latest/characters/#{id}/")
|
32
|
+
end
|
33
|
+
|
34
|
+
def ensure_alliance
|
35
|
+
self.alliance = esi_alliance_model.find_or_create_by(id: alliance_id) if alliance_id.present?
|
36
|
+
end
|
37
|
+
|
38
|
+
def ensure_corporation
|
39
|
+
self.corporation = esi_corporation_model.find_or_create_by(id: corporation_id)
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Evematic::Models::Mixins::ESI::Corporation
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
include Evematic::Models::Mixins::ESI::Entity
|
6
|
+
|
7
|
+
self.table_name = Evematic.config.esi_corporations_table
|
8
|
+
|
9
|
+
belongs_to :alliance,
|
10
|
+
class_name: esi_alliance_class,
|
11
|
+
optional: true
|
12
|
+
|
13
|
+
has_one :access_rule,
|
14
|
+
as: :principal,
|
15
|
+
dependent: :restrict_with_exception
|
16
|
+
|
17
|
+
has_many :characters,
|
18
|
+
class_name: esi_character_class,
|
19
|
+
dependent: :restrict_with_exception
|
20
|
+
|
21
|
+
has_many :identities,
|
22
|
+
class_name: identity_class,
|
23
|
+
through: :characters
|
24
|
+
|
25
|
+
has_many :accounts,
|
26
|
+
class_name: account_class,
|
27
|
+
through: :identities
|
28
|
+
|
29
|
+
before_validation :ensure_alliance
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def fetch_esi_attributes
|
35
|
+
esi_get("/latest/corporations/#{id}/")
|
36
|
+
end
|
37
|
+
|
38
|
+
def ensure_alliance
|
39
|
+
self.alliance = esi_alliance_model.find_or_create_by(id: alliance_id) if alliance_id.present?
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Evematic::Models::Mixins::ESI::Entity
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
include Evematic::ESI::Helper
|
6
|
+
|
7
|
+
before_validation :assign_attributes_from_esi
|
8
|
+
|
9
|
+
define_model_callbacks :esi_sync
|
10
|
+
end
|
11
|
+
|
12
|
+
def assign_attributes_from_esi
|
13
|
+
return if fresh?
|
14
|
+
|
15
|
+
res = fetch_esi_attributes
|
16
|
+
|
17
|
+
attributes = parse_json(res.body).merge(
|
18
|
+
esi_etag: res.headers["etag"].delete('"'),
|
19
|
+
esi_expires_at: DateTime.parse(res.headers["expires"]),
|
20
|
+
esi_last_modified_at: DateTime.parse(res.headers["last-modified"]).change(usec: 0)
|
21
|
+
)
|
22
|
+
transform_esi_attributes(attributes) if respond_to?(:transform_esi_attributes)
|
23
|
+
assign_attributes(attributes)
|
24
|
+
end
|
25
|
+
|
26
|
+
def fresh?
|
27
|
+
return false unless persisted?
|
28
|
+
|
29
|
+
return false if esi_expires_at.blank?
|
30
|
+
|
31
|
+
esi_expires_at >= Time.zone.now
|
32
|
+
end
|
33
|
+
|
34
|
+
def sync
|
35
|
+
run_callbacks :esi_sync do
|
36
|
+
assign_attributes_from_esi
|
37
|
+
changed? ? save : true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def sync!
|
42
|
+
run_callbacks :esi_sync do
|
43
|
+
assign_attributes_from_esi
|
44
|
+
changed? ? save! : true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def parse_json(str)
|
51
|
+
return Oj.load(str) if defined?(Oj)
|
52
|
+
|
53
|
+
JSON.parse(str)
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Evematic::Models::Mixins::Identity
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
self.table_name = Evematic.config.identities_table
|
6
|
+
|
7
|
+
belongs_to :account, class_name: account_class
|
8
|
+
belongs_to :character, class_name: esi_character_class
|
9
|
+
|
10
|
+
has_one :alliance,
|
11
|
+
class_name: esi_alliance_class,
|
12
|
+
through: :character
|
13
|
+
has_one :corporation,
|
14
|
+
class_name: esi_corporation_class,
|
15
|
+
through: :character
|
16
|
+
|
17
|
+
delegate :name, to: :character
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
def sso_authenticate_by(character)
|
22
|
+
character.sync
|
23
|
+
character.alliance.sync if character.alliance.present?
|
24
|
+
character.corporation.sync
|
25
|
+
|
26
|
+
return unless access_rule_model.allows?(character)
|
27
|
+
|
28
|
+
identity = identity_model.find_by(character:)
|
29
|
+
return identity if identity.present?
|
30
|
+
|
31
|
+
identity = identity_model.new(character:, main: true)
|
32
|
+
identity.build_account
|
33
|
+
identity.save!
|
34
|
+
identity
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Evematic::Routes::Routers::Authentication < Evematic::Routes::Router
|
2
|
+
option :controllers, default: -> { {sessions: "evematic/sessions", sso_callbacks: "evematic/sso_callbacks"} }
|
3
|
+
option :path_names, default: -> { {login: "login", logout: "logout", callback: "auth/eve/callback"} }
|
4
|
+
|
5
|
+
def draw!
|
6
|
+
return unless Evematic.config.authentication_enabled
|
7
|
+
|
8
|
+
routes.scope(scope) do
|
9
|
+
routes.get(path_names[:callback], to: "#{controllers[:sso_callbacks]}#eve", as: :sso_callback)
|
10
|
+
routes.get(path_names[:login], to: "#{controllers[:sessions]}#new")
|
11
|
+
routes.delete(path_names[:logout], to: "#{controllers[:sessions]}#destroy")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/evematic/version.rb
CHANGED
data/lib/evematic.rb
CHANGED
@@ -1,6 +1,42 @@
|
|
1
1
|
require "evematic/version"
|
2
|
+
require "evematic/configuration"
|
2
3
|
require "evematic/engine"
|
3
4
|
|
4
5
|
module Evematic
|
5
|
-
|
6
|
+
def self.setup
|
7
|
+
configuration_builder.clear_cache!
|
8
|
+
|
9
|
+
if defined?(Config)
|
10
|
+
settings = Config.const_name.safe_constantize
|
11
|
+
|
12
|
+
configure do |config|
|
13
|
+
config.esi_client_id = settings.esi.client_id
|
14
|
+
config.esi_client_secret = settings.esi.client_secret
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ESI
|
20
|
+
end
|
21
|
+
|
22
|
+
module Models
|
23
|
+
module ESI
|
24
|
+
end
|
25
|
+
end
|
6
26
|
end
|
27
|
+
|
28
|
+
require "zeitwerk"
|
29
|
+
|
30
|
+
loader = Zeitwerk::Loader.for_gem
|
31
|
+
loader.inflector.inflect(
|
32
|
+
"api" => "API",
|
33
|
+
"eve" => "EVE",
|
34
|
+
"esi" => "ESI",
|
35
|
+
"oauth" => "OAuth",
|
36
|
+
"omniauth" => "OmniAuth",
|
37
|
+
"sso" => "SSO"
|
38
|
+
)
|
39
|
+
loader.ignore("#{__dir__}/generators")
|
40
|
+
loader.enable_reloading
|
41
|
+
loader.setup
|
42
|
+
loader.eager_load
|