evematic 0.1.0 → 0.1.1
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/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
|