Migrate from Travis to GitHub Actions for CI (#1534)

* Try migrating from Travis to GitHub Actions for CI

* Update actions.yml and tests.yml

* Add ruby version

* Update config/database.yml.example

* Try rubocop and docker jobs

* Fix indentation

* Update tests.yml

* Update tests.yml

* Update gemfile

* Update rubocop job and Gemfile

* Update .rubocop_shopify_styleguide.yml

* Update gemfile

* Update .rubocop_todo.yml

* Update rubocop configuration and styleguides

* Fix rubocop offenses

* Update .rubocop.yml

* Update .rubocop.yml

* Udate .codeclimate.yml

* Update .codeclimate.yml

* Update .codeclimate.yml

* Update .codeclimate.yml

* Setup unit tests

* Update find_verified_user method in connection.rb

* Add yarn cache and install to setup

* install exporter dependencies; gdal/imagemagick

* Introduce Gitpod to migration work (#1538)

* Add CORS headers (#1536)

* Create .gitpod.dockerfile

* Create .gitpod.yml

* Create database.yml.gitpod

* Update .gitpod.yml

* ruby 2.4.6 in gitpod.dockerfile

* Update .gitpod.yml

* Update database.yml.gitpod

Co-authored-by: Sebastian Silva <sebastian@fuentelibre.org>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>

* Install gdal and use egordm for yarn cache

* Delete unnecessary query and fix layout

* Run script with verbose output

* Try installing package in action.yml

* Setup controllers job

* Fix indentation

* Setup system tests job

* Setup docker development build job

* Fix identifiers

* Fix path to action.yml

* Update development dockerfile

* Setup docker production build job

* Update tests.yml

* Setup assets precompilation job

* Setup production environment

* Update tests.yml

* Update action.yml for production

* Try with test setup

* Remove action.yml for production

* Change names of jobs for friendliness and clarity

* Update .github/workflows/tests.yml

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>

* Move dockerfiles to directory and change docker job names for clarity

* Update docker job names

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
Co-authored-by: Sebastian Silva <sebastian@fuentelibre.org>
This commit is contained in:
Alicia Paz
2021-09-20 19:50:31 -03:00
committed by GitHub
parent d25b2e0aab
commit d2d45dbf42
31 changed files with 541 additions and 1533 deletions

View File

@@ -1,8 +1,5 @@
version: 2 version: 2
plugins: plugins:
rubocop:
enabled: true
channel: rubocop-0-70
brakeman: brakeman:
enabled: true enabled: true
bundler-audit: bundler-audit:

View File

@@ -0,0 +1,31 @@
name: 'Set up test environment'
description: 'Set up test environment for mapknitter'
services:
mysql:
image: mysql:5.7
env:
MYSQL_ROOT_PASSWORD: root
ports:
- 3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
runs:
using: 'composite'
steps:
- name: Setup database
shell: bash
env:
RAILS_ENV: test
DB_USER: root
DB_PASS: root
# tell Rails to use proper port for MySQL
DB_PORT: ${{ job.services.mysql.ports[3306] }}
DISABLE_BOOTSNAP: true
run: |
cp config/database.yml.example config/database.yml
cp db/schema.rb.example db/schema.rb
cp config/config.yml.example config/config.yml
sudo systemctl start mysql
mysql -uroot -proot -e "CREATE DATABASE mapknitter_test;"
bundle exec rake db:schema:load db:migrate --trace
sudo apt-get install -y gdal-bin

166
.github/workflows/tests.yml vendored Normal file
View File

@@ -0,0 +1,166 @@
name: CI/CD workflow
on: [pull_request]
jobs:
rubocop:
name: Code style suggestions
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Prepare Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.4.6
bundler-cache: true
- name: Rubocop report
env:
FORCE_COLOR: 1
run: bundle exec rubocop --color --fail-fast
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.4.6
bundler-cache: true
- uses: ./.github/actions/setup-test-environment
- uses: egordm/gha-yarn-node-cache@v1
- name: Install packages
run: yarn install
- name: 'Model Tests'
env:
RAILS_ENV: test
DB_PASSWORD: root
DB_PORT: ${{ job.services.mysql.ports[3306] }}
DISABLE_BOOTSNAP: true
run: |
bundle exec rails test test:models
integration-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.4.6
bundler-cache: true
- uses: ./.github/actions/setup-test-environment
- uses: egordm/gha-yarn-node-cache@v1
- name: Install JavaScript dependencies with Yarn
run: yarn check || yarn install;
- name: 'Integration Tests'
env:
RAILS_ENV: test
DB_PASSWORD: root
DB_PORT: ${{ job.services.mysql.ports[3306] }}
DISABLE_BOOTSNAP: true
run: bundle exec rails test test:integration
controller-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.4.6
bundler-cache: true
- uses: ./.github/actions/setup-test-environment
- uses: egordm/gha-yarn-node-cache@v1
- name: Install JavaScript dependencies with Yarn
run: yarn check || yarn install;
- name: 'Controller Tests'
env:
RAILS_ENV: test
DB_PASSWORD: root
DB_PORT: ${{ job.services.mysql.ports[3306] }}
DISABLE_BOOTSNAP: true
run: bundle exec rails test test:controllers
system-tests:
runs-on: ubuntu-latest
services:
redis:
image: redis
# Set health checks to wait until redis has started
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
# Maps port 6379 on service container to the host
- 6379:6379
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.4.6
bundler-cache: true
- uses: nanasess/setup-chromedriver@v1.0.1
- uses: ./.github/actions/setup-test-environment
- uses: egordm/gha-yarn-node-cache@v1
- name: Install JavaScript dependencies with Yarn
run: yarn check || yarn install;
- name: 'System Tests'
env:
RAILS_ENV: test
DB_PASSWORD: root
DB_PORT: ${{ job.services.mysql.ports[3306] }}
REDIS_HOST: localhost
REDIS_PORT: 6379
run: |
export DISPLAY=:99
chromedriver --url-base=/wd/hub &
bundle exec rails test test:system
- name: Archive system test screenshots
uses: actions/upload-artifact@v2
with:
name: system-test-screenshots
path: tmp/screenshots/*
docker-build-check-development:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.4.6
bundler-cache: true
- uses: ./.github/actions/setup-test-environment
- name: 'Development Docker Build'
run: docker build -t mapknitter -f dockerfiles/development .
docker-build-check-production:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.4.6
bundler-cache: true
- uses: ./.github/actions/setup-test-environment
- name: 'Development Docker Build'
run: docker build -t mapknitter -f dockerfiles/production .
assets-precompilation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.4.6
bundler-cache: true
- uses: ./.github/actions/setup-test-environment
- uses: egordm/gha-yarn-node-cache@v1
- name: Install JavaScript dependencies with Yarn
run: yarn check || yarn install;
- name: 'Asset Precompilation'
env:
RAILS_ENV: production
DB_PASSWORD: root
DB_PORT: ${{ job.services.mysql.ports[3306] }}
DISABLE_BOOTSNAP: true
run: bundle exec rails assets:precompile

View File

@@ -1,10 +1,13 @@
require: rubocop-rails
require: rubocop-performance require: rubocop-performance
# Start with Spotifys style guide as a base then customize from there # Start with Spotifys style guide as a base then customize from there
inherit_from: inherit_from:
- .rubocop_shopify_styleguide.yml
- .rubocop_todo.yml - .rubocop_todo.yml
inherit_gem:
rubocop-shopify: rubocop.yml
# Apply rule to all cops # Apply rule to all cops
AllCops: AllCops:
Include: Include:
@@ -12,7 +15,7 @@ AllCops:
- '/Rakefile' - '/Rakefile'
- '/config.ru' - '/config.ru'
Exclude: Exclude:
- 'vendor/*' - 'vendor/**/*'
- 'node_modules/**/*' - 'node_modules/**/*'
- 'spec/**/*' - 'spec/**/*'
- 'bin/*' - 'bin/*'

File diff suppressed because it is too large Load Diff

View File

@@ -1,142 +1,7 @@
# This configuration was generated by # This configuration was generated by
# `rubocop --auto-gen-config` # `rubocop --auto-gen-config`
# on 2019-03-02 16:51:15 +0100 using RuboCop version 0.65.0. # on 2021-08-31 01:32:53 UTC using RuboCop version 1.12.1.
# The point is for the user to remove these configuration records # The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base. # one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new # Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again. # versions of RuboCop, may require this file to be generated again.
# Offense count: 180
Metrics/AbcSize:
Max: 178
# Offense count: 13
# Configuration parameters: CountComments, ExcludedMethods.
# ExcludedMethods: refine
Metrics/BlockLength:
Max: 257
# Offense count: 24
# Configuration parameters: CountBlocks.
Metrics/BlockNesting:
Max: 6
# Offense count: 50
Metrics/CyclomaticComplexity:
Max: 28
# Offense count: 171
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/MethodLength:
Max: 86
# Offense count: 2
# Configuration parameters: CountComments.
Metrics/ModuleLength:
Max: 347
# Offense count: 60
Metrics/PerceivedComplexity:
Max: 33
# Offense count: 7
# Configuration parameters: EnforcedStyle.
# SupportedStyles: snake_case, camelCase
Naming/MethodName:
Exclude:
- 'app/controllers/tag_controller.rb'
- 'app/models/doc_list.rb'
- 'app/models/search_request.rb'
- 'app/services/search_service.rb'
# Offense count: 8
# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist, MethodDefinitionMacros.
# NamePrefix: is_, has_, have_
# NamePrefixBlacklist: is_, has_, have_
# NameWhitelist: is_a?
# MethodDefinitionMacros: define_method, define_singleton_method
Naming/PredicateName:
Exclude:
- 'spec/**/*'
- 'app/controllers/openid_controller.rb'
- 'app/models/drupal_file.rb'
- 'app/models/image.rb'
- 'app/models/node.rb'
- 'app/models/revision.rb'
- 'app/models/tag.rb'
- 'app/models/user.rb'
# Offense count: 3
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
# AllowedNames: io, id, to, by, on, in, at, ip, db
Naming/UncommunicativeMethodParamName:
Exclude:
- 'app/models/doc_list.rb'
# Offense count: 9
# Configuration parameters: EnforcedStyle.
# SupportedStyles: snake_case, camelCase
Naming/VariableName:
Exclude:
- 'app/models/concerns/node_shared.rb'
- 'app/models/doc_list.rb'
- 'app/models/revision.rb'
- 'app/models/search_request.rb'
# Offense count: 2
Security/Open:
Exclude:
- 'app/models/image.rb'
- 'app/models/node.rb'
# Offense count: 26
# Configuration parameters: MinBodyLength.
Style/GuardClause:
Exclude:
- 'app/controllers/admin_controller.rb'
- 'app/controllers/application_controller.rb'
- 'app/controllers/features_controller.rb'
- 'app/controllers/notes_controller.rb'
- 'app/controllers/openid_controller.rb'
- 'app/controllers/users_controller.rb'
- 'app/helpers/application_helper.rb'
- 'app/helpers/comment_helper.rb'
- 'app/models/comment.rb'
- 'app/models/node.rb'
- 'app/models/spamaway.rb'
- 'app/models/user.rb'
- 'app/models/user_tag.rb'
- 'app/services/search_criteria.rb'
# Offense count: 2
Style/IdenticalConditionalBranches:
Exclude:
# - 'app/controllers/answers_controller.rb'
# Offense count: 45
# Cop supports --auto-correct.
Style/IfUnlessModifier:
Enabled: false
# Offense count: 1
Style/MixinUsage:
Exclude:
- 'app/controllers/application_controller.rb'
# Offense count: 16
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods.
# SupportedStyles: predicate, comparison
Style/NumericPredicate:
Exclude:
- 'spec/**/*'
- 'app/controllers/application_controller.rb'
- 'app/controllers/users_controller.rb'
- 'app/controllers/wiki_controller.rb'
- 'app/jobs/digest_mail_job.rb'
- 'app/models/comment.rb'
- 'app/models/concerns/statistics.rb'
- 'app/models/user.rb'

View File

@@ -52,8 +52,6 @@ group :dependencies do
end end
group :test do group :test do
gem 'rubocop', '~> 0.70.0'
gem 'rubocop-performance'
gem 'ruby-prof' gem 'ruby-prof'
gem 'rails-perftest' gem 'rails-perftest'
gem 'rails-controller-testing' gem 'rails-controller-testing'
@@ -74,15 +72,19 @@ group :development, :test do
gem 'faker', '~> 2.12.0' gem 'faker', '~> 2.12.0'
gem 'pry-rails', '~> 0.3.9' gem 'pry-rails', '~> 0.3.9'
gem 'action-cable-testing' gem 'action-cable-testing'
gem 'rubocop', require: false
gem 'rubocop-performance'
gem 'rubocop-rails', require: false
gem 'rubocop-shopify', require: false
end end
group :development do group :development do
gem 'jshintrb', '~> 0.3.0' gem 'jshintrb', '~> 0.3.0'
gem 'mini_racer', platforms: :ruby gem 'mini_racer', platforms: :ruby
gem 'listen', '~> 3.2.1' gem 'listen', '~> 3.2.1'
gem 'web-console', '~> 3.3'
gem 'spring' gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0' gem 'spring-watcher-listen', '~> 2.0.0'
gem 'web-console', '~> 3.3'
end end
group :sqlite do group :sqlite do

View File

@@ -6,72 +6,72 @@ GEM
ZenTest (4.12.0) ZenTest (4.12.0)
action-cable-testing (0.6.1) action-cable-testing (0.6.1)
actioncable (>= 5.0) actioncable (>= 5.0)
actioncable (5.2.4.3) actioncable (5.2.6)
actionpack (= 5.2.4.3) actionpack (= 5.2.6)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
actionmailer (5.2.4.3) actionmailer (5.2.6)
actionpack (= 5.2.4.3) actionpack (= 5.2.6)
actionview (= 5.2.4.3) actionview (= 5.2.6)
activejob (= 5.2.4.3) activejob (= 5.2.6)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (5.2.4.3) actionpack (5.2.6)
actionview (= 5.2.4.3) actionview (= 5.2.6)
activesupport (= 5.2.4.3) activesupport (= 5.2.6)
rack (~> 2.0, >= 2.0.8) rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.2.4.3) actionview (5.2.6)
activesupport (= 5.2.4.3) activesupport (= 5.2.6)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3) rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (5.2.4.3) activejob (5.2.6)
activesupport (= 5.2.4.3) activesupport (= 5.2.6)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (5.2.4.3) activemodel (5.2.6)
activesupport (= 5.2.4.3) activesupport (= 5.2.6)
activerecord (5.2.4.3) activerecord (5.2.6)
activemodel (= 5.2.4.3) activemodel (= 5.2.6)
activesupport (= 5.2.4.3) activesupport (= 5.2.6)
arel (>= 9.0) arel (>= 9.0)
activestorage (5.2.4.3) activestorage (5.2.6)
actionpack (= 5.2.4.3) actionpack (= 5.2.6)
activerecord (= 5.2.4.3) activerecord (= 5.2.6)
marcel (~> 0.3.1) marcel (~> 1.0.0)
activesupport (5.2.4.3) activesupport (5.2.6)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
minitest (~> 5.1) minitest (~> 5.1)
tzinfo (~> 1.1) tzinfo (~> 1.1)
addressable (2.7.0) addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0) public_suffix (>= 2.0.2, < 5.0)
ansi (1.5.0) ansi (1.5.0)
arel (9.0.0) arel (9.0.0)
ast (2.4.0) ast (2.4.2)
autoprefixer-rails (10.0.0.2) autoprefixer-rails (10.0.3.0)
execjs execjs
aws-eventstream (1.1.0) aws-eventstream (1.1.1)
aws-partitions (1.383.0) aws-partitions (1.492.0)
aws-sdk-core (3.109.1) aws-sdk-core (3.119.1)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0) aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
jmespath (~> 1.0) jmespath (~> 1.0)
aws-sdk-kms (1.39.0) aws-sdk-kms (1.47.0)
aws-sdk-core (~> 3, >= 3.109.0) aws-sdk-core (~> 3, >= 3.119.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.83.1) aws-sdk-s3 (1.100.0)
aws-sdk-core (~> 3, >= 3.109.0) aws-sdk-core (~> 3, >= 3.119.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.2) aws-sigv4 (1.2.4)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
bindex (0.8.1) bindex (0.8.1)
bootsnap (1.4.8) bootsnap (1.4.9)
msgpack (~> 1.0) msgpack (~> 1.0)
bootstrap-sass (3.4.1) bootstrap-sass (3.4.1)
autoprefixer-rails (>= 5.2.1) autoprefixer-rails (>= 5.2.1)
@@ -88,21 +88,37 @@ GEM
xpath (~> 3.2) xpath (~> 3.2)
childprocess (3.0.0) childprocess (3.0.0)
climate_control (0.2.0) climate_control (0.2.0)
codecov (0.2.11) codecov (0.6.0)
json simplecov (>= 0.15, < 0.22)
simplecov coderay (1.1.3)
coderay (1.1.2) concurrent-ruby (1.1.9)
concurrent-ruby (1.1.7)
crass (1.0.6) crass (1.0.6)
docile (1.3.2) docile (1.3.5)
erubi (1.9.0) erubi (1.10.0)
execjs (2.7.0) execjs (2.8.1)
faker (2.12.0) faker (2.12.0)
i18n (>= 1.6, < 2) i18n (>= 1.6, < 2)
faraday (1.0.1) faraday (1.7.1)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
ffi (1.12.2) ruby2_keywords (>= 0.0.4)
friendly_id (5.3.0) faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
ffi (1.15.3)
friendly_id (5.4.2)
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
geokit (1.13.1) geokit (1.13.1)
geokit-rails (1.1.4) geokit-rails (1.1.4)
@@ -112,11 +128,10 @@ GEM
httparty (0.18.1) httparty (0.18.1)
mime-types (~> 3.0) mime-types (~> 3.0)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
i18n (1.8.5) i18n (1.8.10)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
image_science (1.3.1) image_science (1.3.1)
RubyInline (~> 3.9) RubyInline (~> 3.9)
jaro_winkler (1.5.4)
jmespath (1.4.0) jmespath (1.4.0)
jquery-rails (4.4.0) jquery-rails (4.4.0)
rails-dom-testing (>= 1, < 3) rails-dom-testing (>= 1, < 3)
@@ -126,41 +141,43 @@ GEM
execjs execjs
multi_json (>= 1.3) multi_json (>= 1.3)
rake rake
json (2.3.1) json (2.5.1)
libv8 (7.3.492.27.1) libv8-node (15.14.0.1)
libxml-ruby (3.1.0) libxml-ruby (3.1.0)
listen (3.2.1) listen (3.2.1)
rb-fsevent (~> 0.10, >= 0.10.3) rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10) rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.6.0) loofah (2.12.0)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
mail (2.7.1) mail (2.7.1)
mini_mime (>= 0.1.1) mini_mime (>= 0.1.1)
marcel (0.3.3) marcel (1.0.1)
mimemagic (~> 0.3.2)
method_source (1.0.0) method_source (1.0.0)
mime-types (3.3.1) mime-types (3.3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2020.0512) mime-types-data (3.2021.0704)
mini_magick (4.10.1) mimemagic (0.3.10)
mini_mime (1.0.2) nokogiri (~> 1)
rake
mini_magick (4.11.0)
mini_mime (1.1.1)
mini_portile2 (2.4.0) mini_portile2 (2.4.0)
mini_racer (0.2.15) mini_racer (0.4.0)
libv8 (> 7.3) libv8-node (~> 15.14.0.0)
minitest (5.14.2) minitest (5.14.4)
minitest-reporters (1.4.2) minitest-reporters (1.4.3)
ansi ansi
builder builder
minitest (>= 5.0) minitest (>= 5.0)
ruby-progressbar ruby-progressbar
msgpack (1.3.3) msgpack (1.4.2)
multi_json (1.14.1) multi_json (1.15.0)
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.1.1) multipart-post (2.1.1)
mysql2 (0.5.3) mysql2 (0.5.3)
net-http-persistent (2.9.4) net-http-persistent (2.9.4)
nio4r (2.5.2) nio4r (2.5.8)
nokogiri (1.10.10) nokogiri (1.10.10)
mini_portile2 (~> 2.4.0) mini_portile2 (~> 2.4.0)
oa-core (0.3.2) oa-core (0.3.2)
@@ -170,7 +187,7 @@ GEM
ruby-openid-apps-discovery (~> 1.2.0) ruby-openid-apps-discovery (~> 1.2.0)
open_id_authentication (1.3.0) open_id_authentication (1.3.0)
rack-openid (~> 1.3) rack-openid (~> 1.3)
paper_trail (11.0.0) paper_trail (11.1.0)
activerecord (>= 5.2) activerecord (>= 5.2)
request_store (~> 1.1) request_store (~> 1.1)
paperclip (6.1.0) paperclip (6.1.0)
@@ -179,20 +196,20 @@ GEM
mime-types mime-types
mimemagic (~> 0.3.0) mimemagic (~> 0.3.0)
terrapin (~> 0.6.0) terrapin (~> 0.6.0)
parallel (1.19.1) parallel (1.20.1)
parser (2.7.1.1) parser (3.0.2.0)
ast (~> 2.4.0) ast (~> 2.4.1)
passenger (6.0.6) passenger (6.0.10)
rack rack
rake (>= 0.8.1) rake (>= 0.8.1)
popper_js (1.16.0) popper_js (1.16.0)
pry (0.13.1) pry (0.14.1)
coderay (~> 1.1) coderay (~> 1.1)
method_source (~> 1.0) method_source (~> 1.0)
pry-rails (0.3.9) pry-rails (0.3.9)
pry (>= 0.10.4) pry (>= 0.10.4)
public_suffix (4.0.5) public_suffix (4.0.6)
puma (4.3.6) puma (4.3.8)
nio4r (~> 2.0) nio4r (~> 2.0)
rack (2.2.3) rack (2.2.3)
rack-openid (1.3.1) rack-openid (1.3.1)
@@ -203,18 +220,18 @@ GEM
rack_session_access (0.2.0) rack_session_access (0.2.0)
builder (>= 2.0.0) builder (>= 2.0.0)
rack (>= 1.0.0) rack (>= 1.0.0)
rails (5.2.4.3) rails (5.2.6)
actioncable (= 5.2.4.3) actioncable (= 5.2.6)
actionmailer (= 5.2.4.3) actionmailer (= 5.2.6)
actionpack (= 5.2.4.3) actionpack (= 5.2.6)
actionview (= 5.2.4.3) actionview (= 5.2.6)
activejob (= 5.2.4.3) activejob (= 5.2.6)
activemodel (= 5.2.4.3) activemodel (= 5.2.6)
activerecord (= 5.2.4.3) activerecord (= 5.2.6)
activestorage (= 5.2.4.3) activestorage (= 5.2.6)
activesupport (= 5.2.4.3) activesupport (= 5.2.6)
bundler (>= 1.3.0) bundler (>= 1.3.0)
railties (= 5.2.4.3) railties (= 5.2.6)
sprockets-rails (>= 2.0.0) sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5) rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1) actionpack (>= 5.0.1.rc1)
@@ -223,27 +240,28 @@ GEM
rails-dom-testing (2.0.3) rails-dom-testing (2.0.3)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
nokogiri (>= 1.6) nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0) rails-html-sanitizer (1.4.2)
loofah (~> 2.3) loofah (~> 2.3)
rails-perftest (0.0.7) rails-perftest (0.0.7)
railties (5.2.4.3) railties (5.2.6)
actionpack (= 5.2.4.3) actionpack (= 5.2.6)
activesupport (= 5.2.4.3) activesupport (= 5.2.6)
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0) thor (>= 0.19.0, < 2.0)
rainbow (3.0.0) rainbow (3.0.0)
rake (13.0.1) rake (13.0.6)
rb-fsevent (0.10.3) rb-fsevent (0.11.0)
rb-inotify (0.10.1) rb-inotify (0.10.1)
ffi (~> 1.0) ffi (~> 1.0)
rdiscount (2.2.0.2) rdiscount (2.2.0.2)
recaptcha (5.5.0) recaptcha (5.5.0)
json json
redcarpet (3.5.0) redcarpet (3.5.1)
regexp_parser (1.7.1) regexp_parser (1.8.2)
request_store (1.5.0) request_store (1.5.0)
rack (>= 1.4) rack (>= 1.4)
rexml (3.2.5)
right_aws_api (0.3.5) right_aws_api (0.3.5)
right_cloud_api_base (>= 0.2.6) right_cloud_api_base (>= 0.2.6)
right_cloud_api_base (0.2.6) right_cloud_api_base (0.2.6)
@@ -252,28 +270,40 @@ GEM
net-http-persistent (~> 2.9) net-http-persistent (~> 2.9)
redcarpet (>= 3.0.0) redcarpet (>= 3.0.0)
ruby-hmac (>= 0.4.0) ruby-hmac (>= 0.4.0)
rubocop (0.70.0) rubocop (1.12.1)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 2.6) parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.2.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7) unicode-display_width (>= 1.4.0, < 3.0)
rubocop-performance (1.3.0) rubocop-ast (1.4.1)
rubocop (>= 0.68.0) parser (>= 2.7.1.5)
rubocop-performance (1.10.2)
rubocop (>= 0.90.0, < 2.0)
rubocop-ast (>= 0.4.0)
rubocop-rails (2.9.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 0.90.0, < 2.0)
rubocop-shopify (2.0.1)
rubocop (~> 1.11)
ruby-hmac (0.4.0) ruby-hmac (0.4.0)
ruby-openid (2.9.2) ruby-openid (2.9.2)
ruby-openid-apps-discovery (1.2.0) ruby-openid-apps-discovery (1.2.0)
ruby-openid (>= 2.1.7) ruby-openid (>= 2.1.7)
ruby-prof (1.3.2) ruby-prof (1.4.2)
ruby-progressbar (1.10.1) ruby-progressbar (1.11.0)
rubyzip (2.3.0) ruby2_keywords (0.0.5)
rubyzip (2.3.2)
sass (3.7.4) sass (3.7.4)
sass-listen (~> 4.0.0) sass-listen (~> 4.0.0)
sass-listen (4.0.0) sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4) rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7) rb-inotify (~> 0.9, >= 0.9.7)
sassc (2.3.0) sassc (2.4.0)
ffi (~> 1.9) ffi (~> 1.9)
sassc-rails (2.1.2) sassc-rails (2.1.2)
railties (>= 4.0.0) railties (>= 4.0.0)
@@ -284,15 +314,15 @@ GEM
selenium-webdriver (3.142.7) selenium-webdriver (3.142.7)
childprocess (>= 0.5, < 4.0) childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2) rubyzip (>= 1.2.2)
sentry-raven (3.0.4) sentry-raven (3.1.2)
faraday (>= 1.0) faraday (>= 1.0)
simplecov (0.18.5) simplecov (0.18.5)
docile (~> 1.1) docile (~> 1.1)
simplecov-html (~> 0.11) simplecov-html (~> 0.11)
simplecov-html (0.12.2) simplecov-html (0.12.3)
skylight (4.3.1) skylight (4.3.2)
skylight-core (= 4.3.1) skylight-core (= 4.3.2)
skylight-core (4.3.1) skylight-core (4.3.2)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
spring (2.1.1) spring (2.1.1)
spring-watcher-listen (2.0.1) spring-watcher-listen (2.0.1)
@@ -301,32 +331,32 @@ GEM
sprockets (3.7.2) sprockets (3.7.2)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
sprockets-rails (3.2.1) sprockets-rails (3.2.2)
actionpack (>= 4.0) actionpack (>= 4.0)
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
sqlite3 (1.4.2) sqlite3 (1.4.2)
terrapin (0.6.0) terrapin (0.6.0)
climate_control (>= 0.0.3, < 1.0) climate_control (>= 0.0.3, < 1.0)
thor (1.0.1) thor (1.1.0)
thread_safe (0.3.6) thread_safe (0.3.6)
tilt (2.0.10) tilt (2.0.10)
turbolinks (5.2.1) turbolinks (5.2.1)
turbolinks-source (~> 5.2) turbolinks-source (~> 5.2)
turbolinks-source (5.2.0) turbolinks-source (5.2.0)
tzinfo (1.2.7) tzinfo (1.2.9)
thread_safe (~> 0.1) thread_safe (~> 0.1)
tzinfo-data (1.2020.1) tzinfo-data (1.2021.1)
tzinfo (>= 1.0.0) tzinfo (>= 1.0.0)
uglifier (4.2.0) uglifier (4.2.0)
execjs (>= 0.3.0, < 3) execjs (>= 0.3.0, < 3)
unicode-display_width (1.6.1) unicode-display_width (2.0.0)
web-console (3.7.0) web-console (3.7.0)
actionview (>= 5.0) actionview (>= 5.0)
activemodel (>= 5.0) activemodel (>= 5.0)
bindex (>= 0.4.0) bindex (>= 0.4.0)
railties (>= 5.0) railties (>= 5.0)
websocket-driver (0.7.2) websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
will_paginate (3.3.0) will_paginate (3.3.0)
@@ -377,8 +407,10 @@ DEPENDENCIES
rdiscount (= 2.2.0.2) rdiscount (= 2.2.0.2)
recaptcha (~> 5.5.0) recaptcha (~> 5.5.0)
right_aws_api (~> 0.3.5) right_aws_api (~> 0.3.5)
rubocop (~> 0.70.0) rubocop
rubocop-performance rubocop-performance
rubocop-rails
rubocop-shopify
ruby-openid (~> 2.9) ruby-openid (~> 2.9)
ruby-prof ruby-prof
sass sass
@@ -403,4 +435,4 @@ RUBY VERSION
ruby 2.4.6p354 ruby 2.4.6p354
BUNDLED WITH BUNDLED WITH
1.17.3 2.2.26

View File

@@ -9,7 +9,8 @@ module ApplicationCable
private private
def find_verified_user def find_verified_user
User.find(cookies.signed["user_id"]) reject_unauthorized_connection if cookies.signed["user_id"].nil?
User.find(cookies.signed["user_id"].id)
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
reject_unauthorized_connection reject_unauthorized_connection
end end

View File

@@ -3,7 +3,7 @@ class ConcurrentEditingChannel < ApplicationCable::Channel
def subscribed def subscribed
# Called first to connect user to the channel. # Called first to connect user to the channel.
stream_from "concurrent_editing_channel:#{params[:mapSlug]}" stream_from("concurrent_editing_channel:#{params[:mapSlug]}")
end end
def unsubscribed def unsubscribed
@@ -12,6 +12,6 @@ class ConcurrentEditingChannel < ApplicationCable::Channel
def sync(changes) def sync(changes)
# Responsible for broadcasting the updated warpables or simply images to the user's connected on this channel. # Responsible for broadcasting the updated warpables or simply images to the user's connected on this channel.
ActionCable.server.broadcast "concurrent_editing_channel:#{changes['map_slug']}", changes ActionCable.server.broadcast("concurrent_editing_channel:#{changes["map_slug"]}", changes)
end end
end end

View File

@@ -5,7 +5,7 @@ class AnnotationsController < ApplicationController
before_action :find_map before_action :find_map
def index def index
render file: 'annotations/index.json.erb', content_type: 'application/json' render(file: 'annotations/index.json.erb', content_type: 'application/json')
end end
def create def create
@@ -20,18 +20,18 @@ class AnnotationsController < ApplicationController
style: geojson[:properties][:style] style: geojson[:properties][:style]
) )
@annotation.user_id = current_user.id if logged_in? @annotation.user_id = current_user.id if logged_in?
redirect_to map_annotation_url(@map, @annotation) if @annotation.save redirect_to(map_annotation_url(@map, @annotation)) if @annotation.save
end end
end end
end end
def show def show
@annotation = Annotation.find params[:id] @annotation = Annotation.find(params[:id])
render file: 'annotations/show.json.erb', content_type: 'application/json' render(file: 'annotations/show.json.erb', content_type: 'application/json')
end end
def update def update
@annotation = Annotation.find params[:id] @annotation = Annotation.find(params[:id])
geojson = params[:annotation] geojson = params[:annotation]
return if @annotation.user_id.nil? || current_user.can_edit?(@annotation) return if @annotation.user_id.nil? || current_user.can_edit?(@annotation)
@@ -39,19 +39,19 @@ class AnnotationsController < ApplicationController
coordinates: geojson[:geometry][:coordinates], coordinates: geojson[:geometry][:coordinates],
text: geojson[:properties][:textContent], text: geojson[:properties][:textContent],
style: geojson[:properties][:style]) style: geojson[:properties][:style])
render file: 'annotations/update.json.erb', render(file: 'annotations/update.json.erb',
content_type: 'application/json' content_type: 'application/json')
end end
def destroy def destroy
@annotation = Annotation.find params[:id] @annotation = Annotation.find(params[:id])
# if current_user.can_delete?(@annotation) # if current_user.can_delete?(@annotation)
@annotation.delete @annotation.delete
head :ok head(:ok)
# end # end
end end
def find_map def find_map
@map = Map.find params[:map_id] @map = Map.find(params[:map_id])
end end
end end

View File

@@ -41,7 +41,7 @@ class ApplicationController < ActionController::Base
unless logged_in? unless logged_in?
path_info = request.env['PATH_INFO'] path_info = request.env['PATH_INFO']
flash[:warning] = 'You must be logged in to access this section' flash[:warning] = 'You must be logged in to access this section'
redirect_to '/login?back_to=' + path_info.to_param # halts request cycle redirect_to('/login?back_to=' + path_info.to_param) # halts request cycle
end end
end end
@@ -51,7 +51,7 @@ class ApplicationController < ActionController::Base
begin begin
user_id && User.find(user_id) ? true : false user_id && User.find(user_id) ? true : false
rescue StandardError rescue StandardError
return false false
end end
end end

View File

@@ -14,24 +14,24 @@ class CommentsController < ApplicationController
end end
respond_to do |format| respond_to do |format|
format.html { render partial: 'comments/comment', locals: { comment: @comment } } format.html { render(partial: 'comments/comment', locals: { comment: @comment }) }
format.json { render json: @comment, status: :created } format.json { render(json: @comment, status: :created) }
end end
else else
# we intercept this message in /app/assets/javascripts/maps.js # we intercept this message in /app/assets/javascripts/maps.js
render plain: 'Login required.' render(plain: 'Login required.')
end end
end end
def update def update
@comment = Comment.find params[:id] @comment = Comment.find(params[:id])
if logged_in? && current_user.can_edit?(@comment) if logged_in? && current_user.can_edit?(@comment)
@comment.update_attributes(comment_params) @comment.update_attributes(comment_params)
redirect_to @comment.map redirect_to(@comment.map)
else else
flash[:error] = 'You do not have permissions to update that comment.' flash[:error] = 'You do not have permissions to update that comment.'
redirect_to '/login' redirect_to('/login')
end end
end end
@@ -44,7 +44,7 @@ class CommentsController < ApplicationController
else else
flash[:error] = 'You do not have permission to delete that comment.' flash[:error] = 'You do not have permission to delete that comment.'
end end
redirect_to @comment.map redirect_to(@comment.map)
end end
private private

View File

@@ -23,12 +23,12 @@ class ExportController < ApplicationController
# https://mapknitter.org/warps/yale-farm/yale-farm.jpg # https://mapknitter.org/warps/yale-farm/yale-farm.jpg
def jpg def jpg
send_file 'public/warps/' + params[:id] + '/' + params[:id] + '.jpg' send_file('public/warps/' + params[:id] + '/' + params[:id] + '.jpg')
end end
# https://mapknitter.org/warps/yale-farm/yale-farm-geo.tif # https://mapknitter.org/warps/yale-farm/yale-farm-geo.tif
def geotiff def geotiff
send_file 'public/warps/' + params[:id] + '/' + params[:id] + '-geo.tif' send_file('public/warps/' + params[:id] + '/' + params[:id] + '-geo.tif')
end end
def cancel def cancel
@@ -39,12 +39,12 @@ class ExportController < ApplicationController
export.save export.save
if params[:exports] if params[:exports]
flash[:notice] = 'Export cancelled.' flash[:notice] = 'Export cancelled.'
redirect_to '/exports' redirect_to('/exports')
else else
render plain: 'cancelled' render(plain: 'cancelled')
end end
else else
render plain: 'You must be logged in to export, unless the map is anonymous.' render(plain: 'You must be logged in to export, unless the map is anonymous.')
end end
end end
@@ -64,7 +64,7 @@ class ExportController < ApplicationController
else else
'export has not been run' 'export has not been run'
end end
render plain: output, layout: false render(plain: output, layout: false)
end end
def status def status
@@ -72,12 +72,12 @@ class ExportController < ApplicationController
if export = map.export if export = map.export
if export.export_url.present? if export.export_url.present?
status_response = ExporterClient.new(export.export_url).status status_response = ExporterClient.new(export.export_url).status
render json: status_response render(json: status_response)
else else
render json: export.to_json render(json: export.to_json)
end end
else else
render json: { status: 'export has not been run' } render(json: { status: 'export has not been run' })
end end
end end
@@ -93,12 +93,12 @@ class ExportController < ApplicationController
map_id: params[:map_id], map_id: params[:map_id],
bands_string: 'default bands_string' bands_string: 'default bands_string'
) )
render json: export.to_json render(json: export.to_json)
end end
# for demoing remote url functionality during testing # for demoing remote url functionality during testing
def external_url_test def external_url_test
render json: Export.last.to_json render(json: Export.last.to_json)
end end
private private

View File

@@ -8,18 +8,18 @@ class FeedsController < ApplicationController
.group('maps.id') .group('maps.id')
.order('id DESC') .order('id DESC')
.limit(20) .limit(20)
render layout: false, template: 'feeds/all' render(layout: false, template: 'feeds/all')
response.headers['Content-Type'] = 'application/xml; charset=utf-8' response.headers['Content-Type'] = 'application/xml; charset=utf-8'
end end
def clean def clean
render layout: false, template: 'feeds/clean' render(layout: false, template: 'feeds/clean')
response.headers['Content-Type'] = 'application/xml; charset=utf-8' response.headers['Content-Type'] = 'application/xml; charset=utf-8'
end end
def license def license
@maps = @maps.where(license: params[:id]) @maps = @maps.where(license: params[:id])
render layout: false, template: 'feeds/license' render(layout: false, template: 'feeds/license')
response.headers['Content-Type'] = 'application/xml; charset=utf-8' response.headers['Content-Type'] = 'application/xml; charset=utf-8'
end end
@@ -33,17 +33,17 @@ class FeedsController < ApplicationController
images += map.warpables images += map.warpables
end end
@feed = (@maps + images).sort_by(&:created_at) @feed = (@maps + images).sort_by(&:created_at)
render layout: false, template: 'feeds/author' render(layout: false, template: 'feeds/author')
response.headers['Content-Type'] = 'application/xml; charset=utf-8' response.headers['Content-Type'] = 'application/xml; charset=utf-8'
end end
def tag def tag
@tag = Tag.find_by_name params[:id] @tag = Tag.find_by_name(params[:id])
@maps = @tag.maps.paginate(page: params[:page], per_page: 24) @maps = @tag.maps.paginate(page: params[:page], per_page: 24)
render layout: false, template: 'feeds/tag' render(layout: false, template: 'feeds/tag')
response.headers['Content-Type'] = 'application/xml; charset=utf-8' response.headers['Content-Type'] = 'application/xml; charset=utf-8'
rescue NoMethodError rescue NoMethodError
render plain: "No maps with tag #{params[:id]}" render(plain: "No maps with tag #{params[:id]}")
end end
private private

View File

@@ -39,7 +39,7 @@ class FrontUiController < ApplicationController
session[:lat] = lat session[:lat] = lat
session[:lon] = lon session[:lon] = lon
head 200, content_type: "text/html" head(200, content_type: "text/html")
end end
def about def about

View File

@@ -14,10 +14,10 @@ class ImagesController < ApplicationController
if params[:url][0..42] == 'https://s3.amazonaws.com/grassrootsmapping/' if params[:url][0..42] == 'https://s3.amazonaws.com/grassrootsmapping/'
url = URI.parse(params[:url]) url = URI.parse(params[:url])
result = Net::HTTP.get_response(url) result = Net::HTTP.get_response(url)
send_data result.body, type: result.content_type, disposition: 'inline' send_data(result.body, type: result.content_type, disposition: 'inline')
end end
else else
redirect_to params[:url] redirect_to(params[:url])
end end
end end
@@ -32,46 +32,46 @@ class ImagesController < ApplicationController
map.save map.save
respond_to do |format| respond_to do |format|
if @warpable.save if @warpable.save
format.html { render json: [@warpable.fup_json].to_json, content_type: 'text/html' } format.html { render(json: [@warpable.fup_json].to_json, content_type: 'text/html') }
format.json { render json: { files: [@warpable.fup_json] }, status: :created, location: @warpable.image.url } format.json { render(json: { files: [@warpable.fup_json] }, status: :created, location: @warpable.image.url) }
else else
format.html { render action: 'new' } format.html { render(action: 'new') }
format.json { render json: { files: [@warpable.fup_error_json] }, layout: false } format.json { render(json: { files: [@warpable.fup_error_json] }, layout: false) }
end end
end end
end end
# mapknitter.org/import/<map-name>/?url=http://myurl.com/image.jpg # mapknitter.org/import/<map-name>/?url=http://myurl.com/image.jpg
def import def import
map = Map.find_by_name params[:name] map = Map.find_by_name(params[:name])
@warpable = Warpable.new @warpable = Warpable.new
@warpable.map_id = map.id @warpable.map_id = map.id
@warpable.url = params[:url] @warpable.url = params[:url]
map.updated_at = Time.now map.updated_at = Time.now
map.save map.save
if @warpable.save if @warpable.save
redirect_to '/maps/' + params[:name] redirect_to('/maps/' + params[:name])
else else
flash[:notice] = 'Sorry, the image failed to import.' flash[:notice] = 'Sorry, the image failed to import.'
redirect_to '/map/edit/' + params[:name] redirect_to('/map/edit/' + params[:name])
end end
end end
def url_upload_not_found def url_upload_not_found
flash[:notice] = 'Sorry, the URL you provided was not valid.' flash[:notice] = 'Sorry, the URL you provided was not valid.'
redirect_to '/map/edit/' + params[:id] redirect_to('/map/edit/' + params[:id])
end end
def show def show
@image = Warpable.find params[:id] @image = Warpable.find(params[:id])
respond_to do |format| respond_to do |format|
format.html format.html
format.json { render json: @image.map(&:fup_json) } format.json { render(json: @image.map(&:fup_json)) }
end end
end end
def update def update
@warpable = Warpable.find params[:warpable_id] @warpable = Warpable.find(params[:warpable_id])
if Map.find(@warpable.map_id).anonymous? || logged_in? if Map.find(@warpable.map_id).anonymous? || logged_in?
nodes = [] nodes = []
@@ -94,11 +94,11 @@ class ImagesController < ApplicationController
@warpable.save @warpable.save
respond_to do |format| respond_to do |format|
format.html { render html: 'success' } format.html { render(html: 'success') }
format.json { render json: @warpable.map.fetch_map_data } format.json { render(json: @warpable.map.fetch_map_data) }
end end
else else
render plain: 'You must be logged in to update the image, unless the map is anonymous.' render(plain: 'You must be logged in to update the image, unless the map is anonymous.')
end end
end end
@@ -106,7 +106,7 @@ class ImagesController < ApplicationController
@warpable = Warpable.find(params[:id]) @warpable = Warpable.find(params[:id])
version = @warpable.versions.find(params[:version]) version = @warpable.versions.find(params[:version])
version.reify&.save version.reify&.save
redirect_to @warpable.map redirect_to(@warpable.map)
end end
def destroy def destroy
@@ -114,15 +114,15 @@ class ImagesController < ApplicationController
if (logged_in? && current_user.can_edit?(@warpable.map)) || @warpable.map.anonymous? if (logged_in? && current_user.can_edit?(@warpable.map)) || @warpable.map.anonymous?
@warpable.destroy @warpable.destroy
respond_to do |format| respond_to do |format|
format.html { render html: { notice: 'Image was successfully destroyed.' } } format.html { render(html: { notice: 'Image was successfully destroyed.' }) }
format.json { render json: @warpable } format.json { render(json: @warpable) }
end end
else else
respond_to do |format| respond_to do |format|
msg = "You do not have privileges to delete this image" msg = "You do not have privileges to delete this image"
flash[:notice] = msg flash[:notice] = msg
format.html { redirect_to @warpable.map } format.html { redirect_to(@warpable.map) }
format.json { render json: msg, status: 401 } format.json { render(json: msg, status: 401) }
end end
end end
end end

View File

@@ -11,7 +11,7 @@ class MapsController < ApplicationController
def index def index
# show only maps with at least 1 image to reduce spammer interest # show only maps with at least 1 image to reduce spammer interest
redirect_to '/gallery' redirect_to('/gallery')
# @maps = Map.page(params[:page]) # @maps = Map.page(params[:page])
# .per_page(20) # .per_page(20)
# .where(archived: false, password: '') # .where(archived: false, password: '')
@@ -26,7 +26,7 @@ class MapsController < ApplicationController
def map def map
@maps = Map.map @maps = Map.map
render layout: false render(layout: false)
end end
def new def new
@@ -46,10 +46,10 @@ class MapsController < ApplicationController
end end
if @map.save if @map.save
redirect_to "/maps/#{@map.slug}/edit" redirect_to("/maps/#{@map.slug}/edit")
else else
flash.now[:errors] = @map.errors.full_messages flash.now[:errors] = @map.errors.full_messages
render 'new' render('new')
end end
end end
@@ -60,7 +60,7 @@ class MapsController < ApplicationController
.sample(4) .sample(4)
@unpaginated = true @unpaginated = true
@users = @map.authors @users = @map.authors
render layout: 'application' render(layout: 'application')
end end
def archive def archive
@@ -80,8 +80,8 @@ class MapsController < ApplicationController
def embed def embed
@map.zoom ||= 12 @map.zoom ||= 12
@embed = true @embed = true
response.headers.except! 'X-Frame-Options' # allow use of embed in iframes response.headers.except!('X-Frame-Options') # allow use of embed in iframes
render template: 'maps/edit' render(template: 'maps/edit')
end end
def annotate def annotate
@@ -102,7 +102,7 @@ class MapsController < ApplicationController
save_tags(@map) save_tags(@map)
@map.save @map.save
redirect_to action: 'show' redirect_to(action: 'show')
end end
def destroy def destroy
@@ -112,29 +112,29 @@ class MapsController < ApplicationController
redirect_back(fallback_location: "/") redirect_back(fallback_location: "/")
else else
flash[:error] = 'Only admins or map owners may delete maps.' flash[:error] = 'Only admins or map owners may delete maps.'
redirect_to @map redirect_to(@map)
end end
end end
# used by leaflet to fetch corner coords of each warpable # used by leaflet to fetch corner coords of each warpable
def images def images
render json: @map.warpables render(json: @map.warpables)
end end
# run the export # run the export
def export def export
@map = Map.find_by(id: params[:id]) @map = Map.find_by(id: params[:id])
if logged_in? || Rails.env.development? || verify_recaptcha(model: @map, message: "ReCAPTCHA thinks you're not a human!") if logged_in? || Rails.env.development? || verify_recaptcha(model: @map, message: "ReCAPTCHA thinks you're not a human!")
render plain: @map.run_export(current_user, params[:resolution].to_f) render(plain: @map.run_export(current_user, params[:resolution].to_f))
else else
render plain: 'You must be logged in to export, unless the map is anonymous.' render(plain: 'You must be logged in to export, unless the map is anonymous.')
end end
end end
# render list of exports # render list of exports
def exports def exports
@map = Map.find_by(id: params[:id]) @map = Map.find_by(id: params[:id])
render partial: 'maps/exports', layout: false render(partial: 'maps/exports', layout: false)
end end
# list by region # list by region
@@ -155,8 +155,8 @@ class MapsController < ApplicationController
map.image_urls = map.warpables.map { |warpable| warpable.image.url } map.image_urls = map.warpables.map { |warpable| warpable.image.url }
end end
respond_to do |format| respond_to do |format|
format.html { render 'maps/index', layout: 'application' } format.html { render('maps/index', layout: 'application') }
format.json { render json: @maps.to_json(methods: :image_urls) } format.json { render(json: @maps.to_json(methods: :image_urls)) }
end end
end end
@@ -166,13 +166,13 @@ class MapsController < ApplicationController
@maps = Map.where(password: '', license: params[:id]) @maps = Map.where(password: '', license: params[:id])
.order('updated_at DESC') .order('updated_at DESC')
.paginate(page: params[:page], per_page: 24) .paginate(page: params[:page], per_page: 24)
render 'maps/index', layout: 'application' render('maps/index', layout: 'application')
end end
def featured def featured
@title = 'Featured maps' @title = 'Featured maps'
@maps = Map.featured.paginate(page: params[:page], per_page: 24) @maps = Map.featured.paginate(page: params[:page], per_page: 24)
render 'maps/index', layout: 'application' render('maps/index', layout: 'application')
end end
def search def search
@@ -188,12 +188,12 @@ class MapsController < ApplicationController
.except(:styles, :email) .except(:styles, :email)
@authors = User.where(login: Map.featured.collect(&:author)) @authors = User.where(login: Map.featured.collect(&:author))
.paginate(page: params[:mappers], per_page: 20) .paginate(page: params[:mappers], per_page: 20)
format.html { render 'front_ui/gallery', layout: 'application' } format.html { render('front_ui/gallery', layout: 'application') }
else else
@title = "Search results for '#{data}'" @title = "Search results for '#{data}'"
@maps = Map.search(data).paginate(page: params[:page], per_page: 24) @maps = Map.search(data).paginate(page: params[:page], per_page: 24)
format.html { render 'front_ui/gallery', layout: 'application' } format.html { render('front_ui/gallery', layout: 'application') }
format.json { render json: @maps } format.json { render(json: @maps) }
end end
end end
end end

View File

@@ -6,7 +6,7 @@ class SessionsController < ApplicationController
def new def new
if logged_in? if logged_in?
redirect_to "/" redirect_to("/")
else else
@referer = params[:back_to] @referer = params[:back_to]
end end
@@ -21,8 +21,8 @@ class SessionsController < ApplicationController
openid_url = CGI.unescape(open_id) openid_url = CGI.unescape(open_id)
# here it is localhost:3000/people/admin/identity for admin # here it is localhost:3000/people/admin/identity for admin
# possibly user is providing the whole URL # possibly user is providing the whole URL
if openid_url.include? "publiclab" if openid_url.include?("publiclab")
if openid_url.include? "http" if openid_url.include?("http")
# params[:subaction] contains the value of the provider # params[:subaction] contains the value of the provider
# provider implies ['github', 'google_oauth2', 'twitter', 'facebook'] # provider implies ['github', 'google_oauth2', 'twitter', 'facebook']
url = if params[:subaction] url = if params[:subaction]
@@ -52,14 +52,14 @@ class SessionsController < ApplicationController
successful_login('', nil) successful_login('', nil)
else else
flash[:error] = "Forbidden" flash[:error] = "Forbidden"
redirect_to "/" redirect_to("/")
end end
end end
def logout def logout
session[:user_id] = nil session[:user_id] = nil
flash[:success] = "You have successfully logged out." flash[:success] = "You have successfully logged out."
redirect_to '/' + '?_=' + Time.now.to_i.to_s redirect_to('/' + '?_=' + Time.now.to_i.to_s)
end end
protected protected
@@ -88,13 +88,13 @@ class SessionsController < ApplicationController
@user.save! @user.save!
rescue ActiveRecord::RecordInvalid => e rescue ActiveRecord::RecordInvalid => e
puts e puts e
failed_login "User can not be associated to local account. Probably the account already exists with different capitalization!" failed_login("User can not be associated to local account. Probably the account already exists with different capitalization!")
return return
end end
end end
nonce = params[:n] nonce = params[:n]
if nonce if nonce
tmp = Sitetmp.find_by nonce: nonce tmp = Sitetmp.find_by(nonce: nonce)
if tmp if tmp
data = tmp.attributes data = tmp.attributes
data.delete("nonce") data.delete("nonce")
@@ -105,12 +105,12 @@ class SessionsController < ApplicationController
end end
@current_user = @user @current_user = @user
if site if site
successful_login back_to, site.id successful_login(back_to, site.id)
else else
successful_login back_to, nil successful_login(back_to, nil)
end end
else else
failed_login result.message failed_login(result.message)
return false return false
end end
end end
@@ -120,19 +120,19 @@ class SessionsController < ApplicationController
def failed_login(message = "Authentication failed.") def failed_login(message = "Authentication failed.")
flash[:danger] = message flash[:danger] = message
redirect_to '/' redirect_to('/')
end end
def successful_login(back_to, id) def successful_login(back_to, id)
session[:user_id] = @current_user.id session[:user_id] = @current_user.id
flash[:success] = "You have successfully logged in." flash[:success] = "You have successfully logged in."
if id if id
redirect_to '/sites/' + id.to_s + '/upload' redirect_to('/sites/' + id.to_s + '/upload')
else else
if back_to if back_to
redirect_to back_to redirect_to(back_to)
else else
redirect_to '/sites' redirect_to('/sites')
end end
end end
end end

View File

@@ -5,22 +5,22 @@ class TagsController < ApplicationController
@map = Map.find_by(slug: params[:map_id]) @map = Map.find_by(slug: params[:map_id])
if logged_in? if logged_in?
save_tags(@map) save_tags(@map)
redirect_to @map redirect_to(@map)
else else
flash[:error] = 'You must be logged in to add tags' flash[:error] = 'You must be logged in to add tags'
redirect_to "/login?back_to=/maps/#{@map.slug}" redirect_to("/login?back_to=/maps/#{@map.slug}")
end end
end end
def show def show
@tag = Tag.find_by_name params[:id] @tag = Tag.find_by_name(params[:id])
@maps = @tag.maps.paginate(page: params[:page], per_page: 24) @maps = @tag.maps.paginate(page: params[:page], per_page: 24)
@title = "Maps tagged with ' #{@tag.name} '" @title = "Maps tagged with ' #{@tag.name} '"
tag = Tag.where(name: 'featured').first # note that this is not a join table but the .maps method still works tag = Tag.where(name: 'featured').first # note that this is not a join table but the .maps method still works
@unpaginated = true @unpaginated = true
@authors = User.where(login: tag.maps.collect(&:author)) if tag @authors = User.where(login: tag.maps.collect(&:author)) if tag
@authors ||= [] @authors ||= []
render template: 'tags/index' render(template: 'tags/index')
end end
def destroy def destroy
@@ -29,10 +29,10 @@ class TagsController < ApplicationController
if logged_in? && current_user.can_delete?(@tag) if logged_in? && current_user.can_delete?(@tag)
@tag.delete @tag.delete
flash[:notice] = "Tag #{@tag.name} deleted." flash[:notice] = "Tag #{@tag.name} deleted."
redirect_to @tag.map redirect_to(@tag.map)
else else
flash[:error] = 'You must be logged in to delete tags.' flash[:error] = 'You must be logged in to delete tags.'
redirect_to '/login' redirect_to('/login')
end end
end end

View File

@@ -15,7 +15,7 @@ class UsersController < ApplicationController
.group('maps.user_id') .group('maps.user_id')
.order(sort_column + ' ' + sort_direction) .order(sort_column + ' ' + sort_direction)
.paginate(page: params[:page], per_page: 24) .paginate(page: params[:page], per_page: 24)
render 'users/index' render('users/index')
end end
private private

View File

@@ -5,6 +5,6 @@ class UtilityController < ApplicationController
# /z/x/y.png # /z/x/y.png
# /z/x/(2*z-y-1).png # /z/x/(2*z-y-1).png
y = 2**params[:z].to_i - params[:y].to_i - 1 y = 2**params[:z].to_i - params[:y].to_i - 1
redirect_to "/tms/#{params[:id]}/#{params[:z]}/#{params[:x]}/#{y}.png" redirect_to("/tms/#{params[:id]}/#{params[:z]}/#{params[:x]}/#{y}.png")
end end
end end

View File

@@ -50,6 +50,6 @@ module ApplicationHelper
def sortable(column, title = nil) def sortable(column, title = nil)
title ||= column.titleize title ||= column.titleize
direction = column == sort_column && sort_direction == 'asc' ? 'desc' : 'asc' direction = column == sort_column && sort_direction == 'asc' ? 'desc' : 'asc'
link_to title, sort: column, direction: direction link_to(title, sort: column, direction: direction)
end end
end end

View File

@@ -43,11 +43,11 @@ module UsersHelper
def link_to_user(user, options = {}) def link_to_user(user, options = {})
raise "Invalid user" unless user raise "Invalid user" unless user
options.reverse_merge! content_method: :login, title_method: :login, class: :nickname options.reverse_merge!(content_method: :login, title_method: :login, class: :nickname)
content_text = options.delete(:content_text) content_text = options.delete(:content_text)
content_text ||= user.send(options.delete(:content_method)) content_text ||= user.send(options.delete(:content_method))
options[:title] ||= user.send(options.delete(:title_method)) options[:title] ||= user.send(options.delete(:title_method))
link_to h(content_text), user_path(user), options link_to(h(content_text), user_path(user), options)
end end
# #
@@ -65,11 +65,11 @@ module UsersHelper
def link_to_login_with_IP(content_text = nil, options = {}) # rubocop:disable Naming/MethodName def link_to_login_with_IP(content_text = nil, options = {}) # rubocop:disable Naming/MethodName
ip_addr = request.remote_ip ip_addr = request.remote_ip
content_text ||= ip_addr content_text ||= ip_addr
options.reverse_merge! title: ip_addr options.reverse_merge!(title: ip_addr)
if tag = options.delete(:tag) if tag = options.delete(:tag)
content_tag tag, h(content_text), options content_tag(tag, h(content_text), options)
else else
link_to h(content_text), login_path, options link_to(h(content_text), login_path, options)
end end
end end
@@ -79,12 +79,12 @@ module UsersHelper
# #
def link_to_current_user(options = {}) def link_to_current_user(options = {})
if current_user if current_user
link_to_user current_user, options link_to_user(current_user, options)
else else
content_text = options.delete(:content_text) || 'not signed in' content_text = options.delete(:content_text) || 'not signed in'
# kill ignored options from link_to_user # kill ignored options from link_to_user
%i(content_method title_method).each { |opt| options.delete(opt) } %i(content_method title_method).each { |opt| options.delete(opt) }
link_to_login_with_IP content_text, options link_to_login_with_IP(content_text, options)
end end
end end
end end

View File

@@ -4,7 +4,7 @@ class Export < ApplicationRecord
# currently exporting? # currently exporting?
def running? def running?
!(%w(complete none failed).include? status) !%w(complete none failed).include?(status)
end end
def self.average_cm_per_pixel def self.average_cm_per_pixel

View File

@@ -27,11 +27,11 @@ class User < ApplicationRecord
# #
def login=(value) def login=(value)
write_attribute :login, (value ? value.downcase : nil) write_attribute(:login, (value ? value.downcase : nil))
end end
def email=(value) def email=(value)
write_attribute :email, (value ? value.downcase : nil) write_attribute(:email, (value ? value.downcase : nil))
end end
def last_action def last_action

View File

@@ -11,7 +11,7 @@ class Warpable < ApplicationRecord
styles: { styles: {
medium: "500x375", medium: "500x375",
small: "240x180", small: "240x180",
thumb: "100x100>" thumb: "100x100>",
} }
validates_attachment_content_type :image, content_type: ["image/jpg", "image/jpeg", "image/png", "image/gif"] validates_attachment_content_type :image, content_type: ["image/jpg", "image/jpeg", "image/png", "image/gif"]
@@ -23,7 +23,7 @@ class Warpable < ApplicationRecord
# overriding JSON formatting for Leaflet.DistortableImage # overriding JSON formatting for Leaflet.DistortableImage
def as_json(options = {}) def as_json(options = {})
json = super options json = super(options)
json[:src] = image.url json[:src] = image.url
json[:srcmedium] = image.url(:medium) json[:srcmedium] = image.url(:medium)
json[:nodes] = nodes_array json[:nodes] = nodes_array
@@ -128,7 +128,7 @@ class Warpable < ApplicationRecord
end end
def nodes_array def nodes_array
Node.find nodes.split(',') Node.find(nodes.split(','))
end end
# allow uploads via URL # allow uploads via URL
@@ -155,12 +155,12 @@ class Warpable < ApplicationRecord
end end
def user_id def user_id
Map.find map_id Map.find(map_id)
map.user_id map.user_id
end end
# adjust filename behavior of Paperclip after migrating from attachment_fu # adjust filename behavior of Paperclip after migrating from attachment_fu
Paperclip.interpolates :custom_filename do |attachment, style| Paperclip.interpolates(:custom_filename) do |attachment, style|
if style == :original if style == :original
basename(attachment, style) # generate hash path here basename(attachment, style) # generate hash path here
else else

View File

@@ -23,6 +23,6 @@ production:
test: test:
<<: *default <<: *default
username: username: <%= ENV['DB_USER'] || 'root' %>
password: password: <%= ENV['DB_PASS'] || 'root' %>
database: mapknitter_test database: mapknitter_test

View File

@@ -8,11 +8,11 @@ FROM ruby:2.4.6-stretch
ENV HOME /root ENV HOME /root
# Backported GDAL # Backported GDAL
RUN echo "deb http://packages.laboratoriopublico.org/publiclab/ stretch main" > /etc/apt/sources.list.d/publiclab.list RUN echo "deb [trusted=yes] http://packages.laboratoriopublico.org/publiclab/ stretch main" > /etc/apt/sources.list.d/publiclab.list
# We bring our own key to verify our packages # We bring our own key to verify our packages
COPY sysadmin.publiclab.key /app/sysadmin.publiclab.key COPY sysadmin.publiclab.key /app/sysadmin.publiclab.key
RUN apt-key add /app/sysadmin.publiclab.key RUN apt-key add /app/sysadmin.publiclab.key > /dev/null 2>&1
# Install dependencies for Mapknitter # Install dependencies for Mapknitter
RUN apt-get update -qq && apt-get install -y \ RUN apt-get update -qq && apt-get install -y \
@@ -51,6 +51,7 @@ RUN git config --global url."https://".insteadOf git://
COPY . /app/ COPY . /app/
WORKDIR /app WORKDIR /app
RUN gem install bundler
RUN bundle install RUN bundle install
CMD [ "sh", "/app/start.sh" ] CMD [ "sh", "/app/start.sh" ]

View File

@@ -8,11 +8,11 @@ FROM ruby:2.4.6-stretch
ENV HOME /root ENV HOME /root
# Backported GDAL # Backported GDAL
RUN echo "deb http://packages.laboratoriopublico.org/publiclab/ stretch main" > /etc/apt/sources.list.d/publiclab.list RUN echo "deb [trusted=yes] http://packages.laboratoriopublico.org/publiclab/ stretch main" > /etc/apt/sources.list.d/publiclab.list
# We bring our own key to verify our packages # We bring our own key to verify our packages
COPY sysadmin.publiclab.key /app/sysadmin.publiclab.key COPY sysadmin.publiclab.key /app/sysadmin.publiclab.key
RUN apt-key add /app/sysadmin.publiclab.key RUN apt-key add /app/sysadmin.publiclab.key > /dev/null 2>&1
# Install dependencies for Mapknitter # Install dependencies for Mapknitter
RUN apt-get update -qq && apt-get install --allow-unauthenticated -y --no-install-recommends \ RUN apt-get update -qq && apt-get install --allow-unauthenticated -y --no-install-recommends \
@@ -41,6 +41,6 @@ WORKDIR /app
RUN apt-get clean && \ RUN apt-get clean && \
apt-get autoremove -y apt-get autoremove -y
RUN bundle install RUN gem install bundler && bundle install
CMD [ "sh", "/app/start.sh" ] CMD [ "sh", "/app/start.sh" ]