diff --git a/app/logical/danbooru/ip_address.rb b/app/logical/danbooru/ip_address.rb new file mode 100644 index 000000000..5c9a575da --- /dev/null +++ b/app/logical/danbooru/ip_address.rb @@ -0,0 +1,23 @@ +# A wrapper around the IPAddress gem that adds some extra utility methods. +# +# https://github.com/ipaddress-gem/ipaddress + +module Danbooru + class IpAddress + attr_reader :ip_address + delegate_missing_to :ip_address + + def initialize(string) + @ip_address = ::IPAddress.parse(string) + end + + # "1.2.3.4/24" if the address is a subnet, "1.2.3.4" otherwise. + def to_s + ip_address.size > 1 ? ip_address.to_string : ip_address.to_s + end + + def inspect + "#" + end + end +end diff --git a/app/logical/ip_address_type.rb b/app/logical/ip_address_type.rb index 75570790f..5cce74f92 100644 --- a/app/logical/ip_address_type.rb +++ b/app/logical/ip_address_type.rb @@ -1,9 +1,14 @@ +# See also config/initializers/types.rb + +require "active_record/connection_adapters/postgresql_adapter" + class IpAddressType < ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Inet def cast(value) - super(IPAddress.parse(value)) + return nil if value.blank? + super(Danbooru::IpAddress.new(value)) end def serialize(value) - value.to_string + value&.to_string end end diff --git a/app/models/api_key.rb b/app/models/api_key.rb index 35b507733..d841546f6 100644 --- a/app/models/api_key.rb +++ b/app/models/api_key.rb @@ -1,4 +1,7 @@ class ApiKey < ApplicationRecord + attribute :permitted_ip_addresses, :ip_address, array: true + attribute :last_ip_address, :ip_address + array_attribute :permissions array_attribute :permitted_ip_addresses diff --git a/app/models/ip_address.rb b/app/models/ip_address.rb index 77f44b3ff..ab70f37d6 100644 --- a/app/models/ip_address.rb +++ b/app/models/ip_address.rb @@ -1,7 +1,7 @@ class IpAddress < ApplicationRecord belongs_to :model, polymorphic: true belongs_to :user - attribute :ip_addr, IpAddressType.new + attribute :ip_addr, :ip_address def self.model_types %w[Post User Comment Dmail ArtistVersion ArtistCommentaryVersion NoteVersion WikiPageVersion] @@ -41,8 +41,7 @@ class IpAddress < ApplicationRecord end def to_s - # include the subnet mask only when the IP denotes a subnet. - (ip_addr.size > 1) ? ip_addr.to_string : ip_addr.to_s + ip_addr.to_s end def readonly? diff --git a/app/views/api_keys/_form.html.erb b/app/views/api_keys/_form.html.erb index 739a2b2d8..39bbc0ee9 100644 --- a/app/views/api_keys/_form.html.erb +++ b/app/views/api_keys/_form.html.erb @@ -1,6 +1,6 @@ <%= edit_form_for(api_key, html: { class: "stacked-hints" }) do |f| %> <%= f.input :name, as: :string, hint: "An optional name to help you remember what this key is for." %> - <%= f.input :permitted_ip_addresses, label: "IP Addresses", as: :string, hint: "An optional list of IPs allowed to use this key. Leave blank to allow all IPs." %> - <%= f.input :permissions, as: :select, collection: ApiKey.permissions_list, hint: "An optional list of API endpoints this key can use. Ctrl+click to select multiple endpoints. Leave blank to allow all API endpoints.", input_html: { multiple: true } %> + <%= f.input :permitted_ip_addresses, label: "IP Addresses", as: :string, hint: "An optional list of IPs allowed to use this key. Space separated, subnets allowed. Leave blank to allow all IPs." %> + <%= f.input :permissions, as: :select, collection: ApiKey.permissions_list, hint: "An optional list of API endpoints this key is allowed to use. Ctrl+click to select multiple endpoints. Leave blank to allow all API endpoints.", input_html: { multiple: true } %> <%= f.submit "Create" %> <% end %> diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 99f7aa3cc..09961dda5 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -11,7 +11,6 @@ ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.uncountable %w( fish sheep ) end -# These inflection rules are supported but not enabled by default: -# ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.acronym 'RESTful' -# end +#ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym "IP" # IPAddress +#end diff --git a/config/initializers/types.rb b/config/initializers/types.rb new file mode 100644 index 000000000..de1ef4b05 --- /dev/null +++ b/config/initializers/types.rb @@ -0,0 +1 @@ +ActiveRecord::Type.register(:ip_address, IpAddressType) diff --git a/test/unit/api_key_test.rb b/test/unit/api_key_test.rb index 889c99d78..26b68a67f 100644 --- a/test/unit/api_key_test.rb +++ b/test/unit/api_key_test.rb @@ -24,10 +24,10 @@ class ApiKeyTest < ActiveSupport::TestCase should allow_value([]).for(:permitted_ip_addresses) should allow_value(["1.2.3.4"]).for(:permitted_ip_addresses) should allow_value(["1.2.3.4/24"]).for(:permitted_ip_addresses) - should allow_value(["1.2.3.4/24 4.5.6.7/24"]).for(:permitted_ip_addresses) should allow_value(["0.0.0.0/0"]).for(:permitted_ip_addresses) should allow_value(["2600::1/64"]).for(:permitted_ip_addresses) + #should allow_value(["1.2.3.4/24 4.5.6.7/24"]).for(:permitted_ip_addresses) #should_not allow_value(["blah"]).for(:permitted_ip_addresses) #should_not allow_value(["1.2.3.4/64"]).for(:permitted_ip_addresses) end