yiffspace 0.0.24 → 0.1.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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/lib/yiffspace/concerns/active_record_extensions.rb +3 -3
  4. data/lib/yiffspace/configuration.rb +0 -25
  5. data/lib/yiffspace/{railtie.rb → engine.rb} +9 -7
  6. data/lib/yiffspace/extensions/active_record/where_chain.rb +30 -30
  7. data/lib/yiffspace/include/active_record_extensions.rb +5 -0
  8. data/lib/yiffspace/include/all.rb +12 -0
  9. data/lib/yiffspace/include/api_methods.rb +5 -0
  10. data/lib/yiffspace/include/attribute_matchers.rb +5 -0
  11. data/lib/yiffspace/include/attribute_methods.rb +5 -0
  12. data/lib/yiffspace/include/concurrency_methods.rb +5 -0
  13. data/lib/yiffspace/include/conditional_includes.rb +5 -0
  14. data/lib/yiffspace/include/current_methods.rb +5 -0
  15. data/lib/yiffspace/include/has_bit_flags.rb +5 -0
  16. data/lib/yiffspace/include/user_class_methods.rb +5 -0
  17. data/lib/yiffspace/include/user_methods.rb +5 -0
  18. data/lib/yiffspace/include/user_name_methods.rb +5 -0
  19. data/lib/yiffspace/include/user_resolvable_methods.rb +5 -0
  20. data/lib/yiffspace/version.rb +1 -1
  21. data/lib/yiffspace.rb +5 -6
  22. metadata +15 -50
  23. data/app/helpers/yiff_space/auth_helper.rb +0 -6
  24. data/engines/auth/app/controllers/yiff_space/auth/application_controller.rb +0 -11
  25. data/engines/auth/app/controllers/yiff_space/auth/root_controller.rb +0 -49
  26. data/engines/auth/app/controllers/yiff_space/auth/webhook_controller.rb +0 -73
  27. data/engines/auth/app/views/yiff_space/auth/root/permissions.html.erb +0 -14
  28. data/engines/auth/config/routes.rb +0 -12
  29. data/lib/tasks/yiffspace_tasks.rake +0 -41
  30. data/lib/yiffspace/auth/api_user.rb +0 -43
  31. data/lib/yiffspace/auth/auth_info/anonymous.rb +0 -60
  32. data/lib/yiffspace/auth/auth_info.rb +0 -78
  33. data/lib/yiffspace/auth/client.rb +0 -56
  34. data/lib/yiffspace/auth/discord_info.rb +0 -65
  35. data/lib/yiffspace/auth/engine.rb +0 -58
  36. data/lib/yiffspace/auth/helper.rb +0 -174
  37. data/lib/yiffspace/auth/permissions.rb +0 -87
  38. data/lib/yiffspace/auth/set_client_name.rb +0 -15
  39. data/lib/yiffspace/auth/user_info/anonymous.rb +0 -72
  40. data/lib/yiffspace/auth/user_info.rb +0 -87
  41. data/lib/yiffspace/auth.rb +0 -44
  42. data/lib/yiffspace/core_ext/action_dispatch/set_auth_client/scoped.rb +0 -13
  43. data/lib/yiffspace/core_ext/action_dispatch/set_auth_client.rb +0 -13
  44. data/lib/yiffspace/core_ext/logto/named_session_storage.rb +0 -7
  45. data/lib/yiffspace/extensions/action_dispatch/set_auth_client/scoped.rb +0 -15
  46. data/lib/yiffspace/extensions/action_dispatch/set_auth_client.rb +0 -13
  47. data/lib/yiffspace/extensions/logto/named_session_storage.rb +0 -22
  48. data/lib/yiffspace/logto_management_client.rb +0 -136
  49. data/lib/yiffspace/serializers/anonymous_auth_info_serializer.rb +0 -23
  50. data/lib/yiffspace/serializers/anonymous_user_info_serializer.rb +0 -23
  51. data/lib/yiffspace/serializers/auth_info_serializer.rb +0 -23
  52. data/lib/yiffspace/serializers/discord_info_serializer.rb +0 -23
  53. data/lib/yiffspace/serializers/permissions_serializer.rb +0 -23
  54. data/lib/yiffspace/serializers/user_info_serializer.rb +0 -23
  55. data/lib/yiffspace/utils/user_deduper.rb +0 -66
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 483249113d393f9851f4641c08e917c087a5c1db46cbbd44c8097c0760b883c5
4
- data.tar.gz: 5e2daacda68d812268a384cc00ccc6df4cb05e267725feee663af3b1a5976e86
3
+ metadata.gz: 91faac8d32a587e89936bc66f94459251f40b7a5c59de022e240684f76b632da
4
+ data.tar.gz: 58fbb7700a5f72959bb94e1b6afdd5ebc20532e9ba5af471b312664fbe9124c9
5
5
  SHA512:
6
- metadata.gz: d7df4e7e6aaabe1460202b67c70cde28dc4f6a195afa09050302b4858f532576f380b3f73ed93baea5d15530a429779269583adb3ff32f4420a12abe6962b5ca
7
- data.tar.gz: 9e811ec4b770efe3df29d2664fe0b9adfde3841d501ba1614458dcdf7e3839b5e4a15d14ca035d64cb5ce3cdb17847d07b15d8dc8c98c2a6698d6d6a09863556
6
+ metadata.gz: 1951e8e761f305e1fb07817b11377a051ba6c3715e1e1c6fe54e3d06f742ebce67699c883478be5a8f8299dd2ffacbd59be7308591d7fd7cf88e5f6fedf3e8c8
7
+ data.tar.gz: ab2ddab57baa7d797fd5da05d9e79dd0a8993d8b0c850ead972dbea48bfd72a609530ee825c11f767aeb5a73c3ccae98e29b1b119ee0db56defa19b2dee73569
data/CHANGELOG.md CHANGED
@@ -0,0 +1,11 @@
1
+ ## 0.1.0
2
+
3
+ - **Breaking:** extracted the Logto auth engine (`YiffSpace::Auth::*`) into a
4
+ separate gem, [`yiffspace-auth`](https://github.com/YiffSpace/Auth.rb). Apps
5
+ using auth need to add that gem alongside `yiffspace`.
6
+ - `YiffSpace::Configuration#auth`/`#add_auth`/`#add_default_auth` and the
7
+ `logto_api_*`/`discord_bot_token` settings moved to `yiffspace-auth`.
8
+ - Replaced the dead `YiffSpace::Railtie` with a real `YiffSpace::Engine <
9
+ Rails::Engine`, so the shared `app/` directory (ApplicationController,
10
+ layout, error view, CSS, ActiveJob serializers) actually loads into host
11
+ apps again.
@@ -30,13 +30,13 @@ module YiffSpace
30
30
  end
31
31
 
32
32
  # CrossJoinLateral, LeftJoinLateral, nil
33
- def unnest(column, name: column.singularize, type: Arel::Nodes::LeftJoinLateral)
34
- function = Arel::Nodes::NamedFunction.new("unnest", [arel(column)], name)
33
+ def unnest(column, name: column.singularize, type: ::Arel::Nodes::LeftJoinLateral)
34
+ function = ::Arel::Nodes::NamedFunction.new("unnest", [arel(column)], name)
35
35
  return function if type.nil?
36
36
 
37
37
  joins(type.new(
38
38
  function,
39
- Arel::Nodes::On.new(Arel.sql("TRUE")),
39
+ ::Arel::Nodes::On.new(Arel.sql("TRUE")),
40
40
  ))
41
41
  end
42
42
  end
@@ -31,12 +31,6 @@ module YiffSpace
31
31
  # The `last_ip_addr` attribute of the User model, used by the UserResolvableMethods concern
32
32
  attr_accessor(:last_ip_addr_attribute)
33
33
 
34
- # Logto Management API credentials (shared across all auth clients).
35
- attr_accessor(:logto_api_client_id, :logto_api_client_secret, :logto_api_resource)
36
-
37
- # Discord bot token used to look up Discord users (shared across all auth clients).
38
- attr_accessor(:discord_bot_token)
39
-
40
34
  # The anonymous user's name, can be a proc
41
35
  attr_reader(:anonymous_user_name)
42
36
 
@@ -58,10 +52,6 @@ module YiffSpace
58
52
  @default_ip_address = "127.0.0.1"
59
53
  @last_ip_addr_attribute = :last_ip_addr
60
54
  @anonymous_user_name = -> { "Anonymous" }
61
- @logto_api_client_id = nil
62
- @logto_api_client_secret = nil
63
- @logto_api_resource = nil
64
- @discord_bot_token = nil
65
55
  end
66
56
 
67
57
  def user_class
@@ -103,21 +93,6 @@ module YiffSpace
103
93
  @anonymous_user_name = value.is_a?(Proc) ? value : -> { value }
104
94
  end
105
95
 
106
- def auth(&block)
107
- client = YiffSpace::Auth.register(Auth::DEFAULT_CLIENT_NAME) unless YiffSpace::Auth.instance_variable_get(:@clients).key?(Auth::DEFAULT_CLIENT_NAME)
108
- client ||= YiffSpace::Auth[Auth::DEFAULT_CLIENT_NAME]
109
- block&.call(client)
110
- client
111
- end
112
-
113
- def add_auth(name, &)
114
- YiffSpace::Auth.register(name, &)
115
- end
116
-
117
- def add_default_auth(&)
118
- add_auth(Auth::DEFAULT_CLIENT_NAME, &)
119
- end
120
-
121
96
  def images
122
97
  @images ||= Images.new
123
98
  end
@@ -1,18 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require("rails")
4
+
3
5
  module YiffSpace
4
- class Railtie < Rails::Railtie
6
+ class Engine < ::Rails::Engine
7
+ config.root = File.expand_path("../..", __dir__)
8
+
9
+ initializer("yiffspace.assets") do |app|
10
+ app.config.assets.precompile += %w[yiffspace/application.css] if app.config.respond_to?(:assets)
11
+ end
12
+
5
13
  initializer("yiffspace.serializers") do
6
14
  ActiveSupport.on_load(:active_job) do
7
15
  ActiveJob::Serializers.add_serializers(
8
- Serializers::AnonymousAuthInfoSerializer,
9
- Serializers::AnonymousUserInfoSerializer,
10
- Serializers::AuthInfoSerializer,
11
16
  Serializers::AvatarSerializer,
12
17
  Serializers::BannerSerializer,
13
- Serializers::DiscordInfoSerializer,
14
- Serializers::PermissionsSerializer,
15
- Serializers::UserInfoSerializer,
16
18
  Serializers::UserResolvableSerializer,
17
19
  )
18
20
  end
@@ -23,46 +23,46 @@ module YiffSpace
23
23
  # https://www.postgresql.org/docs/current/static/functions-matching.html#FUNCTIONS-POSIX-REGEXP
24
24
  # "(?e)" means force use of ERE syntax; see sections 9.7.3.1 and 9.7.3.4.
25
25
  def regex(conditions = {}, flags: "e", **kwargs)
26
- conditions.merge!(kwargs) if conditions.is_a?(Hash)
26
+ conditions.merge!(kwargs) if conditions.is_a?(::Hash)
27
27
  build(conditions, :regex, flags)
28
28
  end
29
29
 
30
30
  def not_regex(conditions = {}, flags: "e", **kwargs)
31
- conditions.merge!(kwargs) if conditions.is_a?(Hash)
31
+ conditions.merge!(kwargs) if conditions.is_a?(::Hash)
32
32
  build(conditions, :not_regex, flags)
33
33
  end
34
34
 
35
35
  def tsquery(conditions = {}, ts_config: "english", **kwargs)
36
- conditions.merge!(kwargs) if conditions.is_a?(Hash)
36
+ conditions.merge!(kwargs) if conditions.is_a?(::Hash)
37
37
  build(conditions, :tsquery, ts_config)
38
38
  end
39
39
 
40
40
  METHODS = {
41
- lt: ->(table_name, column, value) { Arel::Table.new(table_name)[column].lt(value) },
42
- lteq: ->(table_name, column, value) { Arel::Table.new(table_name)[column].lteq(value) },
43
- gt: ->(table_name, column, value) { Arel::Table.new(table_name)[column].gt(value) },
44
- gteq: ->(table_name, column, value) { Arel::Table.new(table_name)[column].gteq(value) },
45
- between: ->(table_name, column, value) { Arel::Table.new(table_name)[column].between(value) },
46
- not_between: ->(table_name, column, value) { Arel::Table.new(table_name)[column].not_between(value) },
47
- in: ->(table_name, column, value) { Arel::Table.new(table_name)[column].in(value) },
48
- not_in: ->(table_name, column, value) { Arel::Table.new(table_name)[column].not_in(value) },
49
- like: ->(table_name, column, value) { Arel::Table.new(table_name)[column].matches(value.to_escaped_for_sql_like, Arel.sql("E'\\\\'"), true) },
50
- ilike: ->(table_name, column, value) { Arel::Table.new(table_name)[column].matches(value.to_escaped_for_sql_like, Arel.sql("E'\\\\'"), false) },
51
- not_like: ->(table_name, column, value) { Arel::Table.new(table_name)[column].does_not_match(value.to_escaped_for_sql_like, Arel.sql("E'\\\\'"), true) },
52
- not_ilike: ->(table_name, column, value) { Arel::Table.new(table_name)[column].does_not_match(value.to_escaped_for_sql_like, Arel.sql("E'\\\\'"), false) },
53
- like_all: ->(table_name, column, value) { Arel::Table.new(table_name)[column].matches_all(value.map(&:to_escaped_for_sql_like), Arel.sql("E'\\\\'"), true) },
54
- ilike_all: ->(table_name, column, value) { Arel::Table.new(table_name)[column].matches_all(value.map(&:to_escaped_for_sql_like), Arel.sql("E'\\\\'"), false) },
55
- not_like_all: ->(table_name, column, value) { Arel::Table.new(table_name)[column].does_not_match_all(value.map(&:to_escaped_for_sql_like), Arel.sql("E'\\\\'"), true) },
56
- not_ilike_all: ->(table_name, column, value) { Arel::Table.new(table_name)[column].does_not_match_all(value.map(&:to_escaped_for_sql_like), Arel.sql("E'\\\\'"), false) },
57
- like_any: ->(table_name, column, value) { Arel::Table.new(table_name)[column].matches_any(value.map(&:to_escaped_for_sql_like), Arel.sql("E'\\\\'"), true) },
58
- ilike_any: ->(table_name, column, value) { Arel::Table.new(table_name)[column].matches_any(value.map(&:to_escaped_for_sql_like), Arel.sql("E'\\\\'"), false) },
59
- not_like_any: ->(table_name, column, value) { Arel::Table.new(table_name)[column].does_not_match_any(value.map(&:to_escaped_for_sql_like), Arel.sql("E'\\\\'"), true) },
60
- not_ilike_any: ->(table_name, column, value) { Arel::Table.new(table_name)[column].does_not_match_any(value.map(&:to_escaped_for_sql_like), Arel.sql("E'\\\\'"), false) },
61
- regex: ->(table_name, column, value, flags) { Arel::Table.new(table_name)[column].matches_regexp("(?#{flags})#{value.is_a?(Regexp) ? value.source : value}") },
62
- not_regex: ->(table_name, column, value, flags) { Arel::Table.new(table_name)[column].does_not_match_regexp("(?#{flags})#{value.is_a?(Regexp) ? value.source : value}") },
63
- tsquery: ->(table_name, column, value, ts_config) { Arel.sql("to_tsvector(:ts_config, :table) @@ plainto_tsquery(:ts_config, :value)", ts_config: ts_config, value: value, table: Arel.sql("#{table_name}.#{column}")) },
64
- has_bits: ->(table_name, column, value) { Arel.sql("(#{table_name}.#{column} & #{Arel::Nodes.build_quoted(value).to_sql}) = #{Arel::Nodes.build_quoted(value).to_sql}") },
65
- not_has_bits: ->(table_name, column, value) { Arel.sql("(#{table_name}.#{column} & #{Arel::Nodes.build_quoted(value).to_sql}) != #{Arel::Nodes.build_quoted(value).to_sql}") },
41
+ lt: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].lt(value) },
42
+ lteq: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].lteq(value) },
43
+ gt: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].gt(value) },
44
+ gteq: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].gteq(value) },
45
+ between: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].between(value) },
46
+ not_between: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].not_between(value) },
47
+ in: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].in(value) },
48
+ not_in: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].not_in(value) },
49
+ like: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].matches(value.to_escaped_for_sql_like, ::Arel.sql("E'\\\\'"), true) },
50
+ ilike: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].matches(value.to_escaped_for_sql_like, ::Arel.sql("E'\\\\'"), false) },
51
+ not_like: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].does_not_match(value.to_escaped_for_sql_like, ::Arel.sql("E'\\\\'"), true) },
52
+ not_ilike: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].does_not_match(value.to_escaped_for_sql_like, ::Arel.sql("E'\\\\'"), false) },
53
+ like_all: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].matches_all(value.map(&:to_escaped_for_sql_like), ::Arel.sql("E'\\\\'"), true) },
54
+ ilike_all: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].matches_all(value.map(&:to_escaped_for_sql_like), ::Arel.sql("E'\\\\'"), false) },
55
+ not_like_all: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].does_not_match_all(value.map(&:to_escaped_for_sql_like), ::Arel.sql("E'\\\\'"), true) },
56
+ not_ilike_all: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].does_not_match_all(value.map(&:to_escaped_for_sql_like), ::Arel.sql("E'\\\\'"), false) },
57
+ like_any: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].matches_any(value.map(&:to_escaped_for_sql_like), ::Arel.sql("E'\\\\'"), true) },
58
+ ilike_any: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].matches_any(value.map(&:to_escaped_for_sql_like), ::Arel.sql("E'\\\\'"), false) },
59
+ not_like_any: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].does_not_match_any(value.map(&:to_escaped_for_sql_like), ::Arel.sql("E'\\\\'"), true) },
60
+ not_ilike_any: ->(table_name, column, value) { ::Arel::Table.new(table_name)[column].does_not_match_any(value.map(&:to_escaped_for_sql_like), ::Arel.sql("E'\\\\'"), false) },
61
+ regex: ->(table_name, column, value, flags) { ::Arel::Table.new(table_name)[column].matches_regexp("(?#{flags})#{value.is_a?(Regexp) ? value.source : value}") },
62
+ not_regex: ->(table_name, column, value, flags) { ::Arel::Table.new(table_name)[column].does_not_match_regexp("(?#{flags})#{value.is_a?(Regexp) ? value.source : value}") },
63
+ tsquery: ->(table_name, column, value, ts_config) { ::Arel.sql("to_tsvector(:ts_config, :table) @@ plainto_tsquery(:ts_config, :value)", ts_config: ts_config, value: value, table: ::Arel.sql("#{table_name}.#{column}")) },
64
+ has_bits: ->(table_name, column, value) { ::Arel.sql("(#{table_name}.#{column} & #{::Arel::Nodes.build_quoted(value).to_sql}) = #{::Arel::Nodes.build_quoted(value).to_sql}") },
65
+ not_has_bits: ->(table_name, column, value) { ::Arel.sql("(#{table_name}.#{column} & #{::Arel::Nodes.build_quoted(value).to_sql}) != #{::Arel::Nodes.build_quoted(value).to_sql}") },
66
66
  }.freeze
67
67
 
68
68
  private
@@ -84,9 +84,9 @@ module YiffSpace
84
84
 
85
85
  conditions.each do |key, value|
86
86
  case key
87
- when String, Symbol
87
+ when ::String, ::Symbol
88
88
  key = key.to_s
89
- if value.is_a?(Hash)
89
+ if value.is_a?(::Hash)
90
90
  pairs.concat(normalize_conditions(value, model, key))
91
91
  elsif key.include?(".")
92
92
  table, col = key.split(".", 2)
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/active_record_extensions")
4
+
5
+ ActiveRecordExtensions = YiffSpace::Concerns::ActiveRecordExtensions
@@ -1,8 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative("active_record_extensions")
4
+ require_relative("api_methods")
5
+ require_relative("attribute_matchers")
6
+ require_relative("attribute_methods")
3
7
  require_relative("cache")
8
+ require_relative("concurrency_methods")
9
+ require_relative("conditional_includes")
4
10
  require_relative("current")
11
+ require_relative("current_methods")
5
12
  require_relative("duration_parser")
13
+ require_relative("has_bit_flags")
6
14
  require_relative("helpers")
7
15
  require_relative("open_hash")
8
16
  require_relative("parameter_builder")
@@ -15,5 +23,9 @@ require_relative("table_builder")
15
23
  require_relative("trace_logger")
16
24
  require_relative("u2id")
17
25
  require_relative("user_attribute")
26
+ require_relative("user_class_methods")
18
27
  require_relative("user_like")
28
+ require_relative("user_methods")
29
+ require_relative("user_name_methods")
19
30
  require_relative("user_resolvable")
31
+ require_relative("user_resolvable_methods")
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/api_methods")
4
+
5
+ ApiMethods = YiffSpace::Concerns::ApiMethods
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/attribute_matchers")
4
+
5
+ AttributeMatchers = YiffSpace::Concerns::AttributeMatchers
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/attribute_methods")
4
+
5
+ AttributeMethods = YiffSpace::Concerns::AttributeMethods
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/active_record_extensions")
4
+
5
+ ConcurrencyMethods = YiffSpace::Concerns::ConcurrencyMethods
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/conditional_includes")
4
+
5
+ ConditionalIncludes = YiffSpace::Concerns::ConditionalIncludes
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/current_methods")
4
+
5
+ CurrentMethods = YiffSpace::Concerns::CurrentMethods
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/has_bit_flags")
4
+
5
+ HasBitFlags = YiffSpace::Concerns::HasBitFlags
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/user_class_methods")
4
+
5
+ UserClassMethods = YiffSpace::Concerns::UserClassMethods
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/user_methods")
4
+
5
+ UserMethods = YiffSpace::Concerns::UserMethods
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/user_name_methods")
4
+
5
+ UserNameMethods = YiffSpace::Concerns::UserNameMethods
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("../concerns/user_resolvable_methods")
4
+
5
+ UserResolvableMethods = YiffSpace::Concerns::UserResolvableMethods
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module YiffSpace
4
- VERSION = "0.0.24"
4
+ VERSION = "0.1.0"
5
5
  end
data/lib/yiffspace.rb CHANGED
@@ -20,12 +20,11 @@ loader = Zeitwerk::Loader.for_gem
20
20
  loader.inflector.inflect({ "postgresql" => "PostgreSQL", "yiffspace" => "YiffSpace", "query_dsl" => "QueryDSL" })
21
21
  loader.ignore("#{__dir__}/yiffspace/core_ext")
22
22
  loader.ignore("#{__dir__}/yiffspace/include")
23
- loader.ignore("#{__dir__}/yiffspace/railtie.rb")
24
- loader.ignore("#{__dir__}/yiffspace/auth/engine.rb")
23
+ loader.ignore("#{__dir__}/yiffspace/engine.rb")
25
24
  loader.setup
26
25
 
27
- # Require the auth engine eagerly so it registers with Rails before the host app's
26
+ # Require the engine eagerly so it registers with Rails before the host app's
28
27
  # active_support.initialize_per_engine_zeitwerk_loaders initializer runs. Without this,
29
- # the engine is only loaded during route drawing (after Zeitwerk setup) and its
30
- # app/controllers path is never added to the app's autoload roots.
31
- require_relative("yiffspace/auth/engine") if defined?(Rails)
28
+ # the engine is only loaded lazily (after Zeitwerk setup) and its app/controllers
29
+ # path is never added to the app's autoload roots.
30
+ require_relative("yiffspace/engine") if defined?(Rails)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yiffspace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.24
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Donovan_DMC
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-07-11 00:00:00.000000000 Z
10
+ date: 2026-07-14 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: abbrev
@@ -37,20 +37,6 @@ dependencies:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
39
  version: '0.24'
40
- - !ruby/object:Gem::Dependency
41
- name: logto
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: 0.2.0
47
- type: :runtime
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: 0.2.0
54
40
  - !ruby/object:Gem::Dependency
55
41
  name: rails
56
42
  requirement: !ruby/object:Gem::Requirement
@@ -108,29 +94,10 @@ files:
108
94
  - app/assets/stylesheets/yiffspace/application.css
109
95
  - app/controllers/yiff_space/application_controller.rb
110
96
  - app/helpers/yiff_space/application_helper.rb
111
- - app/helpers/yiff_space/auth_helper.rb
112
97
  - app/models/yiff_space/application_record.rb
113
98
  - app/views/layouts/yiff_space/application.html.erb
114
99
  - app/views/yiff_space/error.html.erb
115
- - engines/auth/app/controllers/yiff_space/auth/application_controller.rb
116
- - engines/auth/app/controllers/yiff_space/auth/root_controller.rb
117
- - engines/auth/app/controllers/yiff_space/auth/webhook_controller.rb
118
- - engines/auth/app/views/yiff_space/auth/root/permissions.html.erb
119
- - engines/auth/config/routes.rb
120
- - lib/tasks/yiffspace_tasks.rake
121
100
  - lib/yiffspace.rb
122
- - lib/yiffspace/auth.rb
123
- - lib/yiffspace/auth/api_user.rb
124
- - lib/yiffspace/auth/auth_info.rb
125
- - lib/yiffspace/auth/auth_info/anonymous.rb
126
- - lib/yiffspace/auth/client.rb
127
- - lib/yiffspace/auth/discord_info.rb
128
- - lib/yiffspace/auth/engine.rb
129
- - lib/yiffspace/auth/helper.rb
130
- - lib/yiffspace/auth/permissions.rb
131
- - lib/yiffspace/auth/set_client_name.rb
132
- - lib/yiffspace/auth/user_info.rb
133
- - lib/yiffspace/auth/user_info/anonymous.rb
134
101
  - lib/yiffspace/concerns/active_record_extensions.rb
135
102
  - lib/yiffspace/concerns/api_methods.rb
136
103
  - lib/yiffspace/concerns/attribute_matchers.rb
@@ -146,8 +113,6 @@ files:
146
113
  - lib/yiffspace/config_builder.rb
147
114
  - lib/yiffspace/configuration.rb
148
115
  - lib/yiffspace/configuration/images.rb
149
- - lib/yiffspace/core_ext/action_dispatch/set_auth_client.rb
150
- - lib/yiffspace/core_ext/action_dispatch/set_auth_client/scoped.rb
151
116
  - lib/yiffspace/core_ext/active_record/all.rb
152
117
  - lib/yiffspace/core_ext/active_record/where_chain.rb
153
118
  - lib/yiffspace/core_ext/all.rb
@@ -158,14 +123,12 @@ files:
158
123
  - lib/yiffspace/core_ext/enumerable/parallel.rb
159
124
  - lib/yiffspace/core_ext/hash/all.rb
160
125
  - lib/yiffspace/core_ext/hash/to_open_hash.rb
161
- - lib/yiffspace/core_ext/logto/named_session_storage.rb
162
126
  - lib/yiffspace/core_ext/object/all.rb
163
127
  - lib/yiffspace/core_ext/object/to_b.rb
164
128
  - lib/yiffspace/core_ext/object/truthy_falsy.rb
165
129
  - lib/yiffspace/core_ext/string/all.rb
166
130
  - lib/yiffspace/core_ext/string/sql.rb
167
- - lib/yiffspace/extensions/action_dispatch/set_auth_client.rb
168
- - lib/yiffspace/extensions/action_dispatch/set_auth_client/scoped.rb
131
+ - lib/yiffspace/engine.rb
169
132
  - lib/yiffspace/extensions/active_record/where_chain.rb
170
133
  - lib/yiffspace/extensions/arel/nodes/cross_join_lateral.rb
171
134
  - lib/yiffspace/extensions/arel/nodes/left_join_lateral.rb
@@ -175,7 +138,6 @@ files:
175
138
  - lib/yiffspace/extensions/arel/visitors/postgresql/left_join_lateral.rb
176
139
  - lib/yiffspace/extensions/enumerable/parallel.rb
177
140
  - lib/yiffspace/extensions/hash/to_open_hash.rb
178
- - lib/yiffspace/extensions/logto/named_session_storage.rb
179
141
  - lib/yiffspace/extensions/object/to_b.rb
180
142
  - lib/yiffspace/extensions/object/truthy_falsy.rb
181
143
  - lib/yiffspace/extensions/string/sql.rb
@@ -187,10 +149,18 @@ files:
187
149
  - lib/yiffspace/images/banner.rb
188
150
  - lib/yiffspace/images/banner/base.rb
189
151
  - lib/yiffspace/images/banner/discord.rb
152
+ - lib/yiffspace/include/active_record_extensions.rb
190
153
  - lib/yiffspace/include/all.rb
154
+ - lib/yiffspace/include/api_methods.rb
155
+ - lib/yiffspace/include/attribute_matchers.rb
156
+ - lib/yiffspace/include/attribute_methods.rb
191
157
  - lib/yiffspace/include/cache.rb
158
+ - lib/yiffspace/include/concurrency_methods.rb
159
+ - lib/yiffspace/include/conditional_includes.rb
192
160
  - lib/yiffspace/include/current.rb
161
+ - lib/yiffspace/include/current_methods.rb
193
162
  - lib/yiffspace/include/duration_parser.rb
163
+ - lib/yiffspace/include/has_bit_flags.rb
194
164
  - lib/yiffspace/include/helpers.rb
195
165
  - lib/yiffspace/include/open_hash.rb
196
166
  - lib/yiffspace/include/parameter_builder.rb
@@ -203,21 +173,17 @@ files:
203
173
  - lib/yiffspace/include/trace_logger.rb
204
174
  - lib/yiffspace/include/u2id.rb
205
175
  - lib/yiffspace/include/user_attribute.rb
176
+ - lib/yiffspace/include/user_class_methods.rb
206
177
  - lib/yiffspace/include/user_like.rb
178
+ - lib/yiffspace/include/user_methods.rb
179
+ - lib/yiffspace/include/user_name_methods.rb
207
180
  - lib/yiffspace/include/user_resolvable.rb
208
- - lib/yiffspace/logto_management_client.rb
209
- - lib/yiffspace/railtie.rb
181
+ - lib/yiffspace/include/user_resolvable_methods.rb
210
182
  - lib/yiffspace/search/query_builder.rb
211
183
  - lib/yiffspace/search/query_dsl.rb
212
184
  - lib/yiffspace/search/query_helper.rb
213
- - lib/yiffspace/serializers/anonymous_auth_info_serializer.rb
214
- - lib/yiffspace/serializers/anonymous_user_info_serializer.rb
215
- - lib/yiffspace/serializers/auth_info_serializer.rb
216
185
  - lib/yiffspace/serializers/avatar_serializer.rb
217
186
  - lib/yiffspace/serializers/banner_serializer.rb
218
- - lib/yiffspace/serializers/discord_info_serializer.rb
219
- - lib/yiffspace/serializers/permissions_serializer.rb
220
- - lib/yiffspace/serializers/user_info_serializer.rb
221
187
  - lib/yiffspace/serializers/user_resolvable_serializer.rb
222
188
  - lib/yiffspace/utils.rb
223
189
  - lib/yiffspace/utils/cache.rb
@@ -232,7 +198,6 @@ files:
232
198
  - lib/yiffspace/utils/table_builder.rb
233
199
  - lib/yiffspace/utils/trace_logger.rb
234
200
  - lib/yiffspace/utils/user_attribute.rb
235
- - lib/yiffspace/utils/user_deduper.rb
236
201
  - lib/yiffspace/utils/user_like.rb
237
202
  - lib/yiffspace/utils/user_resolvable.rb
238
203
  - lib/yiffspace/utils/user_to_id.rb
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YiffSpace
4
- module AuthHelper
5
- end
6
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YiffSpace
4
- module Auth
5
- class ApplicationController < ::YiffSpace::ApplicationController
6
- include(Helper)
7
-
8
- helper(Helper)
9
- end
10
- end
11
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YiffSpace
4
- module Auth
5
- class RootController < ApplicationController
6
- include(Helper)
7
-
8
- before_action(:sync_auth_if_dirty!)
9
-
10
- def show
11
- client.sign_in(redirect_uri: auth_client_config.redirect_uri, post_redirect_uri: params[:path] || "/")
12
- end
13
-
14
- def cb
15
- client.handle_sign_in_callback(url: request.original_url)
16
- user = client.fetch_user_info
17
- self.user = UserInfo.new(id: user["identities"]["discord"]["userId"], user: user, discord: user["identities"]["discord"]["details"]["rawData"])
18
- token = client.access_token_claims(resource: auth_client_config.resource)
19
- self.auth = AuthInfo.new(id: user["identities"]["discord"]["userId"], token: token, permissions: token["scope"].split, roles: user["roles"], client_id: auth_client_config.client_id)
20
- end
21
-
22
- def permissions; end
23
-
24
- def logout
25
- client.sign_out(post_logout_redirect_uri: request.base_url)
26
- full_reset!
27
- end
28
-
29
- def debug
30
- return render("yiffspace/error", locals: { message: "Access Denied" }, status: :forbidden) unless YiffSpace::Auth.enable_debug_action?
31
-
32
- render(json: {
33
- env: request.env.select { |env| env.start_with?("yiffspace.") },
34
- params: params,
35
- session: session,
36
- client: auth_client_config.as_json.merge(client_secret: "[REDACTED]"),
37
- user: client.fetch_user_info,
38
- token: client.access_token_claims(resource: auth_client_config.resource),
39
- })
40
- end
41
-
42
- private
43
-
44
- def client
45
- @client ||= auth_client_config.logto(self)
46
- end
47
- end
48
- end
49
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require("openssl")
4
- require("active_support/security_utils")
5
-
6
- module YiffSpace
7
- module Auth
8
- class WebhookController < ApplicationController
9
- skip_before_action(:verify_authenticity_token)
10
-
11
- HANDLED_EVENTS = %w[
12
- User.Roles.Updated
13
- User.SuspensionStatus.Updated
14
- User.Deleted
15
- Role.Scopes.Updated
16
- ].freeze
17
- DIRTY_FLAG_TTL = 24.hours
18
-
19
- def create
20
- unless verify_signature
21
- render(plain: "Unauthorized", status: :unauthorized)
22
- return
23
- end
24
-
25
- payload = JSON.parse(request.raw_post)
26
- event = payload["event"]
27
-
28
- handle_event(event, payload) if HANDLED_EVENTS.include?(event)
29
-
30
- head(:ok)
31
- rescue JSON::ParserError
32
- render(plain: "Bad Request", status: :bad_request)
33
- end
34
-
35
- private
36
-
37
- def verify_signature
38
- secret = auth_client_config.logto_webhook_secret
39
- return true if secret.blank?
40
-
41
- received = request.headers["logto-signature-sha-256"].to_s
42
- expected = OpenSSL::HMAC.hexdigest("SHA256", secret, request.raw_post)
43
- ActiveSupport::SecurityUtils.secure_compare(received, expected)
44
- end
45
-
46
- def handle_event(event, payload)
47
- data = payload["data"] || {}
48
-
49
- if event == "Role.Scopes.Updated"
50
- handle_role_scopes_updated(data)
51
- else
52
- user_id = data["id"]
53
- mark_dirty(user_id) if user_id.present?
54
- end
55
- end
56
-
57
- def handle_role_scopes_updated(data)
58
- role_id = data["id"]
59
- return if role_id.blank?
60
-
61
- management = auth_client_config.logto_management
62
- users = management.get_users_with_role(role_id)
63
- users.each { |u| mark_dirty(u["id"]) }
64
- rescue StandardError => e
65
- Rails.logger.error("[YiffSpace::Auth::WebhookController] Role.Scopes.Updated fan-out failed: #{e.message}")
66
- end
67
-
68
- def mark_dirty(user_id)
69
- Rails.cache.write(format(Helper::DIRTY_FLAG_KEY, user_id), true, expires_in: DIRTY_FLAG_TTL)
70
- end
71
- end
72
- end
73
- end