mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-18 07:52:23 +01:00
Merge branch 'dev' into host
This commit is contained in:
commit
cf23fae73c
@ -10,6 +10,9 @@ Metrics/AbcSize:
|
||||
Max: 45
|
||||
Metrics/ClassLength:
|
||||
Max: 200
|
||||
Metrics/BlockLength:
|
||||
Exclude:
|
||||
- 'lib/tasks/**/*.rake'
|
||||
Style/BracesAroundHashParameters:
|
||||
EnforcedStyle: context_dependent
|
||||
Style/RegexpLiteral:
|
||||
|
21
CHANGELOG.md
21
CHANGELOG.md
@ -1,5 +1,10 @@
|
||||
# Changelog Fab Manager
|
||||
|
||||
- Refactored rake tasks to use namespaces and descriptions
|
||||
- Fix a bug: unable to create a new oAuth 2.0 provider
|
||||
- Fix a bug: application in unavailable if a SSO is active
|
||||
- Fixed missing translations in authentication providers form
|
||||
|
||||
## v2.8.3 2019 January 29
|
||||
|
||||
- Added user's manual (fr)
|
||||
@ -54,7 +59,7 @@
|
||||
# v2.7.3 2018 December 03
|
||||
|
||||
- Updated Uglifier gem to support ES6 syntax
|
||||
- Fix rake task fablab:es_build_projects_index for ElasticSearch > 1.7
|
||||
- Fix rake task `fablab:es:build_projects_index` for ElasticSearch > 1.7
|
||||
- Fix Dockerfile: yarn was not setup correctly
|
||||
- Fix: unable to build assets
|
||||
|
||||
@ -96,7 +101,7 @@
|
||||
|
||||
- Ability to parametrize machines order on the booking page
|
||||
- Ability to set a neutral gender for the fablab's title (#108)
|
||||
- Fix a bug: rake task fablab:fix:categories_slugs bash interpretation error
|
||||
- Fix a bug: rake task `fablab:fix:categories_slugs` bash interpretation error
|
||||
- Fix a bug: file inputs filled with long filenames render improperly with an overflow
|
||||
- Fix a bug: title concordance radio buttons render improperly on smaller screens
|
||||
- Improved verifications in ElasticSearch upgrade script
|
||||
@ -290,7 +295,7 @@
|
||||
- Fix a bug: new plans statistics are not shown
|
||||
- [TODO DEPLOY] `rake db:migrate`, then `rake db:seed`
|
||||
- [TODO DEPLOY] add the `FABLAB_WITHOUT_SPACES` environment variable
|
||||
- [TODO DEPLOY] `rake fablab:es_add_spaces`
|
||||
- [TODO DEPLOY] `rake fablab:es:add_spaces`
|
||||
- [TODO DEPLOY] `rake fablab:fix:new_plans_statistics` if you have created plans from v2.4.10
|
||||
|
||||
## v2.4.11 2017 March 15
|
||||
@ -306,7 +311,7 @@
|
||||
- Fix a bug: navigation to about page duplicates admin's links in left menu
|
||||
- Fix a bug: changing the price of a plan lost its past statistics
|
||||
- [TODO DEPLOY] `rake db:migrate`
|
||||
- [TODO DEPLOY] `rake fablab:set_plans_slugs`
|
||||
- [TODO DEPLOY] `rake fablab:fix:set_plans_slugs`
|
||||
|
||||
## v2.4.9 2017 January 4
|
||||
|
||||
@ -321,8 +326,8 @@
|
||||
- Fix a bug: when regenerating statistics, previous values are not fully removed (only 10 firsts), resulting in wrong statistics generation (2)
|
||||
- Fix a bug: when deleting an availability just after its creation, the indexer workers crash and retries for a month
|
||||
- [TODO DEPLOY] remove possible value `application/` in `ALLOWED_MIME_TYPES` list, in environment variable
|
||||
- [TODO DEPLOY] `rails runner StatisticCustomAggregation.destroy_all`, then `rake db:seed`, then `rake fablab:es_build_availabilities_index` (1)
|
||||
- [TODO DEPLOY] `rake fablab:generate_stats[1095]` if you already has regenerated the statistics in the past, then they are very likely corrupted. Run this task to fix (2)
|
||||
- [TODO DEPLOY] `rails runner StatisticCustomAggregation.destroy_all`, then `rake db:seed`, then `rake fablab:es:build_availabilities_index` (1)
|
||||
- [TODO DEPLOY] `rake fablab:es:generate_stats[1095]` if you already has regenerated the statistics in the past, then they are very likely corrupted. Run this task to fix (2)
|
||||
|
||||
## v2.4.8 2016 December 15
|
||||
|
||||
@ -450,8 +455,8 @@
|
||||
- Fix a bug: reordering project's steps trigger the unsaved-warning dialog
|
||||
- Fix a bug: unable to compile assets in Docker with CoffeeScript error
|
||||
- Fix a bug: do not force HTTPS for URLs in production environments
|
||||
- [TODO DEPLOY] `rake fablab:es_build_availabilities_index`
|
||||
- [TODO DEPLOY] `rake fablab:es_add_event_filters`
|
||||
- [TODO DEPLOY] `rake fablab:es:build_availabilities_index`
|
||||
- [TODO DEPLOY] `rake fablab:es:add_event_filters`
|
||||
- [TODO DEPLOY] `rake db:migrate`
|
||||
- [TODO DEPLOY] `bundle install`
|
||||
- [TODO DEPLOY] add `EXCEL_DATE_FORMAT`, `ALLOWED_EXTENSIONS` and `ALLOWED_MIME_TYPES` environment variable in `application.yml`
|
||||
|
@ -164,7 +164,7 @@ This procedure is not easy to follow so if you don't need to write some code for
|
||||
rake db:create
|
||||
rake db:migrate
|
||||
ADMIN_EMAIL='youradminemail' ADMIN_PASSWORD='youradminpassword' rake db:seed
|
||||
rake fablab:es_build_stats
|
||||
rake fablab:es:build_stats
|
||||
# for tests
|
||||
RAILS_ENV=test rake db:create
|
||||
RAILS_ENV=test rake db:migrate
|
||||
@ -255,7 +255,7 @@ environment.
|
||||
rake db:create
|
||||
rake db:migrate
|
||||
ADMIN_EMAIL='youradminemail' ADMIN_PASSWORD='youradminpassword' rake db:seed
|
||||
rake fablab:es_build_stats
|
||||
rake fablab:es:build_stats
|
||||
# for tests
|
||||
RAILS_ENV=test rake db:create
|
||||
RAILS_ENV=test rake db:migrate
|
||||
@ -393,7 +393,7 @@ If the scheduled task wasn't executed for any reason (eg. you are in a dev envir
|
||||
|
||||
```bash
|
||||
# Here for the 50 last days
|
||||
rake fablab:generate_stats[50]
|
||||
rake fablab:es:generate_stats[50]
|
||||
```
|
||||
|
||||
<a name="backup-and-restore-elasticsearch"></a>
|
||||
|
@ -411,10 +411,10 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
}).result['finally'](null).then(function () { growl.info(_t('you_will_receive_in_a_moment_an_email_with_instructions_to_reset_your_password')); });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// otherwise the user just closed the modal
|
||||
<% end %>
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Detect if the current page (tab/window) is active of put as background.
|
||||
|
@ -92,6 +92,7 @@ Application.Directives.directive('disableAnimation', ['$animate', ($animate) =>
|
||||
|
||||
/**
|
||||
* Isolate a form's scope from its parent : no nested validation
|
||||
* @see https://stackoverflow.com/a/37481846/1039377
|
||||
*/
|
||||
Application.Directives.directive('isolateForm', [ () =>
|
||||
({
|
||||
@ -100,30 +101,13 @@ Application.Directives.directive('isolateForm', [ () =>
|
||||
link (scope, elm, attrs, ctrl) {
|
||||
if (!ctrl) { return; }
|
||||
|
||||
// Do a copy of the controller
|
||||
const ctrlCopy = {};
|
||||
angular.copy(ctrl, ctrlCopy);
|
||||
|
||||
// Get the form's parent
|
||||
const parent = elm.parent().controller('form');
|
||||
// Remove parent link to the controller
|
||||
parent.$removeControl(ctrl);
|
||||
|
||||
// Replace form controller with a "isolated form"
|
||||
const isolatedFormCtrl = {
|
||||
$setValidity (validationToken, isValid, control) {
|
||||
ctrlCopy.$setValidity(validationToken, isValid, control);
|
||||
return parent.$setValidity(validationToken, true, ctrl);
|
||||
},
|
||||
|
||||
$setDirty () {
|
||||
elm.removeClass('ng-pristine').addClass('ng-dirty');
|
||||
ctrl.$dirty = true;
|
||||
return ctrl.$pristine = false;
|
||||
const parentForm = ctrl.$$parentForm; // Note this uses private API
|
||||
if (!parentForm) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
return angular.extend(ctrl, isolatedFormCtrl);
|
||||
// Remove this form from parent controller
|
||||
parentForm.$removeControl(ctrl);
|
||||
}
|
||||
|
||||
})
|
||||
|
@ -19,7 +19,7 @@ class AuthProvider < ActiveRecord::Base
|
||||
|
||||
before_create :set_initial_state
|
||||
|
||||
def build_providable(params)
|
||||
def build_providable(params, _assignment_options)
|
||||
raise "Unknown providable_type: #{providable_type}" unless PROVIDABLE_TYPES.include?(providable_type)
|
||||
|
||||
self.providable = providable_type.constantize.new(params)
|
||||
|
@ -125,7 +125,7 @@ class Invoice < ActiveRecord::Base
|
||||
reference
|
||||
end
|
||||
|
||||
# for debug & used by rake task "fablab:regenerate_invoices"
|
||||
# for debug & used by rake task "fablab:maintenance:regenerate_invoices"
|
||||
def regenerate_invoice_pdf
|
||||
pdf = ::PDF::Invoice.new(self, nil).render
|
||||
File.binwrite(file, pdf)
|
||||
|
@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# @deprecated
|
||||
# <b>DEPRECATED:</b> Feature removed in v2.8.2
|
||||
json.title notification.notification_type
|
||||
json.description _t('.invoices_generation_was_STATUS_for_user_NAME_html',
|
||||
STATUS: notification.attached_object.invoicing_disabled.to_s,
|
||||
NAME: notification.attached_object.profile.full_name) # messageFormat
|
||||
json.url notification_url(notification, format: :json)
|
@ -1,3 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# @deprecated
|
||||
# <b>DEPRECATED:</b> Feature removed in v1 (87dd9ba0 2015-06-04)
|
||||
json.title notification.notification_type
|
||||
json.description t('.you_have_changed_your_subscription_to_PLAN_html',
|
||||
PLAN: notification.attached_object.plan.name)
|
||||
|
@ -526,6 +526,8 @@ en:
|
||||
|
||||
authentication_new:
|
||||
# add a new authentication provider (SSO)
|
||||
local_database: "Local Database"
|
||||
o_auth2: "OAuth 2.0"
|
||||
add_a_new_authentication_provider: "Add a new authentication provider"
|
||||
a_local_database_provider_already_exists_unable_to_create_another: "A \"Local Database\" provider already exists. Unable to create another."
|
||||
local_provider_successfully_saved: "Local provider successfully saved."
|
||||
|
@ -526,6 +526,8 @@ es:
|
||||
|
||||
authentication_new:
|
||||
# add a new authentication provider (SSO)
|
||||
local_database: "Base de datos local"
|
||||
o_auth2: "OAuth 2.0"
|
||||
add_a_new_authentication_provider: "Agregar un nuevo proveedor de autenticación"
|
||||
a_local_database_provider_already_exists_unable_to_create_another: "A proveedor de \"Base de datos local\" ya existe. No se puede crear otro."
|
||||
local_provider_successfully_saved: "Proveedor local guardado correctamente."
|
||||
|
@ -526,6 +526,8 @@ fr:
|
||||
|
||||
authentication_new:
|
||||
# ajouter un nouveau fournisseur d'authentification (SSO)
|
||||
local_database: "Base de données locale"
|
||||
o_auth2: "OAuth 2.0"
|
||||
add_a_new_authentication_provider: "Ajouter un fournisseur d'authentification"
|
||||
a_local_database_provider_already_exists_unable_to_create_another: "Un fournisseur de type \"Base de données locale\" existe déjà. Impossible d'en créer un second."
|
||||
local_provider_successfully_saved: "Le fournisseur local a bien été enregistré."
|
||||
|
@ -526,6 +526,8 @@ pt:
|
||||
|
||||
authentication_new:
|
||||
# add a new authentication provider (SSO)
|
||||
local_database: "Local Database"
|
||||
o_auth2: "OAuth 2.0"
|
||||
add_a_new_authentication_provider: "Adicionar novo provedor de autenticação"
|
||||
a_local_database_provider_already_exists_unable_to_create_another: "Um provedor \"Local Database\" já existe. Não foi possível criar outro."
|
||||
local_provider_successfully_saved: "Provedor local salvo com sucesso."
|
||||
|
@ -145,7 +145,7 @@ Copy [elasticsearch.yml](../docker/elasticsearch.yml) and [log4j2.properties](..
|
||||
|
||||
Finally reindex your data:
|
||||
```bash
|
||||
rake fablab:es_build_stats
|
||||
rake fablab:generate_stats[3000]
|
||||
rake fablab:es_build_projects_index
|
||||
rake fablab:es:build_stats
|
||||
rake fablab:es:generate_stats[3000]
|
||||
rake fablab:es:build_projects_index
|
||||
```
|
||||
|
@ -53,7 +53,7 @@ For this guide, we will use [GitHub](https://developer.github.com/v3/oauth/) as
|
||||
|
||||
```bash
|
||||
# replace GitHub with the name of the provider you just created
|
||||
rake fablab:switch_auth_provider[GitHub]
|
||||
rake fablab:auth:switch_provider[GitHub]
|
||||
```
|
||||
|
||||
- As the command just prompted you, you have to re-compile the assets
|
||||
@ -62,5 +62,5 @@ rake fablab:switch_auth_provider[GitHub]
|
||||
- Then restart the web-server or the container.
|
||||
- Finally, to notify all existing users about the change (and send them their migration code/link), run:
|
||||
```bash
|
||||
rake fablab:notify_auth_changed
|
||||
rake fablab:auth:notify_changed
|
||||
```
|
||||
|
@ -236,7 +236,7 @@ docker-compose run --rm -e ADMIN_EMAIL=xxx -e ADMIN_PASSWORD=xxx fabmanager bund
|
||||
|
||||
### prepare Elasticsearch (search engine)
|
||||
|
||||
`docker-compose run --rm fabmanager bundle exec rake fablab:es_build_stats`
|
||||
`docker-compose run --rm fabmanager bundle exec rake fablab:es:build_stats`
|
||||
|
||||
### start all services
|
||||
|
||||
|
@ -1,328 +0,0 @@
|
||||
namespace :fablab do
|
||||
# desc "Get all stripe plans and create in fablab app"
|
||||
# task stripe_plan: :environment do
|
||||
# Stripe::Plan.all.data.each do |plan|
|
||||
# unless Plan.find_by(stp_plan_id: plan.id)
|
||||
# group = Group.friendly.find(plan.id.split('-').first)
|
||||
# if group
|
||||
# Plan.create(stp_plan_id: plan.id, name: plan.name, amount: plan.amount, interval: plan.interval, group_id: group.id, skip_create_stripe_plan: true)
|
||||
# else
|
||||
# puts plan.name + " n'a pas été créé. [error]"
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# if Plan.column_names.include? "training_credit_nb"
|
||||
# Plan.all.each do |p|
|
||||
# p.update_columns(training_credit_nb: (p.interval == 'month' ? 1 : 5))
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
desc 'Regenerate the invoices'
|
||||
task :regenerate_invoices, [:year, :month] => :environment do |task, args|
|
||||
year = args.year || Time.now.year
|
||||
month = args.month || Time.now.month
|
||||
start_date = Time.new(year.to_i, month.to_i, 1)
|
||||
end_date = start_date.next_month
|
||||
puts "-> Start regenerate the invoices between #{I18n.l start_date, format: :long} in #{I18n.l end_date-1.minute, format: :long}"
|
||||
invoices = Invoice.only_invoice.where('created_at >= :start_date AND created_at < :end_date', {start_date: start_date, end_date: end_date}).order(created_at: :asc)
|
||||
invoices.each(&:regenerate_invoice_pdf)
|
||||
puts '-> Done'
|
||||
end
|
||||
|
||||
desc 'Cancel stripe subscriptions'
|
||||
task cancel_subscriptions: :environment do
|
||||
Subscription.where('expiration_date >= ?', Time.now.at_beginning_of_day).each do |s|
|
||||
puts "-> Start cancel subscription of #{s.user.email}"
|
||||
s.cancel
|
||||
puts '-> Done'
|
||||
end
|
||||
end
|
||||
|
||||
desc '(re)Build ElasticSearch fablab base for stats'
|
||||
task es_build_stats: :environment do
|
||||
|
||||
puts 'DELETE stats'
|
||||
`curl -XDELETE http://#{ENV["ELASTICSEARCH_HOST"]}:9200/stats`
|
||||
|
||||
puts 'PUT index stats'
|
||||
`curl -XPUT http://#{ENV["ELASTICSEARCH_HOST"]}:9200/stats -d'
|
||||
{
|
||||
"settings" : {
|
||||
"index" : {
|
||||
"number_of_replicas" : 0
|
||||
}
|
||||
}
|
||||
}
|
||||
'`
|
||||
|
||||
|
||||
%w[account event machine project subscription training user space].each do |stat|
|
||||
puts "PUT Mapping stats/#{stat}"
|
||||
`curl -XPUT http://#{ENV["ELASTICSEARCH_HOST"]}:9200/stats/#{stat}/_mapping -d '
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"subType": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"date": {
|
||||
"type": "date"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
}
|
||||
}
|
||||
}';`
|
||||
end
|
||||
es_add_event_filters
|
||||
end
|
||||
|
||||
desc 'add event filters to statistics'
|
||||
task es_add_event_filters: :environment do
|
||||
es_add_event_filters
|
||||
end
|
||||
|
||||
def es_add_event_filters
|
||||
`curl -XPUT http://#{ENV["ELASTICSEARCH_HOST"]}:9200/stats/event/_mapping -d '
|
||||
{
|
||||
"properties": {
|
||||
"ageRange": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"eventTheme": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
}
|
||||
}
|
||||
}';`
|
||||
end
|
||||
|
||||
|
||||
desc 'add spaces reservations to statistics'
|
||||
task es_add_spaces: :environment do
|
||||
`curl -XPUT http://#{ENV["ELASTICSEARCH_HOST"]}:9200/stats/space/_mapping -d '
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"subType": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"date": {
|
||||
"type": "date"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
}
|
||||
}
|
||||
}';`
|
||||
end
|
||||
|
||||
desc 'sync all/one project in ElasticSearch index'
|
||||
task :es_build_projects_index, [:id] => :environment do |task, args|
|
||||
client = Project.__elasticsearch__.client
|
||||
# create index if not exists
|
||||
unless client.indices.exists? index: Project.index_name
|
||||
Project.__elasticsearch__.create_index! force: true
|
||||
end
|
||||
|
||||
# index requested documents
|
||||
if args.id
|
||||
ProjectIndexerWorker.perform_async(:index, id)
|
||||
else
|
||||
Project.pluck(:id).each do |project_id|
|
||||
ProjectIndexerWorker.perform_async(:index, project_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'sync all/one availabilities in ElasticSearch index'
|
||||
task :es_build_availabilities_index, [:id] => :environment do |task, args|
|
||||
client = Availability.__elasticsearch__.client
|
||||
# create index if not exists
|
||||
unless client.indices.exists? index: Availability.index_name
|
||||
Availability.__elasticsearch__.create_index! force: true
|
||||
end
|
||||
# delete doctype if exists
|
||||
if client.indices.exists_type? index: Availability.index_name, type: Availability.document_type
|
||||
client.indices.delete_mapping index: Availability.index_name, type: Availability.document_type
|
||||
end
|
||||
# create doctype
|
||||
client.indices.put_mapping index: Availability.index_name, type: Availability.document_type, body: Availability.mappings.to_hash
|
||||
|
||||
# verify doctype creation was successful
|
||||
if client.indices.exists_type? index: Availability.index_name, type: Availability.document_type
|
||||
puts "[ElasticSearch] #{Availability.index_name}/#{Availability.document_type} successfully created with its mapping."
|
||||
|
||||
# index requested documents
|
||||
if args.id
|
||||
AvailabilityIndexerWorker.perform_async(:index, id)
|
||||
else
|
||||
Availability.pluck(:id).each do |availability_id|
|
||||
AvailabilityIndexerWorker.perform_async(:index, availability_id)
|
||||
end
|
||||
end
|
||||
else
|
||||
puts "[ElasticSearch] An error occurred while creating #{Availability.index_name}/#{Availability.document_type}. Please check your ElasticSearch configuration."
|
||||
puts "\nCancelling..."
|
||||
end
|
||||
end
|
||||
|
||||
desc 'recreate every versions of images'
|
||||
task build_images_versions: :environment do
|
||||
Project.find_each do |project|
|
||||
project.project_image.attachment.recreate_versions! if project.project_image.present? and project.project_image.attachment.present?
|
||||
end
|
||||
ProjectStepImage.find_each do |project_step_image|
|
||||
project_step_image.attachment.recreate_versions! if project_step_image.present? and project_step_image.attachment.present?
|
||||
end
|
||||
Machine.find_each do |machine|
|
||||
machine.machine_image.attachment.recreate_versions! if machine.machine_image.present?
|
||||
end
|
||||
Event.find_each do |event|
|
||||
event.event_image.attachment.recreate_versions! if event.event_image.present?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
desc 'switch the active authentication provider'
|
||||
task :switch_auth_provider, [:provider] => :environment do |task, args|
|
||||
unless args.provider
|
||||
fail 'FATAL ERROR: You must pass a provider name to activate'
|
||||
end
|
||||
|
||||
unless AuthProvider.find_by(name: args.provider) != nil
|
||||
providers = AuthProvider.all.inject('') do |str, item|
|
||||
str += item[:name]+', '
|
||||
end
|
||||
fail "FATAL ERROR: the provider '#{args.provider}' does not exists. Available providers are: #{providers[0..-3]}"
|
||||
end
|
||||
|
||||
if AuthProvider.active.name == args.provider
|
||||
fail "FATAL ERROR: the provider '#{args.provider}' is already enabled"
|
||||
end
|
||||
|
||||
# disable previous provider
|
||||
prev_prev = AuthProvider.find_by(status: 'previous')
|
||||
unless prev_prev.nil?
|
||||
prev_prev.update_attribute(:status, 'pending')
|
||||
end
|
||||
AuthProvider.active.update_attribute(:status, 'previous')
|
||||
|
||||
# enable given provider
|
||||
AuthProvider.find_by(name: args.provider).update_attribute(:status, 'active')
|
||||
|
||||
# migrate the current users.
|
||||
if AuthProvider.active.providable_type != DatabaseProvider.name
|
||||
User.all.each do |user|
|
||||
# Concerns any providers except local database
|
||||
user.generate_auth_migration_token
|
||||
end
|
||||
else
|
||||
User.all.each do |user|
|
||||
# Concerns local database provider
|
||||
user.update_attribute(:auth_token, nil)
|
||||
end
|
||||
end
|
||||
|
||||
# ask the user to restart the application
|
||||
puts "\nActivation successful"
|
||||
|
||||
puts "\n/!\\ WARNING: Please consider the following, otherwise the authentication will be bogus:"
|
||||
puts "\t1) CLEAN the cache with `rake tmp:clear`"
|
||||
puts "\t2) REBUILD the assets with `rake assets:precompile`"
|
||||
puts "\t3) RESTART the application"
|
||||
puts "\t4) NOTIFY the current users with `rake fablab:notify_auth_changed`\n\n"
|
||||
|
||||
end
|
||||
|
||||
desc 'notify users that the auth provider has changed'
|
||||
task notify_auth_changed: :environment do
|
||||
|
||||
I18n.locale = I18n.default_locale
|
||||
|
||||
# notify every users if the provider is not local database provider
|
||||
if AuthProvider.active.providable_type != DatabaseProvider.name
|
||||
User.all.each do |user|
|
||||
NotificationCenter.call type: 'notify_user_auth_migration',
|
||||
receiver: user,
|
||||
attached_object: user
|
||||
end
|
||||
end
|
||||
|
||||
puts "\nUsers successfully notified\n\n"
|
||||
end
|
||||
|
||||
desc 'generate fixtures from db'
|
||||
task generate_fixtures: :environment do
|
||||
Rails.application.eager_load!
|
||||
ActiveRecord::Base.descendants.reject { |c| c == ActiveRecord::SchemaMigration or c == PartnerPlan }.each do |ar_base|
|
||||
p "========== #{ar_base} =============="
|
||||
ar_base.dump_fixtures
|
||||
end
|
||||
end
|
||||
|
||||
desc 'clean stripe secrets from VCR cassettes'
|
||||
task clean_cassettes_secrets: :environment do
|
||||
Dir['test/vcr_cassettes/*.yml'].each do |cassette_file|
|
||||
cassette = File.read(cassette_file)
|
||||
cassette.gsub!(Rails.application.secrets.stripe_api_key, 'sk_test_testfaketestfaketestfake')
|
||||
cassette.gsub!(Rails.application.secrets.stripe_publishable_key, 'pk_test_faketestfaketestfaketest')
|
||||
puts cassette
|
||||
File.write(cassette_file, cassette)
|
||||
end
|
||||
end
|
||||
|
||||
desc '(re)generate statistics in elasticsearch for the past period'
|
||||
task :generate_stats, [:period] => :environment do |task, args|
|
||||
unless args.period
|
||||
fail 'FATAL ERROR: You must pass a number of days (=> past period) to generate statistics on'
|
||||
end
|
||||
|
||||
days = args.period.to_i
|
||||
days.times.each do |i|
|
||||
StatisticService.new.generate_statistic({start_date: i.day.ago.beginning_of_day,end_date: i.day.ago.end_of_day})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
desc 'set slugs to plans'
|
||||
task set_plans_slugs: :environment do
|
||||
# this will maintain compatibility with existing statistics
|
||||
Plan.all.each do |p|
|
||||
p.slug = p.stp_plan_id
|
||||
p.save
|
||||
end
|
||||
end
|
||||
|
||||
desc 'get incoherent invoice'
|
||||
task :get_incoherent_invoice, [:start_date] => :environment do |task, args|
|
||||
date = Date.parse('2017-05-01')
|
||||
if args.start_date
|
||||
begin
|
||||
date = Date.parse(args.start_date)
|
||||
rescue => e
|
||||
fail e
|
||||
end
|
||||
end
|
||||
Invoice.where('created_at > ? AND stp_invoice_id IS NOT NULL', date).each do |invoice|
|
||||
stp_invoice = Stripe::Invoice.retrieve(invoice.stp_invoice_id)
|
||||
if invoice.amount_paid != stp_invoice.total
|
||||
puts "Id: #{invoice.id}, reference: #{invoice.reference}, stripe id: #{stp_invoice.id}, invoice total: #{invoice.amount_paid / 100.0}, stripe invoice total: #{stp_invoice.total / 100.0}, date: #{invoice.created_at}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
66
lib/tasks/fablab/auth.rake
Normal file
66
lib/tasks/fablab/auth.rake
Normal file
@ -0,0 +1,66 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# SSO and authentication relative tasks
|
||||
namespace :fablab do
|
||||
namespace :auth do
|
||||
|
||||
desc 'switch the active authentication provider'
|
||||
task :switch_provider, [:provider] => :environment do |_task, args|
|
||||
raise 'FATAL ERROR: You must pass a provider name to activate' unless args.provider
|
||||
|
||||
if AuthProvider.find_by(name: args.provider).nil?
|
||||
providers = AuthProvider.all.inject('') { |str, item| str + item[:name] + ', ' }
|
||||
raise "FATAL ERROR: the provider '#{args.provider}' does not exists. Available providers are: #{providers[0..-3]}"
|
||||
end
|
||||
|
||||
raise "FATAL ERROR: the provider '#{args.provider}' is already enabled" if AuthProvider.active.name == args.provider
|
||||
|
||||
# disable previous provider
|
||||
prev_prev = AuthProvider.find_by(status: 'previous')
|
||||
prev_prev&.update_attribute(:status, 'pending')
|
||||
|
||||
AuthProvider.active.update_attribute(:status, 'previous')
|
||||
|
||||
# enable given provider
|
||||
AuthProvider.find_by(name: args.provider).update_attribute(:status, 'active')
|
||||
|
||||
# migrate the current users.
|
||||
if AuthProvider.active.providable_type != DatabaseProvider.name
|
||||
# Concerns any providers except local database
|
||||
User.all.each(&:generate_auth_migration_token)
|
||||
else
|
||||
User.all.each do |user|
|
||||
# Concerns local database provider
|
||||
user.update_attribute(:auth_token, nil)
|
||||
end
|
||||
end
|
||||
|
||||
# ask the user to restart the application
|
||||
puts "\nActivation successful"
|
||||
|
||||
puts "\n/!\\ WARNING: Please consider the following, otherwise the authentication will be bogus:"
|
||||
puts "\t1) CLEAN the cache with `rake tmp:clear`"
|
||||
puts "\t2) REBUILD the assets with `rake assets:precompile`"
|
||||
puts "\t3) RESTART the application"
|
||||
puts "\t4) NOTIFY the current users with `rake fablab:auth:notify_changed`\n\n"
|
||||
|
||||
end
|
||||
|
||||
desc 'notify users that the auth provider has changed'
|
||||
task notify_changed: :environment do
|
||||
|
||||
I18n.locale = I18n.default_locale
|
||||
|
||||
# notify every users if the provider is not local database provider
|
||||
if AuthProvider.active.providable_type != DatabaseProvider.name
|
||||
User.all.each do |user|
|
||||
NotificationCenter.call type: 'notify_user_auth_migration',
|
||||
receiver: user,
|
||||
attached_object: user
|
||||
end
|
||||
end
|
||||
|
||||
puts "\nUsers successfully notified\n\n"
|
||||
end
|
||||
end
|
||||
end
|
165
lib/tasks/fablab/es.rake
Normal file
165
lib/tasks/fablab/es.rake
Normal file
@ -0,0 +1,165 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# ElasticSearch relative tasks
|
||||
namespace :fablab do
|
||||
namespace :es do
|
||||
desc '(re)Build ElasticSearch fablab base for stats'
|
||||
task build_stats: :environment do
|
||||
delete_stats_index
|
||||
create_stats_index
|
||||
create_stats_mappings
|
||||
add_event_filters
|
||||
end
|
||||
|
||||
def delete_stats_index
|
||||
puts 'DELETE stats'
|
||||
`curl -XDELETE http://#{ENV['ELASTICSEARCH_HOST']}:9200/stats`
|
||||
end
|
||||
|
||||
def create_stats_index
|
||||
puts 'PUT index stats'
|
||||
`curl -XPUT http://#{ENV['ELASTICSEARCH_HOST']}:9200/stats -d'
|
||||
{
|
||||
"settings" : {
|
||||
"index" : {
|
||||
"number_of_replicas" : 0
|
||||
}
|
||||
}
|
||||
}
|
||||
'`
|
||||
end
|
||||
|
||||
def create_stats_mappings
|
||||
%w[account event machine project subscription training user space].each do |stat|
|
||||
puts "PUT Mapping stats/#{stat}"
|
||||
`curl -XPUT http://#{ENV['ELASTICSEARCH_HOST']}:9200/stats/#{stat}/_mapping -d '
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"subType": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"date": {
|
||||
"type": "date"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
}
|
||||
}
|
||||
}';`
|
||||
end
|
||||
end
|
||||
|
||||
desc 'add event filters to statistics'
|
||||
task add_event_filters: :environment do
|
||||
add_event_filters
|
||||
end
|
||||
|
||||
def add_event_filters
|
||||
`curl -XPUT http://#{ENV['ELASTICSEARCH_HOST']}:9200/stats/event/_mapping -d '
|
||||
{
|
||||
"properties": {
|
||||
"ageRange": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"eventTheme": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
}
|
||||
}
|
||||
}';`
|
||||
end
|
||||
|
||||
|
||||
desc 'add spaces reservations to statistics'
|
||||
task add_spaces: :environment do
|
||||
`curl -XPUT http://#{ENV['ELASTICSEARCH_HOST']}:9200/stats/space/_mapping -d '
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"subType": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"date": {
|
||||
"type": "date"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
}
|
||||
}
|
||||
}';`
|
||||
end
|
||||
|
||||
desc 'sync all/one project in ElasticSearch index'
|
||||
task :build_projects_index, [:id] => :environment do |_task, args|
|
||||
client = Project.__elasticsearch__.client
|
||||
# create index if not exists
|
||||
Project.__elasticsearch__.create_index! force: true unless client.indices.exists? index: Project.index_name
|
||||
|
||||
# index requested documents
|
||||
if args.id
|
||||
ProjectIndexerWorker.perform_async(:index, id)
|
||||
else
|
||||
Project.pluck(:id).each do |project_id|
|
||||
ProjectIndexerWorker.perform_async(:index, project_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'sync all/one availabilities in ElasticSearch index'
|
||||
task :build_availabilities_index, [:id] => :environment do |_task, args|
|
||||
client = Availability.__elasticsearch__.client
|
||||
# create index if not exists
|
||||
Availability.__elasticsearch__.create_index! force: true unless client.indices.exists? index: Availability.index_name
|
||||
# delete doctype if exists
|
||||
if client.indices.exists_type? index: Availability.index_name, type: Availability.document_type
|
||||
client.indices.delete_mapping index: Availability.index_name, type: Availability.document_type
|
||||
end
|
||||
# create doctype
|
||||
client.indices.put_mapping index: Availability.index_name,
|
||||
type: Availability.document_type,
|
||||
body: Availability.mappings.to_hash
|
||||
|
||||
# verify doctype creation was successful
|
||||
if client.indices.exists_type? index: Availability.index_name, type: Availability.document_type
|
||||
puts "[ElasticSearch] #{Availability.index_name}/#{Availability.document_type} successfully created with its mapping."
|
||||
|
||||
# index requested documents
|
||||
if args.id
|
||||
AvailabilityIndexerWorker.perform_async(:index, id)
|
||||
else
|
||||
Availability.pluck(:id).each do |availability_id|
|
||||
AvailabilityIndexerWorker.perform_async(:index, availability_id)
|
||||
end
|
||||
end
|
||||
else
|
||||
puts "[ElasticSearch] An error occurred while creating #{Availability.index_name}/#{Availability.document_type}. " \
|
||||
'Please check your ElasticSearch configuration.'
|
||||
puts "\nCancelling..."
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
desc '(re)generate statistics in ElasticSearch for the past period'
|
||||
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
|
||||
|
||||
days = args.period.to_i
|
||||
days.times.each do |i|
|
||||
StatisticService.new.generate_statistic(start_date: i.day.ago.beginning_of_day, end_date: i.day.ago.end_of_day)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -1,5 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Correctives for bugs or upgrades migrations tasks
|
||||
namespace :fablab do
|
||||
namespace :fix do
|
||||
desc '[release 2.3.0] update reservations referencing reservables not present in database'
|
||||
task reservations_not_existing_reservable: :environment do
|
||||
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
||||
ActiveRecord::Base.connection.execute(
|
||||
@ -9,23 +13,26 @@ namespace :fablab do
|
||||
)
|
||||
end
|
||||
|
||||
desc '[release 2.4.0] put every non-categorized events into a new category called "No Category", to ease re-categorization'
|
||||
task assign_category_to_uncategorized_events: :environment do
|
||||
c = Category.find_or_create_by!({name: 'No category'})
|
||||
c = Category.find_or_create_by!(name: 'No category')
|
||||
Event.where(category: nil).each do |e|
|
||||
e.category = c
|
||||
e.save!
|
||||
end
|
||||
end
|
||||
|
||||
desc '[release 2.4.11] fix is_rolling for edited plans'
|
||||
task rolling_plans: :environment do
|
||||
Plan.where(is_rolling: nil).each do |p|
|
||||
if p.is_rolling.nil? and p.is_rolling != false
|
||||
if p.is_rolling.nil? && p.is_rolling != false
|
||||
p.is_rolling = true
|
||||
p.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc '[release 2.5.0] create missing plans in statistics'
|
||||
task new_plans_statistics: :environment do
|
||||
StatisticSubType.where(key: nil).each do |sst|
|
||||
p = Plan.find_by(name: sst.label)
|
||||
@ -36,6 +43,7 @@ namespace :fablab do
|
||||
end
|
||||
end
|
||||
|
||||
desc '[release 2.5.5] create missing space prices'
|
||||
task new_group_space_prices: :environment do
|
||||
Space.all.each do |space|
|
||||
Group.all.each do |group|
|
||||
@ -48,6 +56,7 @@ namespace :fablab do
|
||||
end
|
||||
end
|
||||
|
||||
desc '[release 2.5.11] put all admins in a special group'
|
||||
task migrate_admins_group: :environment do
|
||||
admins = Group.find_by(slug: 'admins')
|
||||
User.all.each do |user|
|
||||
@ -58,38 +67,39 @@ namespace :fablab do
|
||||
end
|
||||
end
|
||||
|
||||
desc '[release 2.5.14] fix times of recursive events that crosses DST periods'
|
||||
task recursive_events_over_DST: :environment do
|
||||
include ApplicationHelper
|
||||
failed_ids = []
|
||||
groups = Event.group(:recurrence_id).count
|
||||
groups.keys.each do |recurrent_event_id|
|
||||
if recurrent_event_id
|
||||
next unless recurrent_event_id
|
||||
|
||||
begin
|
||||
initial_event = Event.find(recurrent_event_id)
|
||||
Event.where(recurrence_id: recurrent_event_id).where.not(id: recurrent_event_id).each do |event|
|
||||
availability = event.availability
|
||||
if initial_event.availability.start_at.hour != availability.start_at.hour
|
||||
next if initial_event.availability.start_at.hour == availability.start_at.hour
|
||||
|
||||
availability.start_at = dst_correction(initial_event.availability.start_at, availability.start_at)
|
||||
availability.end_at = dst_correction(initial_event.availability.end_at, availability.end_at)
|
||||
availability.save!
|
||||
end
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
failed_ids.push recurrent_event_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if failed_ids.size > 0
|
||||
puts "WARNING: The events with IDs #{failed_ids} were not found.\n These were initial events of a recurrence.\n\n You may have to correct the following events manually (IDs): "
|
||||
puts "#{Event.where(recurrence_id: failed_ids).map(&:id)}"
|
||||
if failed_ids.size.positive?
|
||||
puts "WARNING: The events with IDs #{failed_ids} were not found.\n These were initial events of a recurrence.\n\n" \
|
||||
"You may have to correct the following events manually (IDs): #{Event.where(recurrence_id: failed_ids).map(&:id)}"
|
||||
end
|
||||
end
|
||||
|
||||
desc 'reset slug in events categories'
|
||||
desc '[release 2.6.6] reset slug in events categories'
|
||||
task categories_slugs: :environment do
|
||||
Category.all.each do |cat|
|
||||
`curl -XPOST http://#{ENV["ELASTICSEARCH_HOST"]}:9200/stats/event/_update_by_query?conflicts=proceed\\&refresh\\&wait_for_completion -d '
|
||||
`curl -XPOST http://#{ENV['ELASTICSEARCH_HOST']}:9200/stats/event/_update_by_query?conflicts=proceed\\&refresh\\&wait_for_completion -d '
|
||||
{
|
||||
"script": {
|
||||
"source": "ctx._source.subType = params.slug",
|
||||
@ -106,5 +116,14 @@ namespace :fablab do
|
||||
}';`
|
||||
end
|
||||
end
|
||||
|
||||
desc '[release 2.4.10] set slugs to plans'
|
||||
task set_plans_slugs: :environment do
|
||||
# this will maintain compatibility with existing statistics
|
||||
Plan.all.each do |p|
|
||||
p.slug = p.stp_plan_id
|
||||
p.save
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
49
lib/tasks/fablab/maintenance.rake
Normal file
49
lib/tasks/fablab/maintenance.rake
Normal file
@ -0,0 +1,49 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Maintenance tasks
|
||||
namespace :fablab do
|
||||
namespace :maintenance do
|
||||
desc 'Regenerate the invoices PDF'
|
||||
task :regenerate_invoices, %i[year month] => :environment do |_task, args|
|
||||
year = args.year || Time.now.year
|
||||
month = args.month || Time.now.month
|
||||
start_date = Time.new(year.to_i, month.to_i, 1)
|
||||
end_date = start_date.next_month
|
||||
puts "-> Start regenerate the invoices PDF between #{I18n.l start_date, format: :long} in " \
|
||||
" #{I18n.l end_date - 1.minute, format: :long}"
|
||||
invoices = Invoice.only_invoice
|
||||
.where('created_at >= :start_date AND created_at < :end_date', start_date: start_date, end_date: end_date)
|
||||
.order(created_at: :asc)
|
||||
invoices.each(&:regenerate_invoice_pdf)
|
||||
puts '-> Done'
|
||||
end
|
||||
|
||||
desc 'recreate every versions of images'
|
||||
task build_images_versions: :environment do
|
||||
Project.find_each do |project|
|
||||
if project.project_image.present? && project.project_image.attachment.present?
|
||||
project.project_image.attachment.recreate_versions!
|
||||
end
|
||||
end
|
||||
ProjectStepImage.find_each do |project_step_image|
|
||||
project_step_image.attachment.recreate_versions! if project_step_image.present? && project_step_image.attachment.present?
|
||||
end
|
||||
Machine.find_each do |machine|
|
||||
machine.machine_image.attachment.recreate_versions! if machine.machine_image.present?
|
||||
end
|
||||
Event.find_each do |event|
|
||||
event.event_image.attachment.recreate_versions! if event.event_image.present?
|
||||
end
|
||||
end
|
||||
|
||||
desc 'generate fixtures from db'
|
||||
task generate_fixtures: :environment do
|
||||
Rails.application.eager_load!
|
||||
ActiveRecord::Base.descendants.reject { |c| [ActiveRecord::SchemaMigration, PartnerPlan].include? c }.each do |ar_base|
|
||||
p "========== #{ar_base} =============="
|
||||
ar_base.dump_fixtures
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -1,3 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# OpenLab Projects tasks
|
||||
namespace :fablab do
|
||||
namespace :openlab do
|
||||
desc 'bulk and export projects to openlab'
|
||||
|
48
lib/tasks/fablab/stripe.rake
Normal file
48
lib/tasks/fablab/stripe.rake
Normal file
@ -0,0 +1,48 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Stripe relative tasks
|
||||
namespace :fablab do
|
||||
namespace :stripe do
|
||||
|
||||
desc 'Cancel stripe subscriptions'
|
||||
task cancel_subscriptions: :environment do
|
||||
Subscription.where('expiration_date >= ?', Time.now.at_beginning_of_day).each do |s|
|
||||
puts "-> Start cancel subscription of #{s.user.email}"
|
||||
s.cancel
|
||||
puts '-> Done'
|
||||
end
|
||||
end
|
||||
|
||||
desc 'find any invoices with incoherent total between stripe and DB'
|
||||
task :find_incoherent_invoices, [:start_date] => :environment do |_task, args|
|
||||
date = Date.parse('2017-05-01')
|
||||
if args.start_date
|
||||
begin
|
||||
date = Date.parse(args.start_date)
|
||||
rescue ArgumentError => e
|
||||
raise e
|
||||
end
|
||||
end
|
||||
Invoice.where('created_at > ? AND stp_invoice_id IS NOT NULL', date).each do |invoice|
|
||||
stp_invoice = Stripe::Invoice.retrieve(invoice.stp_invoice_id)
|
||||
next if invoice.amount_paid == stp_invoice.total
|
||||
|
||||
puts "Id: #{invoice.id}, reference: #{invoice.reference}, stripe id: #{stp_invoice.id}, " \
|
||||
"invoice total: #{invoice.amount_paid / 100.0}, stripe invoice total: #{stp_invoice.total / 100.0}, " \
|
||||
"date: #{invoice.created_at}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
desc 'clean stripe secrets from VCR cassettes'
|
||||
task clean_cassettes_secrets: :environment do
|
||||
Dir['test/vcr_cassettes/*.yml'].each do |cassette_file|
|
||||
cassette = File.read(cassette_file)
|
||||
cassette = cassette.gsub(Rails.application.secrets.stripe_api_key, 'sk_test_testfaketestfaketestfake')
|
||||
cassette = cassette.gsub(Rails.application.secrets.stripe_publishable_key, 'pk_test_faketestfaketestfaketest')
|
||||
puts cassette
|
||||
File.write(cassette_file, cassette)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user