From 6794b12555a14bcc19194cc8646d5776e48df0fe Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 3 Dec 2018 15:10:04 +0100 Subject: [PATCH] force gawk during elastic upgrade & rubocop --- .rubocop.yml | 12 +- CHANGELOG.md | 3 + .../api/availabilities_controller.rb | 2 +- .../v1/bookable_machines_controller.rb | 2 +- app/helpers/availability_helper.rb | 2 +- app/models/abuse.rb | 3 +- app/models/age_range.rb | 2 +- app/models/auth_provider.rb | 29 ++-- app/models/availability.rb | 122 +++++++------- app/models/avoir.rb | 20 +-- app/models/category.rb | 12 +- app/models/coupon.rb | 25 ++- app/models/credit.rb | 8 +- app/models/custom_asset.rb | 8 +- app/models/event.rb | 122 ++++++++------ app/models/reservation.rb | 2 +- app/models/user.rb | 149 +++++++++--------- .../api/availabilities/public.json.jbuilder | 2 +- .../availabilities/trainings.json.jbuilder | 2 +- app/views/api/machines/show.json.jbuilder | 4 +- doc/elastic_upgrade.md | 4 +- scripts/elastic-upgrade.sh | 6 + 22 files changed, 290 insertions(+), 251 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 9eb10ab14..09fe97e24 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,8 +1,16 @@ Metrics/LineLength: - Max: 120 + Max: 125 Metrics/MethodLength: - Max: 16 + Max: 30 +Metrics/CyclomaticComplexity: + Max: 9 +Metrics/PerceivedComplexity: + Max: 9 +Metrics/AbcSize: + Max: 42 Style/BracesAroundHashParameters: EnforcedStyle: context_dependent Style/RegexpLiteral: EnforcedStyle: slashes +Style/EmptyElse: + EnforcedStyle: empty diff --git a/CHANGELOG.md b/CHANGELOG.md index bffb14800..2595435f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog Fab Manager +- Applied rubocop roles to ruby files +- Prevent running elastic-upgrade script with wrong awk version + # v2.7.3 2018 December 03 - Updated Uglifier gem to support ES6 syntax diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index c93dc3223..ee7776bf9 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -435,7 +435,7 @@ class API::AvailabilitiesController < API::ApiController end availabilities_filtered.delete_if do |a| if params[:dispo] == 'false' - a.is_reserved or (a.try(:is_completed) and a.is_completed) + a.is_reserved or (a.try(:completed?) and a.completed?) end end end diff --git a/app/controllers/open_api/v1/bookable_machines_controller.rb b/app/controllers/open_api/v1/bookable_machines_controller.rb index bbe6af19c..d7a981d76 100644 --- a/app/controllers/open_api/v1/bookable_machines_controller.rb +++ b/app/controllers/open_api/v1/bookable_machines_controller.rb @@ -14,7 +14,7 @@ class OpenAPI::V1::BookableMachinesController < OpenAPI::V1::BaseController user = User.find(params[:user_id]) @machines.delete_if do |machine| - (machine.trainings.count != 0) and !user.is_training_machine?(machine) + (machine.trainings.count != 0) and !user.training_machine?(machine) end diff --git a/app/helpers/availability_helper.rb b/app/helpers/availability_helper.rb index 71fd74b27..474d7c9d3 100644 --- a/app/helpers/availability_helper.rb +++ b/app/helpers/availability_helper.rb @@ -41,7 +41,7 @@ module AvailabilityHelper def trainings_events_border_color(availability) if availability.is_reserved IS_RESERVED_BY_CURRENT_USER - elsif availability.is_completed + elsif availability.completed? IS_COMPLETED else case availability.available_type diff --git a/app/models/abuse.rb b/app/models/abuse.rb index 56c80fe73..c02066be6 100644 --- a/app/models/abuse.rb +++ b/app/models/abuse.rb @@ -5,10 +5,11 @@ class Abuse < ActiveRecord::Base after_create :notify_admins_abuse_reported - validates :first_name, :last_name, :email, :message, :presence => true + validates :first_name, :last_name, :email, :message, presence: true private + def notify_admins_abuse_reported NotificationCenter.call type: 'notify_admin_abuse_reported', receiver: User.admins, diff --git a/app/models/age_range.rb b/app/models/age_range.rb index 0b4c83b38..b2f508588 100644 --- a/app/models/age_range.rb +++ b/app/models/age_range.rb @@ -5,7 +5,7 @@ class AgeRange < ActiveRecord::Base has_many :events, dependent: :nullify def safe_destroy - if self.events.count == 0 + if events.count.zero? destroy else false diff --git a/app/models/auth_provider.rb b/app/models/auth_provider.rb index 4c5e547a3..17e664b35 100644 --- a/app/models/auth_provider.rb +++ b/app/models/auth_provider.rb @@ -11,16 +11,17 @@ class AuthProvider < ActiveRecord::Base end end - PROVIDABLE_TYPES = %w(DatabaseProvider OAuth2Provider) + PROVIDABLE_TYPES = %w[DatabaseProvider OAuth2Provider].freeze - belongs_to :providable, :polymorphic => true, dependent: :destroy + belongs_to :providable, polymorphic: true, dependent: :destroy accepts_nested_attributes_for :providable attr_accessible :name, :providable_type, :providable_attributes before_create :set_initial_state - def build_providable(params, assignment_options) + def build_providable(params) raise "Unknown providable_type: #{providable_type}" unless PROVIDABLE_TYPES.include?(providable_type) + self.providable = providable_type.constantize.new(params) end @@ -30,11 +31,9 @@ class AuthProvider < ActiveRecord::Base begin provider = find_by(status: 'active') - if provider.nil? - return local - else - return provider - end + return local if provider.nil? + + return provider rescue ActiveRecord::StatementInvalid # we fall here on database creation because the table "active_providers" still does not exists at the moment return local @@ -43,13 +42,12 @@ class AuthProvider < ActiveRecord::Base ## Get the provider matching the omniAuth strategy name def self.from_strategy_name(strategy_name) - if strategy_name.blank? or all.empty? - return SimpleAuthProvider.new - end + return SimpleAuthProvider.new if strategy_name.blank? || all.empty? + parsed = /^([^-]+)-(.+)$/.match(strategy_name) ret = nil all.each do |strategy| - if strategy.provider_type == parsed[1] and strategy.name.downcase.parameterize == parsed[2] + if strategy.provider_type == parsed[1] && strategy.name.downcase.parameterize == parsed[2] ret = strategy break end @@ -59,7 +57,7 @@ class AuthProvider < ActiveRecord::Base ## Return the name that should be registered in OmniAuth for the corresponding strategy def strategy_name - provider_type+'-'+name.downcase.parameterize + provider_type + '-' + name.downcase.parameterize end ## Return the provider type name without the "Provider" part. @@ -81,7 +79,7 @@ class AuthProvider < ActiveRecord::Base end def safe_destroy - if self.status != 'active' + if status != 'active' destroy else false @@ -89,9 +87,10 @@ class AuthProvider < ActiveRecord::Base end private + def set_initial_state # the initial state of a new AuthProvider will be 'pending', except if there is currently # no providers in the database, he we will be 'active' (see seeds.rb) - self.status = 'pending' unless AuthProvider.count == 0 + self.status = 'pending' unless AuthProvider.count.zero? end end diff --git a/app/models/availability.rb b/app/models/availability.rb index f738ea2a2..fe3b28f46 100644 --- a/app/models/availability.rb +++ b/app/models/availability.rb @@ -48,19 +48,27 @@ class Availability < ActiveRecord::Base def safe_destroy case available_type - when 'machines' - reservations = Reservation.where(reservable_type: 'Machine', reservable_id: machine_ids).joins(:slots).where('slots.availability_id = ?', id) - when 'training' - reservations = Reservation.where(reservable_type: 'Training', reservable_id: training_ids).joins(:slots).where('slots.availability_id = ?', id) - when 'space' - reservations = Reservation.where(reservable_type: 'Space', reservable_id: space_ids).joins(:slots).where('slots.availability_id = ?', id) - when 'event' - reservations = Reservation.where(reservable_type: 'Event', reservable_id: event&.id).joins(:slots).where('slots.availability_id = ?', id) - else - STDERR.puts "[safe_destroy] Availability with unknown type #{available_type}" - reservations = [] + when 'machines' + reservations = Reservation.where(reservable_type: 'Machine', reservable_id: machine_ids) + .joins(:slots) + .where('slots.availability_id = ?', id) + when 'training' + reservations = Reservation.where(reservable_type: 'Training', reservable_id: training_ids) + .joins(:slots) + .where('slots.availability_id = ?', id) + when 'space' + reservations = Reservation.where(reservable_type: 'Space', reservable_id: space_ids) + .joins(:slots) + .where('slots.availability_id = ?', id) + when 'event' + reservations = Reservation.where(reservable_type: 'Event', reservable_id: event&.id) + .joins(:slots) + .where('slots.availability_id = ?', id) + else + STDERR.puts "[safe_destroy] Availability with unknown type #{available_type}" + reservations = [] end - if reservations.size == 0 + if reservations.size.zero? # this update may not call any rails callbacks, that's why we use direct SQL update update_column(:destroying, true) destroy @@ -71,86 +79,84 @@ class Availability < ActiveRecord::Base ## compute the total number of places over the whole space availability def available_space_places - if available_type === 'space' - ((end_at - start_at)/ApplicationHelper::SLOT_DURATION.minutes).to_i * nb_total_places - end + return unless available_type == 'space' + + ((end_at - start_at)/ApplicationHelper::SLOT_DURATION.minutes).to_i * nb_total_places end def title(filter = {}) case available_type - when 'machines' - if filter[:machine_ids] - return machines.to_ary.delete_if {|m| !filter[:machine_ids].include?(m.id)}.map(&:name).join(' - ') - end - return machines.map(&:name).join(' - ') - when 'event' - event.name - when 'training' - trainings.map(&:name).join(' - ') - when 'space' - spaces.map(&:name).join(' - ') - else - STDERR.puts "[title] Availability with unknown type #{available_type}" - '???' + when 'machines' + if filter[:machine_ids] + return machines.to_ary.delete_if { |m| !filter[:machine_ids].include?(m.id) }.map(&:name).join(' - ') + end + + machines.map(&:name).join(' - ') + when 'event' + event.name + when 'training' + trainings.map(&:name).join(' - ') + when 'space' + spaces.map(&:name).join(' - ') + else + STDERR.puts "[title] Availability with unknown type #{available_type}" + '???' end end # return training reservations is complete? # if haven't defined a nb_total_places, places are unlimited - def is_completed + def completed? return false if nb_total_places.blank? + if available_type == 'training' || available_type == 'space' nb_total_places <= slots.to_a.select {|s| s.canceled_at == nil }.size elsif available_type == 'event' - event.nb_free_places == 0 + event.nb_free_places.zero? end end def nb_total_places case available_type - when 'training' - super.presence || trainings.map {|t| t.nb_total_places}.reduce(:+) - when 'event' - event.nb_total_places - when 'space' - super.presence || spaces.map {|s| s.default_places}.reduce(:+) - else - nil + when 'training' + super.presence || trainings.map(&:nb_total_places).reduce(:+) + when 'event' + event.nb_total_places + when 'space' + super.presence || spaces.map(&:default_places).reduce(:+) + else + nil end end - def as_indexed_json json = JSON.parse(to_json) json['hours_duration'] = (end_at - start_at) / (60 * 60) - case available_type - when 'machines' - json['subType'] = machines_availabilities.map{|ma| ma.machine.friendly_id} - when'training' - json['subType'] = trainings_availabilities.map{|ta| ta.training.friendly_id} - when 'event' - json['subType'] = [event.category.friendly_id] - when 'space' - json['subType'] = spaces_availabilities.map{|sa| sa.space.friendly_id} - else - json['subType'] = [] - end + json['subType'] = case available_type + when 'machines' + machines_availabilities.map{ |ma| ma.machine.friendly_id } + when 'training' + trainings_availabilities.map{ |ta| ta.training.friendly_id } + when 'event' + [event.category.friendly_id] + when 'space' + spaces_availabilities.map{ |sa| sa.space.friendly_id } + else + [] + end json['bookable_hours'] = json['hours_duration'] * json['subType'].length json['date'] = start_at.to_date json.to_json end private + def length_must_be_1h_minimum - if end_at < (start_at + 1.hour) - errors.add(:end_at, I18n.t('availabilities.must_be_at_least_1_hour_after_the_start_date')) - end + errors.add(:end_at, I18n.t('availabilities.must_be_at_least_1_hour_after_the_start_date')) if end_at < (start_at + 1.hour) end def should_be_associated - if available_type == 'machines' and machine_ids.count == 0 - errors.add(:machine_ids, I18n.t('availabilities.must_be_associated_with_at_least_1_machine')) - end + errors.add(:machine_ids, I18n.t('availabilities.must_be_associated_with_at_least_1_machine')) if available_type == 'machines' && machine_ids.count == 0 end end diff --git a/app/models/avoir.rb b/app/models/avoir.rb index 3150c33f5..66044d1fd 100644 --- a/app/models/avoir.rb +++ b/app/models/avoir.rb @@ -1,12 +1,12 @@ class Avoir < Invoice belongs_to :invoice - validates :avoir_mode, :inclusion => {:in => %w(stripe cheque transfer none cash wallet)} + validates :avoir_mode, inclusion: {in: %w[stripe cheque transfer none cash wallet] } attr_accessor :invoice_items_ids def generate_reference - pattern = Setting.find_by({name: 'invoice_reference'}).value + pattern = Setting.find_by(name: 'invoice_reference').value # invoice number per day (dd..dd) reference = pattern.gsub(/d+(?![^\[]*\])/) do |match| @@ -22,21 +22,21 @@ class Avoir < Invoice end # full year (YYYY) - reference.gsub!(/YYYY(?![^\[]*\])/, self.created_at.strftime('%Y')) + reference.gsub!(/YYYY(?![^\[]*\])/, created_at.strftime('%Y')) # year without century (YY) - reference.gsub!(/YY(?![^\[]*\])/, self.created_at.strftime('%y')) + reference.gsub!(/YY(?![^\[]*\])/, created_at.strftime('%y')) - # abreviated month name (MMM) - reference.gsub!(/MMM(?![^\[]*\])/, self.created_at.strftime('%^b')) + # abbreviated month name (MMM) + reference.gsub!(/MMM(?![^\[]*\])/, created_at.strftime('%^b')) # month of the year, zero-padded (MM) - reference.gsub!(/MM(?![^\[]*\])/, self.created_at.strftime('%m')) + reference.gsub!(/MM(?![^\[]*\])/, created_at.strftime('%m')) # month of the year, non zero-padded (M) - reference.gsub!(/M(?![^\[]*\])/, self.created_at.strftime('%-m')) + reference.gsub!(/M(?![^\[]*\])/, created_at.strftime('%-m')) # day of the month, zero-padded (DD) - reference.gsub!(/DD(?![^\[]*\])/, self.created_at.strftime('%d')) + reference.gsub!(/DD(?![^\[]*\])/, created_at.strftime('%d')) # day of the month, non zero-padded (DD) - reference.gsub!(/DD(?![^\[]*\])/, self.created_at.strftime('%-d')) + reference.gsub!(/DD(?![^\[]*\])/, created_at.strftime('%-d')) # information about refund/avoir (R[text]) reference.gsub!(/R\[([^\]]+)\]/, '\1') diff --git a/app/models/category.rb b/app/models/category.rb index f407c6366..7fbc61258 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -11,23 +11,25 @@ class Category < ActiveRecord::Base def create_statistic_subtype index = StatisticIndex.where(es_type_key: 'event') - StatisticSubType.create!({statistic_types: index.first.statistic_types, key: self.slug, label: self.name}) + StatisticSubType.create!(statistic_types: index.first.statistic_types, key: slug, label: name) end def update_statistic_subtype index = StatisticIndex.where(es_type_key: 'event') - subtype = StatisticSubType.joins(statistic_type_sub_types: :statistic_type).where(key: self.slug, statistic_types: { statistic_index_id: index.first.id }).first - subtype.label = self.name + subtype = StatisticSubType.joins(statistic_type_sub_types: :statistic_type) + .where(key: slug, statistic_types: { statistic_index_id: index.first.id }) + .first + subtype.label = name subtype.save! end def remove_statistic_subtype - subtype = StatisticSubType.where(key: self.slug).first + subtype = StatisticSubType.where(key: slug).first subtype.destroy! end def safe_destroy - if Category.count > 1 && self.events.count == 0 + if Category.count > 1 && events.count.zero? destroy else false diff --git a/app/models/coupon.rb b/app/models/coupon.rb index 69b37310e..bf0b1a730 100644 --- a/app/models/coupon.rb +++ b/app/models/coupon.rb @@ -6,15 +6,15 @@ class Coupon < ActiveRecord::Base validates :name, presence: true validates :code, presence: true - validates :code, format: { with: /\A[A-Z0-9\-]+\z/ ,message: 'only caps letters, numbers, and dashes'} + validates :code, format: { with: /\A[A-Z0-9\-]+\z/, message: 'only caps letters, numbers, and dashes'} validates :code, uniqueness: true validates :validity_per_user, presence: true - validates :validity_per_user, inclusion: { in: %w(once forever) } + validates :validity_per_user, inclusion: { in: %w[once forever] } validates_with CouponDiscountValidator validates_with CouponExpirationValidator def safe_destroy - if self.invoices.size == 0 + if invoices.size.zero? destroy else false @@ -36,15 +36,15 @@ class Coupon < ActiveRecord::Base # @return {String} status identifier ## def status(user_id = nil, amount = nil) - if not active? + if !active? 'disabled' - elsif (!valid_until.nil?) and valid_until.at_end_of_day < DateTime.now + elsif !valid_until.nil? && valid_until.at_end_of_day < DateTime.now 'expired' - elsif (!max_usages.nil?) and invoices.count >= max_usages + elsif !max_usages.nil? && invoices.count >= max_usages 'sold_out' - elsif (!user_id.nil?) and validity_per_user == 'once' and users_ids.include?(user_id.to_i) + elsif !user_id.nil? && validity_per_user == 'once' && users_ids.include?(user_id.to_i) 'already_used' - elsif (!amount.nil?) and type == 'amount_off' and amount_off > amount.to_f + elsif !amount.nil? && type == 'amount_off' && amount_off > amount.to_f 'amount_exceeded' else 'active' @@ -60,15 +60,11 @@ class Coupon < ActiveRecord::Base end def users - self.invoices.map do |i| - i.user - end + invoices.map(&:user) end def users_ids - users.map do |u| - u.id - end + users.map(&:id) end def send_to(user_id) @@ -78,6 +74,7 @@ class Coupon < ActiveRecord::Base end private + def create_stripe_coupon StripeWorker.perform_async(:create_stripe_coupon, id) end diff --git a/app/models/credit.rb b/app/models/credit.rb index 689d5a3ac..754af399c 100644 --- a/app/models/credit.rb +++ b/app/models/credit.rb @@ -3,10 +3,10 @@ class Credit < ActiveRecord::Base belongs_to :plan has_many :users_credits, dependent: :destroy - validates :creditable_id, uniqueness: { scope: [:creditable_type, :plan_id] } - validates :hours, numericality: { greater_than_or_equal_to: 0 }, if: :is_not_training_credit? + validates :creditable_id, uniqueness: { scope: %i[creditable_type plan_id] } + validates :hours, numericality: { greater_than_or_equal_to: 0 }, if: :not_training_credit? - def is_not_training_credit? - not (creditable_type === 'Training') + def not_training_credit? + !creditable_type == 'Training' end end diff --git a/app/models/custom_asset.rb b/app/models/custom_asset.rb index cb47e9bd3..a0e0b22a4 100644 --- a/app/models/custom_asset.rb +++ b/app/models/custom_asset.rb @@ -2,17 +2,15 @@ class CustomAsset < ActiveRecord::Base has_one :custom_asset_file, as: :viewable, dependent: :destroy accepts_nested_attributes_for :custom_asset_file, allow_destroy: true - # static method to retrieve the attachement URL of the custom asset + # static method to retrieve the attachment URL of the custom asset def self.get_url(name) asset = CustomAsset.find_by(name: name) - asset.custom_asset_file.attachment_url if asset and asset.custom_asset_file + asset&.custom_asset_file&.attachment_url end after_update :update_stylesheet if :viewable_changed? def update_stylesheet - if %w(profile-image-file).include? self.name - Stylesheet.first.rebuild! - end + Stylesheet.first.rebuild! if %w[profile-image-file].include? name end end diff --git a/app/models/event.rb b/app/models/event.rb index 6ad394788..a91060ed5 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -25,23 +25,25 @@ class Event < ActiveRecord::Base after_create :event_recurrence before_save :update_nb_free_places # update event updated_at for index cache - after_save -> { self.touch } + after_save -> { touch } def name title end def themes - self.event_themes + event_themes end def recurrence_events - Event.includes(:availability).where('events.recurrence_id = ? AND events.id != ? AND availabilities.start_at >= ?', recurrence_id, id, Time.now).references(:availabilities) + Event.includes(:availability) + .where('events.recurrence_id = ? AND events.id != ? AND availabilities.start_at >= ?', recurrence_id, id, Time.now) + .references(:availabilities) end def safe_destroy reservations = Reservation.where(reservable_type: 'Event', reservable_id: id) - if reservations.size == 0 + if reservations.size.zero? destroy else false @@ -71,64 +73,80 @@ class Event < ActiveRecord::Base # end private + def event_recurrence - if recurrence.present? and recurrence != 'none' - case recurrence - when 'day' - on = nil - when 'week' - on = availability.start_at.wday - when 'month' - on = availability.start_at.day - when 'year' - on = [availability.start_at.month, availability.start_at.day] - else + return unless recurrence.present? && recurrence != 'none' + + on = case recurrence + when 'day' + nil + when 'week' + availability.start_at.wday + when 'month' + availability.start_at.day + when 'year' + [availability.start_at.month, availability.start_at.day] + else + nil + end + r = Recurrence.new(every: recurrence, on: on, starts: availability.start_at+1.day, until: recurrence_end_at) + r.events.each do |date| + days_diff = availability.end_at.day - availability.start_at.day + start_at = DateTime.new( + date.year, + date.month, + date.day, + availability.start_at.hour, + availability.start_at.min, + availability.start_at.sec, + availability.start_at.zone + ) + start_at = dst_correction(availability.start_at,start_at) + end_date = date + days_diff.days + end_at = DateTime.new( + end_date.year, + end_date.month, + end_date.day, + availability.end_at.hour, + availability.end_at.min, + availability.end_at.sec, + availability.end_at.zone + ) + end_at = dst_correction(availability.start_at,end_at) + ei = EventImage.new(attachment: event_image.attachment) if event_image + efs = event_files.map do |f| + EventFile.new(attachment: f.attachment) end - r = Recurrence.new(every: recurrence, on: on, starts: availability.start_at+1.day, until: recurrence_end_at) - r.events.each do |date| - days_diff = availability.end_at.day - availability.start_at.day - start_at = DateTime.new(date.year, date.month, date.day, availability.start_at.hour, availability.start_at.min, availability.start_at.sec, availability.start_at.zone) - start_at = dst_correction(availability.start_at,start_at) - end_date = date + days_diff.days - end_at = DateTime.new(end_date.year, end_date.month, end_date.day, availability.end_at.hour, availability.end_at.min, availability.end_at.sec, availability.end_at.zone) - end_at = dst_correction(availability.start_at,end_at) - if event_image - ei = EventImage.new(attachment: event_image.attachment) - end - efs = event_files.map do |f| - EventFile.new(attachment: f.attachment) - end - event_price_cats = [] - event_price_categories.each do |epc| - event_price_cats.push(EventPriceCategory.new(price_category_id: epc.price_category_id, amount: epc.amount)) - end - event = Event.new({ - recurrence: 'none', - title: title, - description: description, - event_image: ei, - event_files: efs, - availability: Availability.new(start_at: start_at, end_at: end_at, available_type: 'event'), - availability_id: nil, - category_id: category_id, - age_range_id: age_range_id, - event_themes: event_themes, - amount: amount, - event_price_categories: event_price_cats, - nb_total_places: nb_total_places, - recurrence_id: id - }) - event.save + event_price_cats = [] + event_price_categories.each do |epc| + event_price_cats.push(EventPriceCategory.new(price_category_id: epc.price_category_id, amount: epc.amount)) end - update_columns(recurrence_id: id) + event = Event.new( + recurrence: 'none', + title: title, + description: description, + event_image: ei, + event_files: efs, + availability: Availability.new(start_at: start_at, end_at: end_at, available_type: 'event'), + availability_id: nil, + category_id: category_id, + age_range_id: age_range_id, + event_themes: event_themes, + amount: amount, + event_price_categories: event_price_cats, + nb_total_places: nb_total_places, + recurrence_id: id + ) + event.save end + update_columns(recurrence_id: id) end def update_nb_free_places if nb_total_places.nil? self.nb_free_places = nil else - reserved_places = reservations.map(&:total_booked_seats).inject(0){|sum, t| sum + t } + reserved_places = reservations.map(&:total_booked_seats).inject(0){ |sum, t| sum + t } self.nb_free_places = (nb_total_places - reserved_places) end end diff --git a/app/models/reservation.rb b/app/models/reservation.rb index 18a90bf22..d0119fec9 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -427,7 +427,7 @@ class Reservation < ActiveRecord::Base def training_not_fully_reserved slot = self.slots.first - errors.add(:training, "already fully reserved") if Availability.find(slot.availability_id).is_completed + errors.add(:training, "already fully reserved") if Availability.find(slot.availability_id).completed? end private diff --git a/app/models/user.rb b/app/models/user.rb index 53cec3c8f..c8ec16188 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,13 +3,13 @@ class User < ActiveRecord::Base include NotifyWith::NotificationAttachedObject # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable - devise :database_authenticatable, :registerable, - :recoverable, :rememberable, :trackable, :validatable, + devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :async rolify # enable OmniAuth authentication only if needed - devise :omniauthable, :omniauth_providers => [AuthProvider.active.strategy_name.to_sym] unless AuthProvider.active.providable_type == DatabaseProvider.name + devise :omniauthable, omniauth_providers: [AuthProvider.active.strategy_name.to_sym] unless + AuthProvider.active.providable_type == DatabaseProvider.name extend FriendlyId friendly_id :username, use: :slugged @@ -24,7 +24,7 @@ class User < ActiveRecord::Base has_many :reservations, dependent: :destroy accepts_nested_attributes_for :reservations, allow_destroy: true - # Les formations sont déjà faites + # Trainings that were already passed has_many :user_trainings, dependent: :destroy has_many :trainings, through: :user_trainings @@ -52,7 +52,7 @@ class User < ActiveRecord::Base # fix for create admin user before_save do - self.email.downcase! if self.email + email&.downcase! end before_create :assign_default_role @@ -76,10 +76,10 @@ class User < ActiveRecord::Base def to_json(options = {}) ApplicationController.new.view_context.render( - partial: 'api/members/member', - locals: { :member => self }, - formats: [:json], - handlers: [:jbuilder] + partial: 'api/members/member', + locals: { member: self }, + formats: [:json], + handlers: [:jbuilder] ) end @@ -87,11 +87,10 @@ class User < ActiveRecord::Base User.with_role(:admin) end - def is_training_machine?(machine) + def training_machine?(machine) return true if is_admin? - trainings.map do |t| - t.machines - end.flatten.uniq.include?(machine) + + trainings.map(&:machines).flatten.uniq.include?(machine) end def training_reservation_by_machine(machine) @@ -100,6 +99,7 @@ class User < ActiveRecord::Base def subscribed_plan return nil if subscription.nil? or subscription.expired_at < Time.now + subscription.plan end @@ -120,12 +120,12 @@ class User < ActiveRecord::Base end def generate_admin_invoice(offer_day = false, offer_day_start_at = nil) - if self.subscription - if offer_day - self.subscription.generate_and_save_offer_day_invoice(offer_day_start_at) unless self.invoicing_disabled? - else - self.subscription.generate_and_save_invoice unless self.invoicing_disabled? - end + return unless subscription + + if offer_day + subscription.generate_and_save_offer_day_invoice(offer_day_start_at) unless invoicing_disabled? + else + subscription.generate_and_save_invoice unless invoicing_disabled? end end @@ -144,7 +144,7 @@ class User < ActiveRecord::Base end def active_for_authentication? - super and self.is_active? + super && is_active? end def self.from_omniauth(auth) @@ -165,8 +165,8 @@ class User < ActiveRecord::Base end def need_completion? - profile.gender.nil? or profile.first_name.blank? or profile.last_name.blank? or username.blank? or - email.blank? or encrypted_password.blank? or group_id.nil? or profile.birthday.blank? or profile.phone.blank? + profile.gender.nil? || profile.first_name.blank? || profile.last_name.blank? || username.blank? || + email.blank? || encrypted_password.blank? || group_id.nil? || profile.birthday.blank? || profile.phone.blank? end ## Retrieve the requested data in the User and user's Profile tables @@ -177,21 +177,20 @@ class User < ActiveRecord::Base self[parsed[2].to_sym] elsif parsed[1] == 'profile' case sso_mapping - when 'profile.avatar' - self.profile.user_avatar.remote_attachment_url - when 'profile.address' - self.profile.address.address - when 'profile.organization_name' - self.profile.organization.name - when 'profile.organization_address' - self.profile.organization.address.address - else - self.profile[parsed[2].to_sym] + when 'profile.avatar' + profile.user_avatar.remote_attachment_url + when 'profile.address' + profile.address.address + when 'profile.organization_name' + profile.organization.name + when 'profile.organization_address' + profile.organization.address.address + else + profile[parsed[2].to_sym] end end end - ## Set some data on the current user, according to the sso_key given ## @param sso_mapping {String} must be of form 'user._field_' or 'profile._field_'. Eg. 'user.email' ## @param data {*} the data to put in the given key. Eg. 'user@example.com' @@ -200,21 +199,21 @@ class User < ActiveRecord::Base self[sso_mapping[5..-1].to_sym] = data unless data.nil? elsif sso_mapping.to_s.start_with? 'profile.' case sso_mapping.to_s - when 'profile.avatar' - self.profile.user_avatar ||= UserAvatar.new - self.profile.user_avatar.remote_attachment_url = data - when 'profile.address' - self.profile.address ||= Address.new - self.profile.address.address = data - when 'profile.organization_name' - self.profile.organization ||= Organization.new - self.profile.organization.name = data - when 'profile.organization_address' - self.profile.organization ||= Organization.new - self.profile.organization.address ||= Address.new - self.profile.organization.address.address = data - else - self.profile[sso_mapping[8..-1].to_sym] = data unless data.nil? + when 'profile.avatar' + profile.user_avatar ||= UserAvatar.new + profile.user_avatar.remote_attachment_url = data + when 'profile.address' + profile.address ||= Address.new + profile.address.address = data + when 'profile.organization_name' + profile.organization ||= Organization.new + profile.organization.name = data + when 'profile.organization_address' + profile.organization ||= Organization.new + profile.organization.address ||= Address.new + profile.organization.address.address = data + else + profile[sso_mapping[8..-1].to_sym] = data unless data.nil? end end end @@ -232,7 +231,7 @@ class User < ActiveRecord::Base raise SecurityError, 'The identity provider does not match the activated one' end - if User.where(provider: auth.provider, uid: auth.uid).size > 0 + if User.where(provider: auth.provider, uid: auth.uid).size.positive? raise DuplicateIndexError, "This #{active_provider.name} account is already linked to an existing user" end @@ -253,9 +252,7 @@ class User < ActiveRecord::Base # check that the email duplication was resolved if sso_user.email.end_with? '-duplicate' email_addr = sso_user.email.match(/^<([^>]+)>.{20}-duplicate$/)[1] - unless email_addr == self.email - raise DuplicateIndexError, email_addr - end + raise(DuplicateIndexError, email_addr) unless email_addr == email end # update the user's profile to set the data managed by the SSO @@ -264,9 +261,7 @@ class User < ActiveRecord::Base value = sso_user.get_data_from_sso_mapping(field) # we do not merge the email field if its end with the special value '-duplicate' as this means # that the user is currently merging with the account that have the same email than the sso - unless field == 'user.email' and value.end_with? '-duplicate' - self.set_data_from_sso_mapping(field, value) - end + set_data_from_sso_mapping(field, value) unless field == 'user.email' && value.end_with?('-duplicate') end # run the account transfert in an SQL transaction to ensure data integrity @@ -274,34 +269,40 @@ class User < ActiveRecord::Base # remove the temporary account sso_user.destroy # finally, save the new details - self.save! + save! end end def self.mapping # we protect some fields as they are designed to be managed by the system and must not be updated externally - blacklist = %w(id encrypted_password reset_password_token reset_password_sent_at remember_created_at - sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip confirmation_token confirmed_at - confirmation_sent_at unconfirmed_email failed_attempts unlock_token locked_at created_at updated_at stp_customer_id slug - provider auth_token merged_at) + blacklist = %w[id encrypted_password reset_password_token reset_password_sent_at remember_created_at + sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip confirmation_token + confirmed_at confirmation_sent_at unconfirmed_email failed_attempts unlock_token locked_at created_at + updated_at stp_customer_id slug provider auth_token merged_at] User.column_types - .map{|k,v| [k, v.type.to_s]} + .map { |k, v| [k, v.type.to_s] } .delete_if { |col| blacklist.include?(col[0]) } end protected + def confirmation_required? false end private + def assign_default_role - add_role(:member) if self.roles.blank? + add_role(:member) if roles.blank? end def cached_has_role?(role) - roles = Rails.cache.fetch(roles_for: { object_id: self.object_id }, expires_in: 1.day, race_condition_ttl: 2.seconds) { self.roles.map(&:name) } + roles = Rails.cache.fetch( + roles_for: { object_id: object_id }, + expires_in: 1.day, + race_condition_ttl: 2.seconds + ) { roles.map(&:name) } roles.include?(role.to_s) end @@ -314,7 +315,7 @@ class User < ActiveRecord::Base end def create_a_wallet - self.create_wallet + create_wallet end def notify_admin_when_user_is_created @@ -330,19 +331,19 @@ class User < ActiveRecord::Base end def notify_group_changed - if changes[:group_id].first != nil - ex_group = Group.find(changes[:group_id].first) - meta_data = { ex_group_name: ex_group.name } + return if changes[:group_id].first.nil? - User.admins.each do |admin| - notification = Notification.new(meta_data: meta_data) - notification.send_notification(type: :notify_admin_user_group_changed, attached_object: self).to(admin).deliver_later - end + ex_group = Group.find(changes[:group_id].first) + meta_data = { ex_group_name: ex_group.name } - NotificationCenter.call type: :notify_user_user_group_changed, - receiver: self, - attached_object: self + User.admins.each do |admin| + notification = Notification.new(meta_data: meta_data) + notification.send_notification(type: :notify_admin_user_group_changed, attached_object: self).to(admin).deliver_later end + + NotificationCenter.call type: :notify_user_user_group_changed, + receiver: self, + attached_object: self end def notify_admin_invoicing_changed diff --git a/app/views/api/availabilities/public.json.jbuilder b/app/views/api/availabilities/public.json.jbuilder index d1f00d653..151fd7940 100644 --- a/app/views/api/availabilities/public.json.jbuilder +++ b/app/views/api/availabilities/public.json.jbuilder @@ -25,7 +25,7 @@ json.array!(@availabilities) do |availability| if availability.is_reserved json.is_reserved true json.title "#{availability.title}' - #{t('trainings.i_ve_reserved')}" - elsif availability.is_completed + elsif availability.completed? json.is_completed true json.title "#{availability.title} - #{t('trainings.completed')}" end diff --git a/app/views/api/availabilities/trainings.json.jbuilder b/app/views/api/availabilities/trainings.json.jbuilder index ba0724967..cf76193cd 100644 --- a/app/views/api/availabilities/trainings.json.jbuilder +++ b/app/views/api/availabilities/trainings.json.jbuilder @@ -3,7 +3,7 @@ json.array!(@availabilities) do |a| if a.is_reserved json.is_reserved true json.title "#{a.trainings[0].name}' - #{t('trainings.i_ve_reserved')}" - elsif a.is_completed + elsif a.completed? json.is_completed true json.title "#{a.trainings[0].name} - #{t('trainings.completed')}" else diff --git a/app/views/api/machines/show.json.jbuilder b/app/views/api/machines/show.json.jbuilder index f49255956..188e463d6 100644 --- a/app/views/api/machines/show.json.jbuilder +++ b/app/views/api/machines/show.json.jbuilder @@ -6,10 +6,10 @@ json.machine_files_attributes @machine.machine_files do |f| json.attachment_url f.attachment_url end json.trainings @machine.trainings.each, :id, :name, :disabled -json.current_user_is_training current_user.is_training_machine?(@machine) if current_user +json.current_user_is_training current_user.training_machine?(@machine) if current_user json.current_user_training_reservation do json.partial! 'api/reservations/reservation', reservation: current_user.training_reservation_by_machine(@machine) -end if current_user and !current_user.is_training_machine?(@machine) and current_user.training_reservation_by_machine(@machine) +end if current_user and !current_user.training_machine?(@machine) and current_user.training_reservation_by_machine(@machine) json.machine_projects @machine.projects.published.last(10) do |p| json.id p.id diff --git a/doc/elastic_upgrade.md b/doc/elastic_upgrade.md index 1d130befe..13bbe5852 100644 --- a/doc/elastic_upgrade.md +++ b/doc/elastic_upgrade.md @@ -6,8 +6,8 @@ Fab-manager release 2.6.5 has upgraded its dependency to ElasticSearch from vers To keep using fab-manager you need to upgrade your installation with the new version. We've wrote a script to automate the process while keeping your data integrity, but there's some requirements to understand before running it. -- You need to install *curl*, *jq* and *sudo* on your system before running the script. - Usually, `apt update && apt install curl jq sudo`, ran as root, will do the trick but this may change, depending upon your system. +- You need to install *curl*, *jq*, *GNU awk* and *sudo* on your system before running the script. + Usually, `apt update && apt install curl jq sudo gawk`, ran as root, will do the trick but this may change, depending upon your system. - You'll need at least 4GB of RAM for the data migration to complete successfully. The script will try to add 4GB of swap memory if this requirement is detected as missing but this will consume you hard disk space (see below). - 1,17GB of free disk space are also required to perform the data migration. diff --git a/scripts/elastic-upgrade.sh b/scripts/elastic-upgrade.sh index 44933d0b2..fe5f7969f 100755 --- a/scripts/elastic-upgrade.sh +++ b/scripts/elastic-upgrade.sh @@ -36,6 +36,12 @@ config() echo "sudo was not found, exiting..." exit 1 fi + if ! command -v awk || ! [[ $(awk -W version) =~ ^GNU ]] + then + echo "Please install GNU Awk before running this script." + echo "gawk was not found, exiting..." + exit 1 + fi echo "checking memory..." mem=$(free -mt | grep Total | awk '{print $2}') if [ "$mem" -lt 4000 ]