Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .devcontainer/Dockerfile.postgres
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Would use postgis:15-3.5, but it doesn't work with Apple Silicon
# (https://github.com/postgis/docker-postgis/issues/216).
# Therefore we use postgres:15 and apt-install Postgis ourselves.
FROM postgres:15

RUN apt-get update \
&& apt-get install --no-install-recommends -y \
postgresql-15-postgis-3
4 changes: 3 additions & 1 deletion .devcontainer/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ services:
restart: unless-stopped

postgres:
image: postgres:15
build:
context: .
dockerfile: ./Dockerfile.postgres
restart: unless-stopped
networks:
- default
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ jobs:
cache: yarn
- name: Install node modules
run: bundle exec bin/yarn install
- name: Install packages
run: |
sudo apt-get -yqq update
sudo apt-get -yqq install postgresql-postgis
- name: Setup database
run: |
sudo systemctl start postgresql
Expand Down Expand Up @@ -157,6 +161,10 @@ jobs:
cache: yarn
- name: Install node modules
run: bundle exec bin/yarn install
- name: Install packages
run: |
sudo apt-get -yqq update
sudo apt-get -yqq install postgresql-postgis
- name: Setup database
run: |
sudo systemctl start postgresql
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Install packages
run: |
sudo apt-get -yqq update
sudo apt-get -yqq install memcached libvips-dev xvfb mesa-utils libgl1-mesa-dri
sudo apt-get -yqq install memcached libvips-dev xvfb mesa-utils libgl1-mesa-dri postgresql-postgis
- name: Create database
run: |
sudo systemctl start postgresql
Expand Down
3 changes: 2 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ source "https://rubygems.org"
gem "rails", "~> 8.1.0"
gem "turbo-rails"

# Use postgres as the database
# Use postgres+postgis as the database
gem "activerecord-postgis"
gem "pg"

# Use SCSS for stylesheets
Expand Down
9 changes: 9 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ GEM
timeout (>= 0.4.0)
activerecord-import (2.2.0)
activerecord (>= 4.2)
activerecord-postgis (0.5.1)
activerecord (>= 8.1.0, < 8.2)
pg
rgeo-activerecord (>= 8.0)
activestorage (8.1.3)
actionpack (= 8.1.3)
activejob (= 8.1.3)
Expand Down Expand Up @@ -784,6 +788,10 @@ GEM
reline (0.6.3)
io-console (~> 0.5)
rexml (3.4.4)
rgeo (3.1.0)
rgeo-activerecord (8.1.0)
activerecord (>= 8.1, < 8.2)
rgeo (>= 3.0)
rinku (2.0.6)
rotp (6.3.0)
rouge (4.7.0)
Expand Down Expand Up @@ -922,6 +930,7 @@ DEPENDENCIES
actionpack-page_caching (>= 1.2.0)
active_record_union
activerecord-import
activerecord-postgis
addressable (~> 2.8)
annotaterb
argon2
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/api/notes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ def create
lat = OSM.parse_float(params[:lat], OSM::APIBadUserInput, "lat was not a number")
description = params[:text]

raise OSM::APIModerationZoneError if current_user.nil? && ModerationZone.falls_within_any?(:lon => lon, :lat => lat)

# Get note's author info (for logged in users - user_id, for logged out users - IP address)
note_author_info = author_info

Expand Down
44 changes: 44 additions & 0 deletions app/models/moderation_zone.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: moderation_zones
#
# id :bigint not null, primary key
# name :string not null
# reason :string not null
# reason_format :enum default("markdown")
# zone :st_polygon not null, polygon, 4326
# ends_at :datetime
# creator_id :bigint not null
# revoker_id :bigint
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_moderation_zones_on_creator_id (creator_id)
# index_moderation_zones_on_revoker_id (revoker_id)
#
# Foreign Keys
#
# fk_rails_... (creator_id => users.id)
# fk_rails_... (revoker_id => users.id)
#
class ModerationZone < ApplicationRecord
belongs_to :creator, :class_name => "User"
belongs_to :revoker, :class_name => "User", :optional => true

validates :name, :presence => true
validates :reason, :presence => true
validates :zone, :presence => true

def self.falls_within_any?(lon:, lat:)
factory = RGeo::Cartesian.simple_factory(:srid => 4326)
point = factory.point(lon, lat)

where(
arel_table[:zone].st_contains(point)
).exists?
end
end
7 changes: 7 additions & 0 deletions db/migrate/20260113142804_enable_postgis.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class EnablePostgis < ActiveRecord::Migration[8.1]
def change
enable_extension "postgis"
Comment thread
gravitystorm marked this conversation as resolved.
end
end
18 changes: 18 additions & 0 deletions db/migrate/20260113144310_create_moderation_zones.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

class CreateModerationZones < ActiveRecord::Migration[8.1]
def change
create_table :moderation_zones do |t|
t.string :name, :null => false
t.string :reason, :null => false
t.column :reason_format, :format_enum, :default => "markdown"
t.st_polygon :zone, :srid => 4326, :null => false
t.datetime :ends_at

t.references :creator, :null => false, :foreign_key => { :to_table => :users }
t.references :revoker, :foreign_key => { :to_table => :users }

t.timestamps
end
end
end
98 changes: 98 additions & 0 deletions db/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ CREATE EXTENSION IF NOT EXISTS btree_gist WITH SCHEMA public;
COMMENT ON EXTENSION btree_gist IS 'support for indexing common datatypes in GiST';


--
-- Name: postgis; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS postgis WITH SCHEMA public;


--
-- Name: EXTENSION postgis; Type: COMMENT; Schema: -; Owner: -
--

COMMENT ON EXTENSION postgis IS 'PostGIS geometry and geography spatial types and functions';


--
-- Name: format_enum; Type: TYPE; Schema: public; Owner: -
--
Expand Down Expand Up @@ -1003,6 +1017,43 @@ CREATE SEQUENCE public.messages_id_seq
ALTER SEQUENCE public.messages_id_seq OWNED BY public.messages.id;


--
-- Name: moderation_zones; Type: TABLE; Schema: public; Owner: -
--

CREATE TABLE public.moderation_zones (
id bigint NOT NULL,
name character varying NOT NULL,
reason character varying NOT NULL,
reason_format public.format_enum DEFAULT 'markdown'::public.format_enum,
zone public.geometry(Polygon,4326) NOT NULL,
ends_at timestamp(6) without time zone,
creator_id bigint NOT NULL,
revoker_id bigint,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);


--
-- Name: moderation_zones_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--

CREATE SEQUENCE public.moderation_zones_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;


--
-- Name: moderation_zones_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--

ALTER SEQUENCE public.moderation_zones_id_seq OWNED BY public.moderation_zones.id;


--
-- Name: node_tags; Type: TABLE; Schema: public; Owner: -
--
Expand Down Expand Up @@ -1852,6 +1903,13 @@ ALTER TABLE ONLY public.issues ALTER COLUMN id SET DEFAULT nextval('public.issue
ALTER TABLE ONLY public.messages ALTER COLUMN id SET DEFAULT nextval('public.messages_id_seq'::regclass);


--
-- Name: moderation_zones id; Type: DEFAULT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.moderation_zones ALTER COLUMN id SET DEFAULT nextval('public.moderation_zones_id_seq'::regclass);


--
-- Name: note_comments id; Type: DEFAULT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -2180,6 +2238,14 @@ ALTER TABLE ONLY public.messages
ADD CONSTRAINT messages_pkey PRIMARY KEY (id);


--
-- Name: moderation_zones moderation_zones_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.moderation_zones
ADD CONSTRAINT moderation_zones_pkey PRIMARY KEY (id);


--
-- Name: node_tags node_tags_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -2725,6 +2791,20 @@ CREATE INDEX index_issues_on_status ON public.issues USING btree (status);
CREATE INDEX index_issues_on_updated_by ON public.issues USING btree (updated_by);


--
-- Name: index_moderation_zones_on_creator_id; Type: INDEX; Schema: public; Owner: -
--

CREATE INDEX index_moderation_zones_on_creator_id ON public.moderation_zones USING btree (creator_id);


--
-- Name: index_moderation_zones_on_revoker_id; Type: INDEX; Schema: public; Owner: -
--

CREATE INDEX index_moderation_zones_on_revoker_id ON public.moderation_zones USING btree (revoker_id);


--
-- Name: index_note_comments_on_author_id_and_created_at; Type: INDEX; Schema: public; Owner: -
--
Expand Down Expand Up @@ -3282,6 +3362,14 @@ ALTER TABLE ONLY public.social_links
ADD CONSTRAINT fk_rails_6034fd4f62 FOREIGN KEY (user_id) REFERENCES public.users(id);


--
-- Name: moderation_zones fk_rails_6a0b70e3da; Type: FK CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.moderation_zones
ADD CONSTRAINT fk_rails_6a0b70e3da FOREIGN KEY (creator_id) REFERENCES public.users(id);


--
-- Name: oauth_access_tokens fk_rails_732cb83ab7; Type: FK CONSTRAINT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -3354,6 +3442,14 @@ ALTER TABLE ONLY public.oauth_access_tokens
ADD CONSTRAINT fk_rails_ee63f25419 FOREIGN KEY (resource_owner_id) REFERENCES public.users(id) NOT VALID;


--
-- Name: moderation_zones fk_rails_f2132b7340; Type: FK CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.moderation_zones
ADD CONSTRAINT fk_rails_f2132b7340 FOREIGN KEY (revoker_id) REFERENCES public.users(id);


--
-- Name: friends friends_friend_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -3687,6 +3783,8 @@ INSERT INTO "schema_migrations" (version) VALUES
('21'),
('20260223105922'),
('20260218183352'),
('20260113144310'),
('20260113142804'),
('20251218105716'),
('20251121134648'),
('20250704143751'),
Expand Down
4 changes: 2 additions & 2 deletions doc/MANUAL_INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ sudo apt-get update
sudo apt-get install ruby ruby-dev ruby-bundler \
libvips-dev libxml2-dev libxslt1-dev \
nodejs build-essential git-core \
postgresql postgresql-contrib libpq-dev \
postgresql postgresql-contrib postgresql-postgis libpq-dev \
libsasl2-dev libffi-dev libgd-dev \
libarchive-dev libyaml-dev libbz2-dev npm
sudo npm install --global yarn
Expand All @@ -40,7 +40,7 @@ sudo npm install --global yarn
sudo dnf install ruby ruby-devel rubygem-rdoc rubygem-bundler \
rubygems libxml2-devel nodejs gcc gcc-c++ git \
postgresql postgresql-server \
postgresql-contrib libpq-devel \
postgresql-contrib postgis libpq-devel \
perl-podlators libffi-devel gd-devel \
libarchive-devel libyaml-devel bzip2-devel \
nodejs-yarn vips-devel
Expand Down
7 changes: 7 additions & 0 deletions docker/postgres/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# Would use postgis:14-3.5, but it doesn't work with Apple Silicon
# (https://github.com/postgis/docker-postgis/issues/216).
# Therefore we use postgres:14 and apt-install Postgis ourselves.
FROM postgres:14

RUN apt-get update \
&& apt-get install --no-install-recommends -y \
postgresql-14-postgis-3

# Add db init script to install OSM-specific Postgres user.
ADD docker/postgres/openstreetmap-postgres-init.sh /docker-entrypoint-initdb.d/
14 changes: 12 additions & 2 deletions lib/osm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,18 @@ def status

# Raised when access is denied.
class APIAccessDenied < APIError
def initialize
super("Access denied")
def initialize(message = "Access denied")
super
end

def status
:forbidden
end
end

class APIModerationZoneError < APIAccessDenied
def initialize(message = "You don't have permissions to make changes in this zone, as it is currently protected by moderators")
super
end

def status
Expand Down
Loading