diff --git a/.ruby-version b/.ruby-version index a9eea9a34..d7edb5686 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-2.3.8 +ruby-2.6.5 diff --git a/CHANGELOG.md b/CHANGELOG.md index 62eafbce6..38b542d17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog Fab-manager +## v4.4.2 2020 May 19 + +- Upgraded to ruby 2.6.5 +- Prevent admins from leaving their dedicated group +- Faraday was downgraded from 1.0 to 0.17 for better compatibility with elasticsearch-ruby 5 (#205 #196) +- Added [an option](doc/environment.md#ALLOW_INSECURE_HTTP) to allow usage in production without HTTPS +- Now using node.js instead of therubyracer for building javascript assets +- Removed dependency to has_secure_token to fix warnings about already initialized constant +- Fix a bug: when an admin logs on the subscription page, his view is broken +- Fix a bug: admin's members list shows the same members multiple times +- Fix a bug: when a new account is created through the sign-up modal, the role is not reported in the StatisticProfile (#196) +- Fix a bug: openAPI clients interface has a bugged behavior when creating/editing a client +- Fix a security issue: updated actionpack-page_caching from 1.1.0 to 1.2.2 to fix [CVE-2020-8159](https://nvd.nist.gov/vuln/detail/CVE-2020-8159) +- [TODO DEPLOY] `rails fablab:fix:role_in_statistic_profile` +- [TODO DEPLOY] `rails fablab:es:generate_stats[2019-06-13]` (run after the command above!) +- [TODO DEPLOY] -> (only dev) `rvm use && bundle install` + ## v4.4.1 2020 May 12 - Prevent VersionCheckWorker from polluting the sidekiq stack in development diff --git a/Dockerfile b/Dockerfile index 04e5c8428..b93014ac6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:2.3.8-alpine +FROM ruby:2.6.5-alpine MAINTAINER peng@sleede.com # Install upgrade system packages @@ -28,6 +28,8 @@ RUN apk update && apk upgrade && \ git \ patch +RUN gem install bundler + # Throw error if Gemfile has been modified since Gemfile.lock RUN bundle config --global frozen 1 diff --git a/Gemfile b/Gemfile index dfe35d9bd..6c091f384 100644 --- a/Gemfile +++ b/Gemfile @@ -18,8 +18,6 @@ gem 'sass-rails', '~> 5.0', '>= 5.0.6' # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 4.1.20' -# See https://github.com/sstephenson/execjs#readme for more supported runtimes -gem 'therubyracer', '= 0.12.0', platforms: :ruby # Use jquery as the JavaScript library gem 'jquery-rails' @@ -115,6 +113,7 @@ gem 'prawn-table' gem 'elasticsearch-model', '~> 5' gem 'elasticsearch-persistence', '~> 5' gem 'elasticsearch-rails', '~> 5' +gem 'faraday', '~> 0.17' gem 'notify_with' @@ -122,7 +121,7 @@ gem 'pundit' gem 'oj' -gem 'actionpack-page_caching', '1.1.0' +gem 'actionpack-page_caching', '1.2.2' gem 'rails-observers' gem 'chroma' @@ -133,7 +132,6 @@ gem 'openlab_ruby' gem 'api-pagination' gem 'apipie-rails' -gem 'has_secure_token' # XLS files generation gem 'caxlsx' diff --git a/Gemfile.lock b/Gemfile.lock index 5513821f6..f6cbe0f62 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -39,8 +39,8 @@ GEM rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionpack-page_caching (1.1.0) - actionpack (>= 4.0.0, < 6) + actionpack-page_caching (1.2.2) + actionpack (>= 5.0.0) actionview (5.2.4.2) activesupport (= 5.2.4.2) builder (~> 3.1) @@ -165,7 +165,7 @@ GEM execjs (2.7.0) faker (2.10.2) i18n (>= 1.6, < 2) - faraday (1.0.0) + faraday (0.17.3) multipart-post (>= 1.2, < 3) ffi (1.12.2) font-awesome-rails (4.7.0.5) @@ -179,8 +179,6 @@ GEM raabro (~> 1.1) globalid (0.4.2) activesupport (>= 4.2.0) - has_secure_token (1.0.0) - activerecord (>= 3.0) hashdiff (1.0.1) hashery (2.1.2) hashie (4.1.0) @@ -217,11 +215,10 @@ GEM activerecord kaminari-core (= 1.2.0) kaminari-core (1.2.0) - libv8 (3.16.14.19) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - loofah (2.4.0) + loofah (2.5.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -348,7 +345,6 @@ GEM redis (4.1.3) redis-namespace (1.6.0) redis (>= 3.0.4) - ref (2.0.0) repost (0.3.2) responders (2.4.1) actionpack (>= 4.2.0, < 6.0) @@ -419,9 +415,6 @@ GEM ffi term-ansicolor (1.7.1) tins (~> 1.0) - therubyracer (0.12.0) - libv8 (~> 3.16.14.0) - ref thor (1.0.1) thread_safe (0.3.6) tilt (2.0.10) @@ -432,7 +425,7 @@ GEM camertron-eprun cldr-plurals-runtime-rb (~> 1.0) tzinfo - tzinfo (1.2.6) + tzinfo (1.2.7) thread_safe (~> 0.1) uglifier (4.2.0) execjs (>= 0.3.0, < 3) @@ -463,7 +456,7 @@ PLATFORMS DEPENDENCIES aasm - actionpack-page_caching (= 1.1.0) + actionpack-page_caching (= 1.2.2) active_record_query_trace api-pagination apipie-rails @@ -484,11 +477,11 @@ DEPENDENCIES elasticsearch-persistence (~> 5) elasticsearch-rails (~> 5) faker + faraday (~> 0.17) font-awesome-rails foreman forgery friendly_id (~> 5.1.0) - has_secure_token icalendar jbuilder (~> 2.5) jbuilder_cache_multi @@ -533,11 +526,10 @@ DEPENDENCIES spring-watcher-listen (~> 2.0.0) stripe (= 5.1.1) sys-filesystem - therubyracer (= 0.12.0) uglifier (>= 4.1.20) vcr (= 3.0.1) web-console (>= 3.3.0) webmock BUNDLED WITH - 1.17.3 + 2.1.4 diff --git a/README.md b/README.md index 01a4d8e53..29fb01742 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ Before reporting an issue, please check if your issue is not listed in the [know ## Related Documentation -- [Ruby 2.3.0](http://ruby-doc.org/core-2.3.0/) +- [Ruby 2.6.5](http://ruby-doc.org/core-2.6.5/) - [Ruby on Rails](http://api.rubyonrails.org) - [AngularJS](https://docs.angularjs.org/api) - [Angular-Bootstrap](http://angular-ui.github.io/bootstrap/) diff --git a/app/assets/javascripts/controllers/admin/open_api_clients.js b/app/assets/javascripts/controllers/admin/open_api_clients.js index 0b71944dc..17fb545ae 100644 --- a/app/assets/javascripts/controllers/admin/open_api_clients.js +++ b/app/assets/javascripts/controllers/admin/open_api_clients.js @@ -20,11 +20,18 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien $scope.clientFormVisible = false; $scope.client = {}; - $scope.toggleForm = () => $scope.clientFormVisible = !$scope.clientFormVisible; + /** + * Show the name edition form for a new client + */ + $scope.createClient = function () { + $scope.clientFormVisible = true; + $scope.client = {}; + }; - // Change the order criterion to the one provided - // @param orderBy {string} ordering criterion - // + /** + * Change the order criterion to the one provided + * @param orderBy {string} ordering criterion + */ $scope.setOrder = function (orderBy) { if ($scope.order === orderBy) { return $scope.order = `-${orderBy}`; @@ -33,6 +40,14 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien } }; + /** + * Reset the name ot its original value and close the edition form + */ + $scope.cancelEdit = function () { + $scope.client.name = $scope.clientOriginalName; + $scope.clientFormVisible = false; + }; + $scope.saveClient = function (client) { if (client.id != null) { OpenAPIClient.update({ id: client.id }, { open_api_client: client }, function (clientResp) { @@ -47,13 +62,13 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien } $scope.clientFormVisible = false; - $scope.clientForm.$setPristine(); - return $scope.client = {}; + $scope.client = {}; }; $scope.editClient = function (client) { $scope.clientFormVisible = true; - return $scope.client = client; + $scope.client = client; + $scope.clientOriginalName = client.name; }; $scope.deleteClient = index => diff --git a/app/assets/javascripts/controllers/application.js.erb b/app/assets/javascripts/controllers/application.js.erb index ea478fb65..c0f67baa2 100644 --- a/app/assets/javascripts/controllers/application.js.erb +++ b/app/assets/javascripts/controllers/application.js.erb @@ -450,9 +450,9 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco return $state.go(toState, toParams); } }, function (reason) { - // authentication did not ended successfully + // authentication did not end successfully if (reason === 'signup') { - // open signup modal + // open sign-up modal $scope.signup(); } else if (reason === 'resetPassword') { // open the 'reset password' modal diff --git a/app/assets/javascripts/controllers/plans.js.erb b/app/assets/javascripts/controllers/plans.js.erb index 7f4fa4386..19fbc30cf 100644 --- a/app/assets/javascripts/controllers/plans.js.erb +++ b/app/assets/javascripts/controllers/plans.js.erb @@ -197,10 +197,10 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop } } - $scope.$on('devise:new-session', function (event, user) { $scope.ctrl.member = user; }); + $scope.$on('devise:new-session', function (event, user) { if (user.role !== 'admin') { $scope.ctrl.member = user; } }); // watch when a coupon is applied to re-compute the total price - return $scope.$watch('coupon.applied', function (newValue, oldValue) { + $scope.$watch('coupon.applied', function (newValue, oldValue) { if ((newValue !== null) || (oldValue !== null)) { return updateCartPrice(); } diff --git a/app/assets/templates/admin/open_api_clients/index.html.erb b/app/assets/templates/admin/open_api_clients/index.html.erb index 07e9764f7..73ff4df84 100644 --- a/app/assets/templates/admin/open_api_clients/index.html.erb +++ b/app/assets/templates/admin/open_api_clients/index.html.erb @@ -34,14 +34,14 @@
- +
- +
diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb index e3de9c028..004566f98 100644 --- a/app/controllers/health_controller.rb +++ b/app/controllers/health_controller.rb @@ -20,7 +20,8 @@ class HealthController < ActionController::Base version: Version.up_to_date? }, stats: HealthService.stats, - tagline: 'The platform to manage your fablab or your coworking space.' + tagline: 'The platform to manage your fablab or your coworking space.', + url: 'https://www.fab-manager.com' } end end diff --git a/app/models/open_api/client.rb b/app/models/open_api/client.rb index 2dc2bf231..a9815eaf7 100644 --- a/app/models/open_api/client.rb +++ b/app/models/open_api/client.rb @@ -1,9 +1,29 @@ +# frozen_string_literal: true + +# OpenAPI::Client keeps track of the authorized accesses to the 3-rd party API (aka. OpenAPI) class OpenAPI::Client < ApplicationRecord has_many :calls_count_tracings, foreign_key: :open_api_client_id, dependent: :destroy - has_secure_token + validates :name, presence: true + validates_uniqueness_of :token + + before_create :set_initial_token def increment_calls_count update_column(:calls_count, calls_count+1) end + + def regenerate_token + update_attributes(token: generate_unique_secure_token) + end + + private + + def set_initial_token + self.token = generate_unique_secure_token + end + + def generate_unique_secure_token + SecureRandom.base58(24) + end end diff --git a/app/models/user.rb b/app/models/user.rb index 9be269857..545285114 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -319,6 +319,16 @@ class User < ApplicationRecord .delete_if { |col| blacklist.include?(col[0]) } end + # will update the statistic_profile after a group switch or a role update + def update_statistic_profile + raise NoProfileError if statistic_profile.nil? || statistic_profile.id.nil? + + statistic_profile.update_attributes( + group_id: group_id, + role_id: roles.first.id + ) + end + protected # remove projects drafts that are not linked to another user @@ -430,13 +440,4 @@ class User < ApplicationRecord email: email ) end - - # will update the statistic_profile after a group switch. Updating the role is not supported - def update_statistic_profile - raise NoProfileError if statistic_profile.nil? - - statistic_profile.update_attributes( - group_id: group_id - ) - end end diff --git a/app/policies/training_policy.rb b/app/policies/training_policy.rb index 585f1d7b5..6fb3d1215 100644 --- a/app/policies/training_policy.rb +++ b/app/policies/training_policy.rb @@ -8,7 +8,7 @@ class TrainingPolicy < ApplicationPolicy end end - def create + def create? user.admin? end diff --git a/app/services/members/import_service.rb b/app/services/members/import_service.rb index 305610750..d087cfc4b 100644 --- a/app/services/members/import_service.rb +++ b/app/services/members/import_service.rb @@ -7,8 +7,7 @@ class Members::ImportService require 'csv' log = [] begin - CSV.foreach(import.attachment.url, headers: true, col_sep: ';') do |row| - begin + CSV.foreach(import.attachment.url, headers: true, col_sep: ';') do |row| password = hide_password(row) log << { row: row.to_hash } @@ -31,7 +30,6 @@ class Members::ImportService puts e puts e.backtrace end - end rescue ArgumentError => e log << e.to_s puts e diff --git a/app/services/members/list_service.rb b/app/services/members/list_service.rb index 7b7c8d429..4f2f6c8ab 100644 --- a/app/services/members/list_service.rb +++ b/app/services/members/list_service.rb @@ -16,7 +16,7 @@ class Members::ListService SELECT MAX("created_at") AS "s2_created_at", "statistic_profile_id" AS "s2_statistic_profile_id" FROM "subscriptions" GROUP BY "statistic_profile_id" - ) As s2 + ) AS s2 ON "s1"."statistic_profile_id" = "s2"."s2_statistic_profile_id" WHERE "s1"."expiration_date" > now()::date ) AS "subscriptions" ON "subscriptions"."statistic_profile_id" = "statistic_profiles"."id" ' \ @@ -78,7 +78,7 @@ class Members::ListService direction = (params[:order_by][0] == '-' ? 'DESC' : 'ASC') order_key = (params[:order_by][0] == '-' ? params[:order_by][1, params[:order_by].size] : params[:order_by]) limit = params[:size] - offset = (params[:page]&.to_i || 1) - 1 + offset = ((params[:page]&.to_i || 1) - 1) * (params[:size]&.to_i || 1) order_key = case order_key when 'last_name' @@ -97,7 +97,7 @@ class Members::ListService 'users.id' end - "#{order_key} #{direction} LIMIT #{limit} OFFSET #{offset}" + "#{order_key} #{direction}, users.id ASC LIMIT #{limit} OFFSET #{offset}" end end end diff --git a/app/services/members/members_service.rb b/app/services/members/members_service.rb index a5f63ca8e..df90b1d4d 100644 --- a/app/services/members/members_service.rb +++ b/app/services/members/members_service.rb @@ -15,6 +15,12 @@ class Members::MembersService return false end + if params[:group_id] && params[:group_id].to_i != Group.find_by(slug: 'admins').id && @member.admin? + # an admin cannot change his group + @member.errors.add(:group_id, I18n.t('members.admins_cant_change_group')) + return false + end + not_complete = member.need_completion? up_result = member.update(params) @@ -35,13 +41,16 @@ class Members::MembersService @member.statistic_profile.group_id = params[:group_id] @member.statistic_profile.role_id = Role.find_or_create_by!(name: 'member').id - if @member.save - @member.generate_subscription_invoice(current_user.id) - @member.send_confirmation_instructions - UsersMailer.delay.notify_user_account_created(@member, @member.password) - true - else - false + ActiveRecord::Base.transaction do + if @member.save + @member.update_statistic_profile + @member.generate_subscription_invoice(current_user.id) + @member.send_confirmation_instructions + UsersMailer.delay.notify_user_account_created(@member, @member.password) + true + else + false + end end end diff --git a/app/views/api/members/mapping.json.jbuilder b/app/views/api/members/mapping.json.jbuilder index ffbc0da97..265942937 100644 --- a/app/views/api/members/mapping.json.jbuilder +++ b/app/views/api/members/mapping.json.jbuilder @@ -1,3 +1,5 @@ +# frozen_string_literal: true + @members.each do |member| - json.set! member.id, member.profile.full_name + json.set! member.id, member&.profile&.full_name end \ No newline at end of file diff --git a/config/initializers/active_record_base.rb b/config/initializers/active_record_base.rb index 07b68d779..4bb708204 100644 --- a/config/initializers/active_record_base.rb +++ b/config/initializers/active_record_base.rb @@ -1,24 +1,26 @@ +# frozen_string_literal: true + ActiveRecord::Base.class_eval do def dump_fixture fixture_file = "#{Rails.root}/test/fixtures/#{self.class.table_name}.yml" - File.open(fixture_file, "a") do |f| + File.open(fixture_file, 'a') do |f| f.puts({ "#{self.class.table_name.singularize}_#{id}" => attributes }. to_yaml.sub!(/---\s?/, "\n")) end end def self.dump_fixtures - fixture_file = "#{Rails.root}/test/fixtures/#{self.table_name}.yml" - mode = (File.exists?(fixture_file) ? 'a' : 'w') + fixture_file = "#{Rails.root}/test/fixtures/#{table_name}.yml" + mode = (File.exist?(fixture_file) ? 'a' : 'w') File.open(fixture_file, mode) do |f| - if self.attribute_names.include?("id") - self.all.each do |instance| - f.puts({ "#{self.table_name.singularize}_#{instance.id}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n")) + if attribute_names.include?('id') + all.each do |instance| + f.puts({ "#{table_name.singularize}_#{instance.id}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n")) end else - self.all.each_with_index do |instance, i| - f.puts({ "#{self.table_name.singularize}_#{i}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n")) + all.each_with_index do |instance, i| + f.puts({ "#{table_name.singularize}_#{i}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n")) end end end diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 3e0085a3c..d9c5c4111 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -2,4 +2,6 @@ # Be sure to restart your server when you modify this file. -Rails.application.config.session_store :cookie_store, key: '_Fab-manager_session', secure: (Rails.env.production? || Rails.env.staging?) +Rails.application.config.session_store :cookie_store, + key: '_Fab-manager_session', + secure: (Rails.env.production? || Rails.env.staging?) && !Rails.application.secrets.allow_insecure_http diff --git a/config/locales/en.yml b/config/locales/en.yml index b4d4eff67..38e57f15a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -53,6 +53,7 @@ en: #members management members: unable_to_change_the_group_while_a_subscription_is_running: "Unable to change the group while a subscription is running" + admins_cant_change_group: "Unable to remove an administrator from his dedicated group" please_input_the_authentication_code_sent_to_the_address: "Please input the authentication code sent to the e-mail address %{EMAIL}" your_authentication_code_is_not_valid: "Your authentication code is not valid." current_authentication_method_no_code: "The current authentication method does not require any migration code" diff --git a/config/locales/es.yml b/config/locales/es.yml index 764028fb7..e5a17c705 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -53,6 +53,7 @@ es: #members management members: unable_to_change_the_group_while_a_subscription_is_running: "No se puede cambiar de grupo mientras haya una suscripción en curso" + admins_cant_change_group: "Unable to remove an administrator from his dedicated group" please_input_the_authentication_code_sent_to_the_address: "Por favor Ingrese el código de autenticación enviado a la dirección de correo electrónico %{EMAIL}" your_authentication_code_is_not_valid: "Su código de autenticación no es válido." current_authentication_method_no_code: "El método de autenticación actual no requiere ningún código de migración" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index f4335218c..009fec28e 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -53,6 +53,7 @@ fr: #members management members: unable_to_change_the_group_while_a_subscription_is_running: "Impossible de changer le groupe tant qu'un abonnement est en cours" + admins_cant_change_group: "Impossible de supprimer un administrateur de son groupe dédié" please_input_the_authentication_code_sent_to_the_address: "Merci d'enter le code d'authentification qui a été envoyé à l'adresse de courriel %{EMAIL}" your_authentication_code_is_not_valid: "Votre code d'authentification n'est pas valide." current_authentication_method_no_code: "La méthode d'authentification actuelle ne requiert pas de code de migration" diff --git a/config/locales/pt.yml b/config/locales/pt.yml index baf95e3dc..e4e9b1af2 100755 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -53,6 +53,7 @@ pt: #members management members: unable_to_change_the_group_while_a_subscription_is_running: "Não é possível alterar o grupo enquanto uma assinatura está sendo executada" + admins_cant_change_group: "Unable to remove an administrator from his dedicated group" please_input_the_authentication_code_sent_to_the_address: "Por favor insira o código de autenticação enviado para seu endereço de email %{EMAIL}" your_authentication_code_is_not_valid: "Seu código de autentiicação não é válido." current_authentication_method_no_code: "O método de autenticação atual não requer nenhum código de migração" diff --git a/config/locales/zu.yml b/config/locales/zu.yml index fc2868d77..ed2d331a5 100644 --- a/config/locales/zu.yml +++ b/config/locales/zu.yml @@ -53,6 +53,7 @@ zu: #members management members: unable_to_change_the_group_while_a_subscription_is_running: "crwdns3275:0crwdne3275:0" + admins_cant_change_group: "crwdns20496:0crwdne20496:0" please_input_the_authentication_code_sent_to_the_address: "crwdns3277:0%{EMAIL}crwdne3277:0" your_authentication_code_is_not_valid: "crwdns3279:0crwdne3279:0" current_authentication_method_no_code: "crwdns3281:0crwdne3281:0" diff --git a/config/secrets.yml b/config/secrets.yml index f864f9dc1..6a261a3ec 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -56,6 +56,7 @@ development: superadmin_email: <%= ENV["SUPERADMIN_EMAIL"] %> recaptcha_site_key: <%= ENV["RECAPTCHA_SITE_KEY"] %> recaptcha_secret_key: <%= ENV["RECAPTCHA_SECRET_KEY"] %> + allow_insecure_http: <%= ENV.fetch("ALLOW_INSECURE_HTTP", false) %> test: secret_key_base: 83daf5e7b80d990f037407bab78dff9904aaf3c195a50f84fa8695a22287e707dfbd9524b403b1dcf116ae1d8c06844c3d7ed942564e5b46be6ae3ead93a9d30 @@ -103,6 +104,7 @@ test: superadmin_email: <%= ENV["SUPERADMIN_EMAIL"] %> recaptcha_site_key: <%= ENV["RECAPTCHA_SITE_KEY"] %> recaptcha_secret_key: <%= ENV["RECAPTCHA_SECRET_KEY"] %> + allow_insecure_http: <%= ENV.fetch("ALLOW_INSECURE_HTTP", false) %> staging: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> @@ -160,6 +162,7 @@ staging: recaptcha_site_key: <%= ENV["RECAPTCHA_SITE_KEY"] %> recaptcha_secret_key: <%= ENV["RECAPTCHA_SECRET_KEY"] %> enable_in_context_translation: <%= ENV["ENABLE_IN_CONTEXT_TRANSLATION"] %> + allow_insecure_http: <%= ENV.fetch("ALLOW_INSECURE_HTTP", false) %> # Do not keep production secrets in the repository, # instead read values from the environment. @@ -218,3 +221,4 @@ production: superadmin_email: <%= ENV["SUPERADMIN_EMAIL"] %> recaptcha_site_key: <%= ENV["RECAPTCHA_SITE_KEY"] %> recaptcha_secret_key: <%= ENV["RECAPTCHA_SECRET_KEY"] %> + allow_insecure_http: <%= ENV.fetch("ALLOW_INSECURE_HTTP", false) %> diff --git a/doc/development_readme.md b/doc/development_readme.md index 23839225d..7a681f880 100644 --- a/doc/development_readme.md +++ b/doc/development_readme.md @@ -93,7 +93,7 @@ This procedure is not easy to follow so if you don't need to write some code for 10. Install bundler in the current RVM gemset ```bash - gem install bundler --version=1.17.3 + gem install bundler ``` 11. Install the required ruby gems and javascript plugins diff --git a/doc/environment.md b/doc/environment.md index 90d713044..c98a597df 100644 --- a/doc/environment.md +++ b/doc/environment.md @@ -266,6 +266,14 @@ You can change this behavior by setting this variable to one of the following va - "session" to display the tours each time you reopen the application. - "manual" to prevent displaying the tours automatically; you'll still be able to trigger them by pressing the F1 key. + + + ALLOW_INSECURE_HTTP + +In production and staging environments, the session cookie won't be sent to the server unless through the HTTPS protocol. +If you're using Fab-manager on a non-public network or for testing purposes, you can disable this behavior by setting this variable to `true`. +Please, ensure you know what you're doing, as this can lead to serious security issues. + ## Internationalization setting. diff --git a/env.example b/env.example index 739f04dae..16130e8e7 100644 --- a/env.example +++ b/env.example @@ -71,6 +71,7 @@ SUMMERNOTE_LOCALE=fr-FR ANGULAR_LOCALE=fr-fr FULLCALENDAR_LOCALE=fr FORCE_VERSION_CHECK=false +ALLOW_INSECURE_HTTP=false ELASTICSEARCH_LANGUAGE_ANALYZER=french diff --git a/lib/tasks/fablab/es.rake b/lib/tasks/fablab/es.rake index 5950bd550..3b8285d25 100644 --- a/lib/tasks/fablab/es.rake +++ b/lib/tasks/fablab/es.rake @@ -166,9 +166,10 @@ namespace :fablab do desc '(re)generate statistics in ElasticSearch for the past period. Use 0 to generate for today' task :generate_stats, [:period] => :environment do |_task, args| - raise 'FATAL ERROR: You must pass a number of days (=> past period) to generate statistics on' unless args.period + raise 'FATAL ERROR: You must pass a number of days (=> past period) OR a date to generate statistics' unless args.period - days = args.period.to_i + days = date_to_days(args.period) + puts "\n==> generating statistics for the last #{days} days <==\n" if days.zero? StatisticService.new.generate_statistic(start_date: DateTime.current.beginning_of_day, end_date: DateTime.current.end_of_day) else @@ -178,5 +179,11 @@ namespace :fablab do end end + def date_to_days(value) + date = Date.parse(value.to_s) + (DateTime.current.to_date - date).to_i + rescue ArgumentError + value.to_i + end end end diff --git a/lib/tasks/fablab/fix.rake b/lib/tasks/fablab/fix.rake index af7836254..0d479b1e2 100644 --- a/lib/tasks/fablab/fix.rake +++ b/lib/tasks/fablab/fix.rake @@ -164,5 +164,15 @@ namespace :fablab do end end end + + desc '[release 4.4.2] add missing role to StatisticProfile' + task role_in_statistic_profile: :environment do + puts "Fixing #{StatisticProfile.where(role_id: nil).count} bugged profiles...\n" + StatisticProfile.where(role_id: nil).each do |sp| + role_id = sp&.user&.roles&.first&.id + sp.role_id = role_id + sp.save! + end + end end end diff --git a/package.json b/package.json index ab52b2670..631e53021 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fab-manager", - "version": "4.4.1", + "version": "4.4.2", "description": "Fab-manager is the FabLab management solution. It provides a comprehensive, web-based, open-source tool to simplify your administrative tasks and your marker's projects.", "keywords": [ "fablab", diff --git a/provision/box_setup.zsh b/provision/box_setup.zsh index a266beefb..491e2598b 100755 --- a/provision/box_setup.zsh +++ b/provision/box_setup.zsh @@ -157,11 +157,11 @@ install_rvm() { install_ruby() { echo 'Installing Ruby' sudo apt-get install -y libxml2-dev libxslt1-dev libpq-dev libidn11-dev - rvm install ruby-2.3.8 - rvm use ruby-2.3.8@global + rvm install ruby-2.6.5 + rvm use ruby-2.6.5@global gem update --system --no-doc gem update --no-doc - rvm use ruby-2.3.8 --default + rvm use ruby-2.6.5 --default rvm cleanup all } diff --git a/setup/env.example b/setup/env.example index 37a2edd57..65a19af58 100644 --- a/setup/env.example +++ b/setup/env.example @@ -72,6 +72,7 @@ NAVINUM_API_PASSWORD= LOG_LEVEL=debug DISK_SPACE_MB_ALERT='100' SUPERADMIN_EMAIL= +ALLOW_INSECURE_HTTP=false ALLOWED_EXTENSIONS=pdf ai eps cad math svg stl dxf dwg obj step iges igs 3dm 3dmf doc docx png ino scad fcad skp sldprt sldasm slddrw slddrt tex latex ps fcstd fcstd1