Add importer role that can be associated with higher rate limits

This commit is contained in:
Tom Hughes 2023-10-29 15:34:12 +00:00
parent b5995c5175
commit c6bb4a5f4e
12 changed files with 244 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg6042"
version="1.1"
inkscape:version="0.48.2 r9819"
width="20"
height="20"
sodipodi:docname="blank_moderator.svg"
inkscape:export-filename="/Users/saman/work_repos/openstreetmap-website/app/assets/images/roles/blank_moderator.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata
id="metadata6048">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6046" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1264"
inkscape:window-height="776"
id="namedview6044"
showgrid="false"
inkscape:zoom="1"
inkscape:cx="10"
inkscape:cy="10"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg6042" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#38e13a;fill-opacity:1;fill-rule:nonzero;stroke:#38e13a;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M 10,2 8.125,8 2,8 6.96875,11.71875 5,18 10,14 15,18 13.03125,11.71875 18,8 11.875,8 10,2 z"
id="path4709" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M 10,2 8.125,8 2,8 6.96875,11.71875 5,18 10,14 15,18 13.03125,11.71875 18,8 11.875,8 10,2 z"
id="path5684" />
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

View file

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4678"
version="1.1"
inkscape:version="0.48.2 r9819"
width="20"
height="20"
sodipodi:docname="moderator.svg"
inkscape:export-filename="/Users/saman/work_repos/openstreetmap-website/app/assets/images/roles/moderator.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata
id="metadata4684">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4682" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1574"
inkscape:window-height="831"
id="namedview4680"
showgrid="false"
inkscape:zoom="1"
inkscape:cx="9.1260993"
inkscape:cy="11.531765"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg4678">
<inkscape:grid
type="xygrid"
id="grid4707" />
</sodipodi:namedview>
<path
style="color:#000000;fill:#38e13a;fill-opacity:1;fill-rule:nonzero;stroke:#38e13a;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 10,2 5,16 -5,-4 -5,4 z"
id="path4709"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="color:#000000;fill:#38e13a;fill-opacity:1;fill-rule:nonzero;stroke:#38e13a;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 2,8 16,0 -8,6 z"
id="path5479"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -290,6 +290,12 @@ class User < ApplicationRecord
role? "administrator"
end
##
# returns true if the user has the importer role, false otherwise
def importer?
role? "importer"
end
##
# returns true if the user has the requested role
def role?(role)

View file

@ -23,7 +23,7 @@ class UserRole < ApplicationRecord
belongs_to :user
belongs_to :granter, :class_name => "User"
ALL_ROLES = %w[administrator moderator].freeze
ALL_ROLES = %w[administrator moderator importer].freeze
validates :role, :inclusion => ALL_ROLES, :uniqueness => { :scope => :user_id }
end

View file

@ -51,6 +51,10 @@ if defined?(ActiveRecord::ConnectionAdapters::AbstractAdapter)
execute "DROP TYPE #{enumeration_name}"
end
def add_enumeration_value(enumeration_name, value)
execute "ALTER TYPE #{enumeration_name} ADD VALUE '#{value}'"
end
def rename_enumeration(old_name, new_name)
old_name = quote_table_name(old_name)
new_name = quote_table_name(new_name)

View file

@ -2739,12 +2739,15 @@ en:
role:
administrator: "This user is an administrator"
moderator: "This user is a moderator"
importer: "This user is a importer"
grant:
administrator: "Grant administrator access"
moderator: "Grant moderator access"
importer: "Grant importer access"
revoke:
administrator: "Revoke administrator access"
moderator: "Revoke moderator access"
importer: "Revoke importer access"
block_history: "Active Blocks"
moderator_history: "Blocks Given"
comments: "Comments"

View file

@ -0,0 +1,9 @@
class AddImporterRole < ActiveRecord::Migration[7.1]
def up
add_enumeration_value :user_role_enum, "importer"
end
def down
raise ActiveRecord::IrreversibleMigration
end
end

View file

@ -91,7 +91,8 @@ CREATE TYPE public.nwr_enum AS ENUM (
CREATE TYPE public.user_role_enum AS ENUM (
'administrator',
'moderator'
'moderator',
'importer'
);
@ -3437,6 +3438,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('23'),
('22'),
('21'),
('20231029151516'),
('20231010194809'),
('20231007141103'),
('20230830115220'),

View file

@ -47,6 +47,12 @@ FactoryBot.define do
end
end
factory :importer_user do
after(:create) do |user, _evaluator|
create(:user_role, :role => "importer", :user => user)
end
end
factory :moderator_user do
after(:create) do |user, _evaluator|
create(:user_role, :role => "moderator", :user => user)

View file

@ -9,17 +9,27 @@ class UserRolesHelperTest < ActionView::TestCase
icon = role_icon(current_user, "moderator")
assert_dom_equal "", icon
icon = role_icon(current_user, "importer")
assert_dom_equal "", icon
icon = role_icon(create(:moderator_user), "moderator")
expected = <<~HTML.delete("\n")
<img srcset="/images/roles/moderator.svg" border="0" alt="This user is a moderator" title="This user is a moderator" src="/images/roles/moderator.png" width="20" height="20" />
HTML
assert_dom_equal expected, icon
icon = role_icon(create(:importer_user), "importer")
expected = <<~HTML.delete("\n")
<img srcset="/images/roles/importer.svg" border="0" alt="This user is a importer" title="This user is a importer" src="/images/roles/importer.png" width="20" height="20" />
HTML
assert_dom_equal expected, icon
end
def test_role_icon_administrator
self.current_user = create(:administrator_user)
user = create(:user)
icon = role_icon(user, "moderator")
expected = <<~HTML.delete("\n")
<a data-confirm="Are you sure you want to grant the role `moderator&#39; to the user `#{user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(user.display_name)}/role/moderator/grant">
@ -28,7 +38,16 @@ class UserRolesHelperTest < ActionView::TestCase
HTML
assert_dom_equal expected, icon
icon = role_icon(user, "importer")
expected = <<~HTML.delete("\n")
<a data-confirm="Are you sure you want to grant the role `importer&#39; to the user `#{user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(user.display_name)}/role/importer/grant">
<img srcset="/images/roles/blank_importer.svg" border="0" alt="Grant importer access" title="Grant importer access" src="/images/roles/blank_importer.png" width="20" height="20" />
</a>
HTML
assert_dom_equal expected, icon
moderator_user = create(:moderator_user)
icon = role_icon(moderator_user, "moderator")
expected = <<~HTML.delete("\n")
<a data-confirm="Are you sure you want to revoke the role `moderator&#39; from the user `#{moderator_user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(moderator_user.display_name)}/role/moderator/revoke">
@ -36,6 +55,32 @@ class UserRolesHelperTest < ActionView::TestCase
</a>
HTML
assert_dom_equal expected, icon
icon = role_icon(user, "importer")
expected = <<~HTML.delete("\n")
<a data-confirm="Are you sure you want to grant the role `importer&#39; to the user `#{user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(user.display_name)}/role/importer/grant">
<img srcset="/images/roles/blank_importer.svg" border="0" alt="Grant importer access" title="Grant importer access" src="/images/roles/blank_importer.png" width="20" height="20" />
</a>
HTML
assert_dom_equal expected, icon
importer_user = create(:importer_user)
icon = role_icon(user, "moderator")
expected = <<~HTML.delete("\n")
<a data-confirm="Are you sure you want to grant the role `moderator&#39; to the user `#{user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(user.display_name)}/role/moderator/grant">
<img srcset="/images/roles/blank_moderator.svg" border="0" alt="Grant moderator access" title="Grant moderator access" src="/images/roles/blank_moderator.png" width="20" height="20" />
</a>
HTML
assert_dom_equal expected, icon
icon = role_icon(importer_user, "importer")
expected = <<~HTML.delete("\n")
<a data-confirm="Are you sure you want to revoke the role `importer&#39; from the user `#{importer_user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(importer_user.display_name)}/role/importer/revoke">
<img srcset="/images/roles/importer.svg" border="0" alt="Revoke importer access" title="Revoke importer access" src="/images/roles/importer.png" width="20" height="20" />
</a>
HTML
assert_dom_equal expected, icon
end
def test_role_icons_normal
@ -50,10 +95,17 @@ class UserRolesHelperTest < ActionView::TestCase
HTML
assert_dom_equal expected, icons
icons = role_icons(create(:importer_user))
expected = <<~HTML.delete("\n")
<img srcset="/images/roles/importer.svg" border="0" alt="This user is a importer" title="This user is a importer" src="/images/roles/importer.png" width="20" height="20" />
HTML
assert_dom_equal expected, icons
icons = role_icons(create(:super_user))
expected = <<~HTML.delete("\n")
<img srcset="/images/roles/administrator.svg" border="0" alt="This user is an administrator" title="This user is an administrator" src="/images/roles/administrator.png" width="20" height="20" />
<img srcset="/images/roles/moderator.svg" border="0" alt="This user is a moderator" title="This user is a moderator" src="/images/roles/moderator.png" width="20" height="20" />
<img srcset="/images/roles/importer.svg" border="0" alt="This user is a importer" title="This user is a importer" src="/images/roles/importer.png" width="20" height="20" />
HTML
assert_dom_equal expected, icons
end
@ -70,6 +122,9 @@ class UserRolesHelperTest < ActionView::TestCase
<a data-confirm="Are you sure you want to grant the role `moderator&#39; to the user `#{user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(user.display_name)}/role/moderator/grant">
<img srcset="/images/roles/blank_moderator.svg" border="0" alt="Grant moderator access" title="Grant moderator access" src="/images/roles/blank_moderator.png" width="20" height="20" />
</a>
<a data-confirm="Are you sure you want to grant the role `importer&#39; to the user `#{user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(user.display_name)}/role/importer/grant">
<img srcset="/images/roles/blank_importer.svg" border="0" alt="Grant importer access" title="Grant importer access" src="/images/roles/blank_importer.png" width="20" height="20" />
</a>
HTML
assert_dom_equal expected, icons
@ -82,6 +137,24 @@ class UserRolesHelperTest < ActionView::TestCase
<a data-confirm="Are you sure you want to revoke the role `moderator&#39; from the user `#{moderator_user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(moderator_user.display_name)}/role/moderator/revoke">
<img srcset="/images/roles/moderator.svg" border="0" alt="Revoke moderator access" title="Revoke moderator access" src="/images/roles/moderator.png" width="20" height="20" />
</a>
<a data-confirm="Are you sure you want to grant the role `importer&#39; to the user `#{moderator_user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(moderator_user.display_name)}/role/importer/grant">
<img srcset="/images/roles/blank_importer.svg" border="0" alt="Grant importer access" title="Grant importer access" src="/images/roles/blank_importer.png" width="20" height="20" />
</a>
HTML
assert_dom_equal expected, icons
importer_user = create(:importer_user)
icons = role_icons(importer_user)
expected = <<~HTML.delete("\n")
<a data-confirm="Are you sure you want to grant the role `administrator&#39; to the user `#{importer_user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(importer_user.display_name)}/role/administrator/grant">
<img srcset="/images/roles/blank_administrator.svg" border="0" alt="Grant administrator access" title="Grant administrator access" src="/images/roles/blank_administrator.png" width="20" height="20" />
</a>
<a data-confirm="Are you sure you want to grant the role `moderator&#39; to the user `#{importer_user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(importer_user.display_name)}/role/moderator/grant">
<img srcset="/images/roles/blank_moderator.svg" border="0" alt="Grant moderator access" title="Grant moderator access" src="/images/roles/blank_moderator.png" width="20" height="20" />
</a>
<a data-confirm="Are you sure you want to revoke the role `importer&#39; from the user `#{importer_user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(importer_user.display_name)}/role/importer/revoke">
<img srcset="/images/roles/importer.svg" border="0" alt="Revoke importer access" title="Revoke importer access" src="/images/roles/importer.png" width="20" height="20" />
</a>
HTML
assert_dom_equal expected, icons
@ -94,6 +167,9 @@ class UserRolesHelperTest < ActionView::TestCase
<a data-confirm="Are you sure you want to revoke the role `moderator&#39; from the user `#{super_user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(super_user.display_name)}/role/moderator/revoke">
<img srcset="/images/roles/moderator.svg" border="0" alt="Revoke moderator access" title="Revoke moderator access" src="/images/roles/moderator.png" width="20" height="20" />
</a>
<a data-confirm="Are you sure you want to revoke the role `importer&#39; from the user `#{super_user.display_name}&#39;?" rel="nofollow" data-method="post" href="/user/#{ERB::Util.u(super_user.display_name)}/role/importer/revoke">
<img srcset="/images/roles/importer.svg" border="0" alt="Revoke importer access" title="Revoke importer access" src="/images/roles/importer.png" width="20" height="20" />
</a>
HTML
assert_dom_equal expected, icons
end