Merge pull request #21146 from opf/code-maintenance/67826-major-only-aggregate-migrations-up-until-last-major-release

Aggregate Migrations prior to 16.0
This commit is contained in:
Jens Ulferts
2025-11-26 15:14:41 +01:00
committed by GitHub
76 changed files with 487 additions and 2966 deletions
+1 -1
View File
@@ -115,7 +115,7 @@ node_modules/
# Ignore global package-lock.json that generates
plaintext.yml
structure.sql
db/*.sql
# Local development
# used by dotenv
@@ -1,182 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class WorkPackages::AutomaticMode::MigrateValuesJob < ApplicationJob
def perform
with_temporary_tables do
change_independent_childless_work_packages_scheduling_mode_to_manual
set_lags_for_follows_relations
copy_values_to_work_packages_and_update_journals
end
end
private
def with_temporary_tables
WorkPackage.transaction do
create_temporary_tables
yield
ensure
drop_temporary_tables
end
end
def create_temporary_tables
execute(<<~SQL.squish)
CREATE UNLOGGED TABLE temp_wp_values
AS SELECT
id,
start_date,
due_date,
schedule_manually
FROM work_packages
SQL
execute(<<~SQL.squish)
CREATE MATERIALIZED VIEW follows_relations
AS SELECT
relations.id as id,
relations.from_id as succ_id,
COALESCE(wp_pred.due_date, wp_pred.start_date) as pred_date,
COALESCE(wp_succ.start_date, wp_succ.due_date) as succ_date,
wp_succ.schedule_manually as succ_schedule_manually
FROM relations
LEFT JOIN work_packages wp_pred ON relations.to_id = wp_pred.id
LEFT JOIN work_packages wp_succ ON relations.from_id = wp_succ.id
WHERE relation_type = 'follows'
SQL
execute("CREATE INDEX ON follows_relations (succ_id)")
end
def drop_temporary_tables
execute("DROP TABLE temp_wp_values")
execute("DROP MATERIALIZED VIEW follows_relations")
end
# Change the scheduling mode to manual for:
# - non-successor (independent) and non-parent (childless) work packages
# - successor work packages with dates but without any predecessor with dates
def change_independent_childless_work_packages_scheduling_mode_to_manual
execute(<<~SQL.squish)
UPDATE temp_wp_values
SET schedule_manually = true
WHERE NOT EXISTS (
SELECT 1
FROM follows_relations
WHERE follows_relations.succ_id = temp_wp_values.id
AND (follows_relations.pred_date IS NOT NULL
OR follows_relations.succ_date IS NULL)
) AND NOT EXISTS (
SELECT 1
FROM work_packages
WHERE work_packages.parent_id = temp_wp_values.id
)
SQL
end
def set_lags_for_follows_relations
working_days = Setting.working_days
# Here is the algorithm:
# - Take all follows relations with dates
# - Filter to keep only the closest relation for a same successor
# - Generate a series of dates between the min date and the max date and
# filter for working days
# - Use both information to count the number of working days between
# predecessor and successor dates and update the lag with it
execute(<<~SQL.squish)
WITH closest_follows_relations_with_dates AS (
SELECT DISTINCT ON (succ_id)
id,
pred_date,
succ_date
FROM follows_relations
WHERE pred_date IS NOT NULL
AND succ_date IS NOT NULL
ORDER BY succ_id, pred_date DESC
),
working_dates AS (
SELECT date::date
FROM generate_series(
(SELECT MIN(pred_date) FROM closest_follows_relations_with_dates),
(SELECT MAX(succ_date) FROM closest_follows_relations_with_dates),
'1 day'::interval
) AS date
WHERE EXTRACT(ISODOW FROM date)::integer IN (#{working_days.join(',')})
AND NOT date IN (SELECT date FROM non_working_days)
)
UPDATE relations
SET lag = (
SELECT COUNT(*)
FROM working_dates
WHERE date > pred_date
AND date < succ_date
)
FROM closest_follows_relations_with_dates
WHERE relations.id = closest_follows_relations_with_dates.id
SQL
end
def copy_values_to_work_packages_and_update_journals
updated_work_package_ids = copy_values_to_work_packages
create_journals_for_updated_work_packages(updated_work_package_ids)
end
def copy_values_to_work_packages
results = execute(<<~SQL.squish)
UPDATE work_packages
SET schedule_manually = temp_wp_values.schedule_manually,
lock_version = lock_version + 1,
updated_at = NOW()
FROM temp_wp_values
WHERE work_packages.id = temp_wp_values.id
AND work_packages.schedule_manually IS DISTINCT FROM temp_wp_values.schedule_manually
RETURNING work_packages.id
SQL
results.column_values(0)
end
def create_journals_for_updated_work_packages(updated_work_package_ids)
cause = { type: "system_update", feature: "scheduling_mode_adjusted" }
WorkPackage.where(id: updated_work_package_ids).find_each do |work_package|
Journals::CreateService
.new(work_package, system_user)
.call(cause:)
end
end
# Executes an sql statement, shorter.
def execute(sql)
ActiveRecord::Base.connection.execute(sql)
end
def system_user
@system_user ||= User.system
end
end
-404
View File
@@ -1,404 +0,0 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
Dir[Rails.root.join("db/migrate/tables/*.rb").to_s].each { |file| require file }
Dir[Rails.root.join("db/migrate/extensions/*.rb").to_s].each { |file| require file }
require Rails.root.join("db/migrate/migration_utils/squashed_migration").to_s
# This migration aggregates a set of former migrations
class AggregatedMigrations < SquashedMigration
extensions Extensions::BtreeGist,
Extensions::PgTrgm,
Extensions::Unaccent,
Extensions::VersionNameCollation
tables Tables::Projects,
Tables::Colors,
Tables::Types,
Tables::Statuses,
Tables::WorkPackages,
Tables::Users,
Tables::GroupUsers,
Tables::Categories,
Tables::Relations,
Tables::WorkPackageHierarchies,
Tables::Sessions,
Tables::Announcements,
Tables::Attachments,
Tables::LdapAuthSources,
Tables::Forums,
Tables::Messages,
Tables::CustomFieldSections,
Tables::CustomFields,
Tables::CustomFieldsProjects,
Tables::CustomFieldsTypes,
Tables::CustomOptions,
Tables::CustomValues,
Tables::Changesets,
Tables::ChangesetsWorkPackages,
Tables::Journals,
Tables::WorkPackageJournals,
Tables::ProjectJournals,
Tables::MessageJournals,
Tables::NewsJournals,
Tables::WikiPageJournals,
Tables::ChangesetJournals,
Tables::AttachmentJournals,
Tables::AttachableJournals,
Tables::CustomizableJournals,
Tables::Comments,
Tables::Changes,
Tables::Repositories,
Tables::Enumerations,
Tables::Roles,
Tables::RolePermissions,
Tables::MemberRoles,
Tables::Members,
Tables::News,
Tables::ProjectsTypes,
Tables::Queries,
Tables::Settings,
Tables::Tokens,
Tables::UserPreferences,
Tables::UserPasswords,
Tables::Versions,
Tables::Watchers,
Tables::WikiPages,
Tables::WikiRedirects,
Tables::Wikis,
Tables::Workflows,
Tables::Exports,
Tables::MenuItems,
Tables::CustomStyles,
Tables::DesignColors,
Tables::EnterpriseTokens,
Tables::EnabledModules,
Tables::AttributeHelpTexts,
Tables::CustomActions,
Tables::CustomActionsProjects,
Tables::CustomActionsRoles,
Tables::CustomActionsStatuses,
Tables::CustomActionsTypes,
Tables::OAuthApplications,
Tables::OAuthAccessGrants,
Tables::OAuthAccessTokens,
Tables::OrderedWorkPackages,
Tables::Notifications,
Tables::NotificationSettings,
Tables::Views,
Tables::OAuthClients,
Tables::OAuthClientTokens,
Tables::NonWorkingDays,
Tables::PaperTrailAudits,
Tables::ProjectCustomFieldProjectMappings,
Tables::ProjectQueries,
Tables::GoodJobs,
Tables::GoodJobProcesses,
Tables::GoodJobSettings,
Tables::GoodJobBatches,
Tables::GoodJobExecutions,
Tables::Favorites,
Tables::EmojiReactions,
Tables::AuthProviders,
Tables::RemoteIdentities,
Tables::HierarchicalItems,
Tables::HierarchicalItemHierarchies
# rubocop:disable Metrics/CollectionLiteralLength
squashed_migrations *%w[
10000000000000_to_v710_aggregated_migrations
20100528100562_aggregated_global_roles_migrations
20170703075208_add_attribute_help_texts
20170705134348_remove_attribute_visibility
20170818063404_add_timeline_labels_to_query
20170829095701_generate_wp_closure
20171106074835_move_hashed_token_to_core
20171129145631_add_fulltext_to_attachments
20180105130053_rebuild_dag
20180108132929_vacuum_relations
20180116065518_add_hierarchy_paths
20190301122554_remove_hierarchy_paths
20180117065255_remove_timelines_and_reportings
20180122135443_add_tsv_columns_to_attachments
20180123092002_add_custom_actions
20180213155320_add_description_to_custom_actions
20180221151038_add_position_to_custom_action
20180305130811_remove_wiki_content_versions
20180419061910_timestamp_for_caching
20180504144320_add_color_to_statuses_and_enumerations
20180510184732_rename_planning_elemnt_type_colors_to_colors
20180518130559_add_timestamps_to_wiki
20180524084654_remove_non_null_container_on_attachments
20180524113516_add_consent_timestamp_to_user
20180706150714_convert_to_markdown
20180717102331_remove_in_aggregation_from_type
20180801072018_remove_responsible_and_type_from_project
20180830120550_migrate_light_background_themes
20180903110212_add_highlighting_to_query
20180924141838_add_highlighted_attributes_to_query
20181101132712_add_read_only_to_statuses
20181112125034_create_doorkeeper_tables
20181121174153_create_ordered_work_packages
20190124081710_remove_accessibility_mode
20190207155607_add_hidden_to_queries
20190227163226_add_tls_mode_to_auth_sources
20190312083304_rename_boards_to_forums
20190411122815_set_timeline_auto_zoom
20190502102512_ensure_postgres_index_names
20190507132517_add_board_view_to_roles
20190509071101_add_default_description_to_types
20190527095959_set_manage_board_permission
20190603060951_set_assign_versions_permission
20190618115620_fix_available_languages
20190619143049_add_timestamps_to_query
20190716071941_add_display_representation_to_query
20190722082648_add_derived_estimated_hours_to_work_packages
20190724093332_add_journal_versions_table
20190920102446_clean_custom_values
20190923111902_add_project_status_reporting
20190923123858_simplify_project_active_and_timestamp
20191106132533_make_system_user_active
20191112111040_fix_system_user_status
20191115141154_add_content_orientation_to_custom_fields
20191216135213_join_table_for_active_activities
20200114091135_add_theme_name_to_custom_styles
20200115090742_fix_parent_id_for_wiki_pages
20200206101135_add_theme_logo_to_custom_style
20200217061622_add_timestamp_to_news
20200217155632_rename_tokens
20200220171133_rename_bim_module
20200302100431_fix_attachable_journals
20200325101528_strip_whitespace_from_user_attributes
20200326102408_rename_fixed_version
20200403105252_add_cron_to_delayed_jobs
20200415131633_add_work_package_exports
20200427121606_add_filter_to_ldap
20200428105404_unique_member_role
20200504085933_add_schedule_manually_to_work_packages
20200522131255_splash_multi_list_customizable_journals
20200522140244_remove_journal_versions_table
20200527130633_add_templated_to_project
20200625133727_fix_inherited_group_member_roles
20200708065116_fix_members_inconsistencies
20200803081038_journalize_scheduling_mode
20200820140526_remove_summable_setting
20200903064009_enable_current_project_custom_fields_columns
20200907090753_change_attachment_filesize_to_big_int
20200914092212_set_current_timestamp_defaults_for_bcf_viewpoints_and_issues
20200924085508_cleanup_orphaned_journal_data
20200925084550_members_allow_null_on_project
20201005120137_ensure_integer_for_relations_foreign_keys
20201005184411_rename_timestamps
20201125121949_remove_renamed_cron_job
20210221230446_add_group_user_primary_key
20210126112238_add_uniqueness_constrain_on_lastname_for_groups_and_placeholder_users
20210127134438_alter_user_attributes_max_length.rb
20210214205545_replace_invalid_principal_references
20210310101840_generalize_exports
20210331085058_migrate_sessions_unlogged
20210427065703_make_system_user_admin
20210510193438_remove_project_setting
20210512121322_make_project_identifier_unique
20210519141244_remove_reply_from_message_journalizing
20210616145324_polymorphic_journal_data
20210616191052_create_notifications
20210618125430_authors_as_watchers
20210618132206_add_notification_settings
20210628185054_extend_custom_field_name_length
20210701073944_add_digest_setting
20210701082511_add_digest_to_notification
20210726070813_remove_journal_versions
20210802114054_add_notification_setting_options
20210825183540_make_user_preferences_json
20210902201126_cleanup_user_preferences
20210914065555_cleanup_notifications
20210915154656_add_user_preference_settings_indices
20210917190141_non_work_package_notification_settings
20210922123908_notification_foreign_key_constraint
20210928133538_add_reminder_workdays
20211005080304_tzinfo_time_zones
20211005135637_remove_invalid_group_users
20211026061420_add_indexes_for_email_reminder_pause
20211101152840_redistribute_edit_project_permission
20211102161932_remove_custom_field_types
20211103120946_clean_emails_footer
20211104151329_default_notification_setting
20211117195121_remove_destroyed_help_texts
20211118203332_clean_hide_mail
20211130161501_add_views
20211209092519_query_views
20220106145037_fix_missing_notification_settings
20220202140507_reorder_project_children
20220223095355_projects_lft_rgt_index
20220302123642_assignable_to_permission
20220319211253_add_parent_id_to_wp
20220323083000_add_include_subprojects_to_query
20220414085531_migrate_team_planner_permissions
20220428071221_restore_defaults_on_empty_settings
20220426132637_refix_inherited_group_member_roles
20220408080838_bigint_primary_key_on_relations
20220503093844_create_oauth_client
20220511124930_create_week_days
20220517113828_create_non_working_days
20220518154147_create_oauth_client_tokens
20220525154549_add_duration_to_work_packages
20220614132200_add_ignore_non_working_days_to_work_packages
20220615213015_migrate_log_time_to_log_own_time_in_role_permissions
20220620132922_change_duration_default_value
20220622151721_drop_project_associations
20220629061540_add_paper_trail
20220629073727_add_polymorphic_integration_to_oauth_application
20220712132505_add_foreign_key_constraint_for_type_color_id
20220714145356_migrate_work_package_export_settings
20220804112533_remove_notification_cleanup_job
20220811061024_rename_work_package_export_limit
20220817154403_remove_work_packages_duration_field_active_setting
20220818074150_fix_invalid_journals
20220818074159_fix_deleted_data_journals
20220830074821_add_ignore_non_working_days_to_work_package_journals
20220830092057_change_default_for_non_working_days
20220831073113_work_package_project_foreign_key
20220831081937_migrate_timestamps_to_with_timezone
20220909153412_drop_week_days
20220911182835_create_default_working_days_setting_entry
20220918165443_add_start_date_due_date_and_overdue_to_notification_settings
20220922200908_split_involved_notification_setting
20220926124435_constrain_work_package_dates
20220929114423_add_unique_index_to_ldap_groups_membership
20220930133418_set_duration_for_milestone_work_packages
20221017073431_remove_orphaned_tokens
20221017184204_change_defaults_for_notification_settings
20221026132134_bigint_primary_and_foreign_keys
20221028070534_change_notification_settings_start_date_due_date_and_overdue_duration_unit_to_days
20221027151959_remove_plaintext_tokens
20221029194419_add_timestamps_to_queries
20221115082403_add_ldap_tls_options
20221129074635_remove_activity_type_from_journals_table
20221130150352_create_project_journals
20221201140825_add_non_null_constraint_on_projects_identifier
20221202130039_fill_project_journals_with_existing_data
20221213092910_remove_default_values_from_journal_tables_definition
20230508150835_copy_project_status_into_projects_and_journals
20230105073117_remove_renamed_date_alert_job
20230105134940_work_package_date_indices
20230130134630_add_index_for_work_package_journals_project_id
20230306083203_non_null_data_reference_on_journals
20230309104056_unique_index_on_custom_fields_projects
20230314093106_add_update_delete_cascade_to_work_packages_project_id
20230314165213_add_foreign_keys_to_work_packages
20230315103437_add_foreign_keys_to_workflows
20230315183431_add_foreign_keys_to_projects_types
20230315184533_add_foreign_keys_to_custom_fields_projects
20230322135932_merge_wiki_content_into_page
20230328154645_add_gin_trgm_index_on_journals_and_custom_values
20230531093004_remove_default_from_query_name
20230606083221_add_cause_to_journal
20230608151123_add_validity_period_to_journals
20230613155001_add_export_logo_to_custom_style
20230718084649_add_create_user_permission_to_roles
20230726061920_rename_auth_source_to_ldap_auth_source
20230726112130_remove_type_from_ldap_auth_sources
20230803113215_add_indices_to_work_package_journals
20230808080001_remove_some_string_length_constraints
20230808140921_add_derived_remaining_hours_to_work_packages
20230810074642_add_optional_entity_to_members
20230829151629_add_copy_work_packages_permission_to_roles
20230905090205_add_share_workpackages_permission
20230905126002_add_export_cover_to_custom_style
20230911093530_remove_news_journals_title_length_constraint
20230912185647_add_view_shared_work_packages_permission
20231002141527_fix_default_language_value_for_chinese_simplified
20231005113307_role_to_project_role
20231017093339_add_allow_non_open_versions_to_custom_fields
20231024150429_add_shared_to_notification_settings
20231026111049_add_public_permissions_to_project_roles
20231027102747_rollback_create_meeting_agendas_and_split_edit_meeting_role
20231031133334_create_project_custom_field_project_mappings
20231105194747_add_data_to_tokens
20231123111357_create_custom_field_sections
20231128080650_add_work_package_roles
20231205143648_add_add_work_package_attachment_permission_to_commenters
20231212131603_set_custom_fields_filter_default_true
20231227100753_fix_derived_work_and_remaining_work_values
20240104172050_add_project_queries
20240115112549_fix_spent_time_widget_identifier
20240116165933_add_derived_done_ratio_to_work_packages
20240131130134_fix_inherited_group_memberships
20240206173841_fix_untranslated_work_package_roles
20240207075946_add_status_to_attachment
20240208100316_enable_required_project_custom_fields_in_all_projects
20240222155909_rename_columns_on_project_queries
20240227154544_remove_delayed_jobs
20240306083241_change_default_value_of_alternative_color
20240206085104_remove_enums
20240307094432_change_done_ratio_default_value_to_null
20240307102541_reduce_configurable_design_variables
20240307190126_rename_portuguese_locale
20240311111957_enable_unaccent_extension
20240325150312_change_derived_done_ratio_default_value_to_null
20240328154805_change_status_default_done_ratio_to_zero
20240402065214_remove_ldap_tls_setting
20240402072213_update_progress_calculation
20240404074025_create_favorite
20240408093541_change_default_accent_and_bim_primary_color
20240422141623_rename_estimate_and_time_attribute_group
20240424093311_add_excluded_from_totals_to_statuses
20240424160513_add_settings_to_projects
20240430143313_update_default_project_columns
20240506091102_remove_totals_from_childless_work_packages
20240513135928_extend_oauth_applications
20240519123921_add_public_to_project_queries
20240522073759_fix_status_excluded_from_totals_changed_journal_cause
20240527070439_add_project_query_roles
20240611105232_set_watched_notification_setting_to_true
20240624103354_create_emoji_reactions
20240625075139_add_uniqueness_index_to_project_custom_field_project_mappings
20240703131639_add_timestamps_to_user_preferences
20240715183144_add_indexes_to_custom_options
20240801105918_add_auth_providers
20240805104004_rename_visible_to_admin_only_in_custom_fields
20240806144333_create_remote_identities
20240808125617_populate_remote_identities
20240808133947_add_lock_version_to_oauth_client_tokens
20240813131647_drop_origin_user_id_from_oauth_client_tokens
20240820123011_remove_project_from_notification
20240909151818_migrate_legacy_default_theme_to_light_theme
20240920152544_set_versions_name_collation
20240924114246_create_hierarchical_items
20240408132459_rename_delay_to_lag
20240410060041_remove_virtual_delay_column
20240620115412_add_project_attribute_roles
20240917105829_add_primary_key_to_custom_fields_projects
20241001205821_add_standard_global_role
20241002151949_remove_hide_mail_from_user_preferences
20241015081341_remove_obsolete_design_variables
]
# rubocop:enable Metrics/CollectionLiteralLength
end
+171
View File
@@ -0,0 +1,171 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
Dir[Rails.root.join("db/migrate/tables/*.rb").to_s].each { |file| require file }
Dir[Rails.root.join("db/migrate/extensions/*.rb").to_s].each { |file| require file }
require Rails.root.join("db/migrate/migration_utils/squashed_migration").to_s
# This migration aggregates a set of former migrations
class AggregatedMigrations < SquashedMigration
extensions Extensions::BtreeGist,
Extensions::PgTrgm,
Extensions::Unaccent,
Extensions::VersionNameCollation
tables Tables::Projects,
Tables::Colors,
Tables::Types,
Tables::Statuses,
Tables::WorkPackages,
Tables::Users,
Tables::GroupUsers,
Tables::Categories,
Tables::Relations,
Tables::WorkPackageHierarchies,
Tables::Sessions,
Tables::Announcements,
Tables::Attachments,
Tables::LdapAuthSources,
Tables::Forums,
Tables::Messages,
Tables::CustomFieldSections,
Tables::CustomFields,
Tables::CustomFieldsProjects,
Tables::CustomFieldsTypes,
Tables::CustomOptions,
Tables::CustomValues,
Tables::Changesets,
Tables::ChangesetsWorkPackages,
Tables::Journals,
Tables::WorkPackageJournals,
Tables::ProjectJournals,
Tables::MessageJournals,
Tables::NewsJournals,
Tables::WikiPageJournals,
Tables::ChangesetJournals,
Tables::AttachmentJournals,
Tables::AttachableJournals,
Tables::CustomizableJournals,
Tables::Comments,
Tables::Changes,
Tables::Repositories,
Tables::Enumerations,
Tables::Roles,
Tables::RolePermissions,
Tables::MemberRoles,
Tables::Members,
Tables::News,
Tables::ProjectsTypes,
Tables::Queries,
Tables::Settings,
Tables::Tokens,
Tables::UserPreferences,
Tables::UserPasswords,
Tables::Versions,
Tables::Watchers,
Tables::WikiPages,
Tables::WikiRedirects,
Tables::Wikis,
Tables::Workflows,
Tables::Exports,
Tables::MenuItems,
Tables::CustomStyles,
Tables::DesignColors,
Tables::EnterpriseTokens,
Tables::EnabledModules,
Tables::AttributeHelpTexts,
Tables::CustomActions,
Tables::CustomActionsProjects,
Tables::CustomActionsRoles,
Tables::CustomActionsStatuses,
Tables::CustomActionsTypes,
Tables::OAuthApplications,
Tables::OAuthAccessGrants,
Tables::OAuthAccessTokens,
Tables::OrderedWorkPackages,
Tables::Notifications,
Tables::NotificationSettings,
Tables::Views,
Tables::OAuthClients,
Tables::OAuthClientTokens,
Tables::NonWorkingDays,
Tables::PaperTrailAudits,
Tables::ProjectCustomFieldProjectMappings,
Tables::ProjectQueries,
Tables::GoodJobs,
Tables::GoodJobProcesses,
Tables::GoodJobSettings,
Tables::GoodJobBatches,
Tables::GoodJobExecutions,
Tables::Favorites,
Tables::EmojiReactions,
Tables::AuthProviders,
Tables::RemoteIdentities,
Tables::HierarchicalItems,
Tables::HierarchicalItemHierarchies,
Tables::ProjectPhaseDefinitions,
Tables::ProjectPhases,
Tables::Reminders,
Tables::ReminderNotifications,
Tables::ProjectPhaseJournals,
Tables::ServiceAccountAssociations,
Tables::ExportSettings
squashed_migrations *%w[
1000015_aggregated_migrations
20241030154245_create_project_life_cycles
20241119131205_create_reminders
20241120095318_update_scheduling_mode_and_lags
20241121094113_migrate_cost_settings_to_regular_settings
20241121113638_create_reminder_notifications
20241125161226_unique_index_on_project_life_cycle_steps
20241126111225_add_project_life_cycle_step_roles
20241127161228_grant_select_project_life_cycle_permission
20241129135602_populate_manage_own_reminders_permission
20241211152749_introduce_patterns_to_types
20241217190533_add_uniqueness_index_to_project_life_cycle_step_definitions_name
20250102161733_adds_position_cache_to_hierarchy_items
20250108100511_remove_incorrect_manage_own_reminders_permission
20250114162956_create_project_life_cycle_step_journals
20250117105334_remove_manage_own_reminders_permission
20250128164217_remove_is_default_for_time_entry_activities
20250210163523_add_export_templates_to_type
20250213193012_fix_typo_in_settings_user_format_value
20250214162601_add_project_life_cycle_step_date_indices
20250220123358_add_polymorphic_auth_source_and_integration_to_remote_identities
20250226134521_add_restricted_to_journals
20250227161653_populate_comments_with_restricted_visibility_permissions
20250324133701_create_service_account_associations
20250324161229_merge_lifecycle_steps
20250326151553_export_settings
20250327071204_add_dismissed_enterprise_banners_to_user_preference
20250402083709_change_remote_identities_foreign_key_indices
]
end
@@ -1,50 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class UpdateSchedulingModeAndLags < ActiveRecord::Migration[7.1]
def up
change_column_default :work_packages, :schedule_manually, from: false, to: true
execute "UPDATE work_packages SET schedule_manually = false WHERE schedule_manually IS NULL"
change_column_null :work_packages, :schedule_manually, false
migration_job = WorkPackages::AutomaticMode::MigrateValuesJob
if Rails.env.development?
migration_job.perform_now
else
migration_job.perform_later
end
end
def down
change_column_default :work_packages, :schedule_manually, from: true, to: false
# Keep the not-null constraint when rolling back
change_column_null :work_packages, :schedule_manually, false
end
end
@@ -1,43 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddStartEndTimesToTimeEntries < ActiveRecord::Migration[7.1]
def change
change_table :time_entries, bulk: true do |t|
t.integer :start_time, null: true
t.integer :end_time, null: true
end
change_table :time_entry_journals, bulk: true do |t|
t.integer :start_time, null: true
t.integer :end_time, null: true
end
end
end
@@ -1,54 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class MigrateCostSettingsToRegularSettings < ActiveRecord::Migration[7.1]
def up
costs_settings = Setting.plugin_costs || {}
if costs_settings["costs_currency"]
Setting.create(name: "costs_currency", value: costs_settings["costs_currency"])
end
if costs_settings["costs_currency_format"]
Setting.create(name: "costs_currency_format", value: costs_settings["costs_currency_format"])
end
Setting.where(name: "plugin_costs").destroy_all
end
def down
costs_settings = {
"costs_currency" => Setting.costs_currency,
"costs_currency_format" => Setting.costs_currency_format
}
Setting.create(name: "plugin_costs", value: costs_settings)
Setting.where(name: ["costs_currency", "costs_currency_format"]).destroy_all
end
end
@@ -1,43 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddTimezoneIdentifierToTimeEntry < ActiveRecord::Migration[7.1]
def change
change_table :time_entries, bulk: true do |t|
t.string :time_zone, null: true
t.remove :end_time, type: :integer
end
change_table :time_entry_journals, bulk: true do |t|
t.string :time_zone, null: true
t.remove :end_time, type: :integer
end
end
end
@@ -1,37 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class UniqueIndexOnProjectLifeCycleSteps < ActiveRecord::Migration[7.1]
def change
add_index :project_life_cycle_steps,
%i[project_id definition_id],
unique: true
end
end
@@ -1,37 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require_relative "migration_utils/permission_adder"
class GrantSelectProjectLifeCyclePermission < ActiveRecord::Migration[7.1]
def up
::Migration::MigrationUtils::PermissionAdder.add(:edit_project, :select_project_life_cycle)
end
end
@@ -1,42 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require Rails.root.join("db/migrate/migration_utils/permission_adder")
class PopulateManageOwnRemindersPermission < ActiveRecord::Migration[7.1]
def up
::Migration::MigrationUtils::PermissionAdder
.add(:view_project,
:manage_own_reminders)
end
# No-op
def down; end
end
@@ -30,14 +30,7 @@
class CreateGoodJobExecutionErrorBacktrace < ActiveRecord::Migration[7.1]
def change
reversible do |dir|
dir.up do
# Ensure this incremental update migration is idempotent
# with monolithic install migration.
return if connection.column_exists?(:good_job_executions, :error_backtrace)
end
end
add_column :good_job_executions, :error_backtrace, :text, array: true
# Moved to db/migrate/tables/good_job_executions.rb
# These files are not squashed since good_job will recreate them otherwise when an update is done.
end
end
@@ -30,17 +30,7 @@
class CreateGoodJobProcessLockIds < ActiveRecord::Migration[7.1]
def change
reversible do |dir|
dir.up do
# Ensure this incremental update migration is idempotent
# with monolithic install migration.
return if connection.column_exists?(:good_jobs, :locked_by_id)
end
end
add_column :good_jobs, :locked_by_id, :uuid
add_column :good_jobs, :locked_at, :datetime
add_column :good_job_executions, :process_id, :uuid
add_column :good_job_processes, :lock_type, :integer, limit: 2
# Moved to several db/migrate/tables/good_job*.rb
# These files are not squashed since good_job will recreate them otherwise when an update is done.
end
end
@@ -29,52 +29,8 @@
#++
class CreateGoodJobProcessLockIndexes < ActiveRecord::Migration[7.1]
disable_ddl_transaction!
# rubocop:disable Metrics/AbcSize
def change
reversible do |dir|
dir.up do
unless connection.index_name_exists?(:good_jobs, :index_good_jobs_on_priority_scheduled_at_unfinished_unlocked)
add_index :good_jobs, %i[priority scheduled_at],
order: { priority: "ASC NULLS LAST", scheduled_at: :asc },
where: "finished_at IS NULL AND locked_by_id IS NULL",
name: :index_good_jobs_on_priority_scheduled_at_unfinished_unlocked,
algorithm: :concurrently
end
unless connection.index_name_exists?(:good_jobs, :index_good_jobs_on_locked_by_id)
add_index :good_jobs, :locked_by_id,
where: "locked_by_id IS NOT NULL",
name: :index_good_jobs_on_locked_by_id,
algorithm: :concurrently
end
unless connection.index_name_exists?(:good_job_executions, :index_good_job_executions_on_process_id_and_created_at)
add_index :good_job_executions, %i[process_id created_at],
name: :index_good_job_executions_on_process_id_and_created_at,
algorithm: :concurrently
end
end
dir.down do
if connection.index_name_exists?(
:good_jobs, :index_good_jobs_on_priority_scheduled_at_unfinished_unlocked
)
remove_index(:good_jobs, name: :index_good_jobs_on_priority_scheduled_at_unfinished_unlocked)
end
if connection.index_name_exists?(:good_jobs, :index_good_jobs_on_locked_by_id)
remove_index(:good_jobs, name: :index_good_jobs_on_locked_by_id)
end
if connection.index_name_exists?(
:good_job_executions, :index_good_job_executions_on_process_id_and_created_at
)
remove_index(:good_job_executions, name: :index_good_job_executions_on_process_id_and_created_at)
end
end
end
# Moved to several db/migrate/tables/good_job*.rb
# These files are not squashed since good_job will recreate them otherwise when an update is done.
end
# rubocop:enable Metrics/AbcSize
end
@@ -30,14 +30,7 @@
class CreateGoodJobExecutionDuration < ActiveRecord::Migration[7.1]
def change
reversible do |dir|
dir.up do
# Ensure this incremental update migration is idempotent
# with monolithic install migration.
return if connection.column_exists?(:good_job_executions, :duration)
end
end
add_column :good_job_executions, :duration, :interval
# Moved to db/migrate/tables/good_job_executions.rb
# These files are not squashed since good_job will recreate them otherwise when an update is done.
end
end
@@ -1,37 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class IntroducePatternsToTypes < ActiveRecord::Migration[7.1]
def change
change_table :types do |t|
t.text :patterns, null: true
end
end
end
@@ -1,35 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddUniquenessIndexToProjectLifeCycleStepDefinitionsName < ActiveRecord::Migration[7.1]
def change
add_index :project_life_cycle_step_definitions, :name, unique: true
end
end
@@ -1,70 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddsPositionCacheToHierarchyItems < ActiveRecord::Migration[7.1]
def change
add_column :hierarchical_items, :position_cache, :bigint, null: true
add_index :hierarchical_items, :position_cache
reversible do |dir|
dir.up do
update_sql = ->(root_id) {
<<-SQL.squish
UPDATE hierarchical_items
SET position_cache = subquery.position
FROM (
SELECT hi.id
, SUM((1 + COALESCE(anc.sort_order, 0)) *
POWER(count_max.total_descendants, count_max.max_gens - depths.generations)) AS position
FROM hierarchical_items hi
INNER JOIN hierarchical_item_hierarchies hih ON hi.id = hih.descendant_id
JOIN hierarchical_item_hierarchies anc_h ON anc_h.descendant_id = hih.descendant_id
JOIN hierarchical_items anc ON anc.id = anc_h.ancestor_id
JOIN hierarchical_item_hierarchies depths ON depths.ancestor_id = #{root_id} AND depths.descendant_id = anc.id
, (
SELECT COUNT(1) AS total_descendants, MAX(generations) + 1 AS max_gens
FROM hierarchical_items hi
INNER JOIN hierarchical_item_hierarchies hih ON hi.id = hih.ancestor_id
WHERE ancestor_id = #{root_id}
) count_max
WHERE hih.ancestor_id = #{root_id}
GROUP BY hi.id) as subquery
WHERE hierarchical_items.id = subquery.id;
SQL
}
roots_sql = "select id from hierarchical_items where custom_field_id is not NULL;"
ActiveRecord::Base.connection.execute(roots_sql).each do |row|
ActiveRecord::Base.connection.execute(update_sql.call(row["id"]))
end
end
end
end
end
@@ -1,67 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class RemoveIncorrectManageOwnRemindersPermission < ActiveRecord::Migration[7.1]
def up
# Remove manage_own_reminders permission from non member and anonymous roles
# Use hardcoded values for `Role::BUILTIN_NON_MEMBER` and `Role::BUILTIN_ANONYMOUS`
# to avoid breaking the migration if the values are changed in the future
non_member_builtin = 1 # Role::BUILTIN_NON_MEMBER
anonymous_builtin = 2 # Role::BUILTIN_ANONYMOUS
execute <<-SQL.squish
DELETE FROM role_permissions
WHERE role_id IN (
SELECT id FROM roles WHERE builtin IN (#{non_member_builtin}, #{anonymous_builtin})
)
AND permission = 'manage_own_reminders'
SQL
# Remove all reminders created by anonymous user and cascade delete related records
execute <<-SQL.squish
WITH deleted_reminders AS (
DELETE FROM reminders
WHERE creator_id IN (
SELECT id FROM users WHERE type = 'AnonymousUser'
)
RETURNING id
),
deleted_reminder_notifications AS (
DELETE FROM reminder_notifications
WHERE reminder_id IN (SELECT id FROM deleted_reminders)
RETURNING notification_id
)
DELETE FROM notifications
WHERE id IN (SELECT notification_id FROM deleted_reminder_notifications)
SQL
end
# No-op
def down; end
end
@@ -1,41 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class RemoveManageOwnRemindersPermission < ActiveRecord::Migration[7.1]
def up
execute <<-SQL.squish
DELETE FROM role_permissions
WHERE permission = 'manage_own_reminders'
SQL
end
# No-op
def down; end
end
@@ -1,39 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class RemoveIsDefaultForTimeEntryActivities < ActiveRecord::Migration[7.1]
def up
execute <<~SQL.squish
UPDATE "enumerations"
SET "is_default" = false
WHERE "type" = 'TimeEntryActivity'
SQL
end
end
@@ -1,35 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddExportTemplatesToType < ActiveRecord::Migration[7.1]
def change
add_column :types, :pdf_export_templates_config, :jsonb, default: {}
end
end
@@ -2,16 +2,7 @@
class AddJobsFinishedAtToGoodJobBatches < ActiveRecord::Migration[7.1]
def change
reversible do |dir|
dir.up do
# Ensure this incremental update migration is idempotent
# with monolithic install migration.
return if connection.column_exists?(:good_job_batches, :jobs_finished_at)
end
end
change_table :good_job_batches do |t|
t.datetime :jobs_finished_at
end
# Moved to db/migrate/tables/good_job_batches.rb
# These files are not squashed since good_job will recreate them otherwise when an update is done.
end
end
@@ -1,43 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class FixTypoInSettingsUserFormatValue < ActiveRecord::Migration[7.1]
def up
Setting
.where(name: "user_format", value: "lastname_coma_firstname")
.update(value: "lastname_comma_firstname")
end
def down
Setting
.where(name: "user_format", value: "lastname_comma_firstname")
.update(value: "lastname_coma_firstname")
end
end
@@ -1,36 +0,0 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2010-2025 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
class AddProjectLifeCycleStepDateIndices < ActiveRecord::Migration[7.1]
def change
add_index :project_life_cycle_steps, :start_date
add_index :project_life_cycle_steps, :end_date
end
end
@@ -1,75 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddPolymorphicAuthSourceAndIntegrationToRemoteIdentities < ActiveRecord::Migration[7.1]
def up
remove_foreign_key :remote_identities, :oauth_clients
rename_column :remote_identities, :oauth_client_id, :auth_source_id
add_column :remote_identities, :auth_source_type, :string
remove_index :remote_identities, :auth_source_id
remove_index :remote_identities, %i[user_id auth_source_id]
add_index :remote_identities, %i[auth_source_type auth_source_id]
add_column :remote_identities, :integration_type, :string
add_column :remote_identities, :integration_id, :bigint
add_index :remote_identities, %i[integration_type integration_id]
execute <<~SQL.squish
UPDATE remote_identities
SET auth_source_type = 'OAuthClient',
integration_id = oauth_clients.integration_id,
integration_type = oauth_clients.integration_type
FROM oauth_clients
WHERE remote_identities.auth_source_id = oauth_clients.id;
SQL
change_column_null(:remote_identities, :integration_id, false)
change_column_null(:remote_identities, :integration_type, false)
change_column_null(:remote_identities, :auth_source_type, false)
add_index(:remote_identities,
%i[user_id auth_source_type auth_source_id integration_id integration_type],
unique: true)
end
def down
remove_index(:remote_identities,
%i[user_id auth_source_type auth_source_id integration_id integration_type])
rename_column :remote_identities, :auth_source_id, :oauth_client_id
add_foreign_key :remote_identities, :oauth_clients
add_index :remote_identities, :oauth_client_id
add_index :remote_identities, %i[user_id oauth_client_id], unique: true
remove_column :remote_identities, :auth_source_type
remove_column :remote_identities, :integration_id
remove_column :remote_identities, :integration_type
end
end
@@ -1,35 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddRestrictedToJournals < ActiveRecord::Migration[7.1]
def change
add_column :journals, :restricted, :boolean, default: false, null: false
end
end
@@ -1,44 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require Rails.root.join("db/migrate/migration_utils/permission_adder")
class PopulateCommentsWithRestrictedVisibilityPermissions < ActiveRecord::Migration[7.1]
def up
# grant the permission to view/write/edit comments with restricted visibility
# to users that can manage project members
::Migration::MigrationUtils::PermissionAdder.add(:manage_members, :view_comments_with_restricted_visibility)
::Migration::MigrationUtils::PermissionAdder.add(:manage_members, :add_comments_with_restricted_visibility)
::Migration::MigrationUtils::PermissionAdder.add(:manage_members, :edit_own_comments_with_restricted_visibility)
end
# noop
def down; end
end
@@ -1,35 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddBacklogToMeetingSections < ActiveRecord::Migration[8.0]
def change
add_column :meeting_sections, :backlog, :boolean, default: false, null: false
end
end
@@ -1,127 +0,0 @@
# frozen_string_literal: true
#
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require Rails.root.join("db/migrate/migration_utils/permission_renamer")
class MergeLifecycleSteps < ActiveRecord::Migration[8.0]
def change
reversible do |direction|
direction.up do
delete_life_cycle_project_queries
delete_life_cycles
::Migration::MigrationUtils::PermissionRenamer.rename("view_project_stages_and_gates", "view_project_phases")
::Migration::MigrationUtils::PermissionRenamer.rename("select_project_life_cycle", "select_project_phases")
::Migration::MigrationUtils::PermissionRenamer.rename("edit_project_stages_and_gates", "edit_project_phases")
end
direction.down do
::Migration::MigrationUtils::PermissionRenamer.rename("view_project_phases", "view_project_stages_and_gates")
::Migration::MigrationUtils::PermissionRenamer.rename("select_project_phases", "select_project_life_cycle")
::Migration::MigrationUtils::PermissionRenamer.rename("edit_project_phases", "edit_project_stages_and_gates")
end
end
adapt_tables
rename_tables
end
def delete_life_cycles
# The feature is behind a feature flag and not yet released.
# Potential data is thus simply removed and the seeder will add the updated data.
execute <<-SQL.squish
DELETE FROM project_life_cycle_steps;
SQL
execute <<-SQL.squish
DELETE FROM project_life_cycle_step_definitions;
SQL
execute <<-SQL.squish
DELETE FROM project_life_cycle_step_journals;
SQL
end
def delete_life_cycle_project_queries
step_ids = select_all(<<-SQL.squish).to_a.flatten.flat_map(&:values)
SELECT id from project_life_cycle_step_definitions;
SQL
if step_ids.any?
# This should be possible to be done like with orders and filters
execute <<-SQL.squish
DELETE
FROM project_queries
WHERE selects::jsonb ?| array[#{step_ids.map { |id| "'lcsd_#{id}'" }.join(',')}];
SQL
end
execute <<-SQL.squish
DELETE
FROM project_queries
WHERE jsonb_path_exists(orders::jsonb, '$[*] ? (@.attribute like_regex "^lcsd.*")');
SQL
execute <<-SQL.squish
DELETE
FROM project_queries
WHERE jsonb_path_exists(filters::jsonb, '$[*] ? (@.attribute like_regex "^lcsd.*")');
SQL
end
def adapt_tables
change_table(:project_life_cycle_step_definitions, bulk: true) do |t|
t.column :start_gate, :boolean, default: false, null: false
t.column :start_gate_name, :string
t.column :finish_gate, :boolean, default: false, null: false
t.column :finish_gate_name, :string
t.remove :type, type: :string
end
change_table(:project_life_cycle_steps) do |t|
t.remove :type, type: :string
t.rename :end_date, :finish_date
end
change_table(:project_life_cycle_step_journals) do |t|
t.rename :life_cycle_step_id, :phase_id
t.rename :end_date, :finish_date
end
change_table(:work_packages) do |t|
t.rename :project_life_cycle_step_id, :project_phase_id
end
end
def rename_tables
rename_table :project_life_cycle_step_definitions, :project_phase_definitions
rename_table :project_life_cycle_steps, :project_phases
rename_table :project_life_cycle_step_journals, :project_phase_journals
end
end
@@ -1,35 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddDismissedEnterpriseBannersToUserPreference < ActiveRecord::Migration[8.0]
def change
add_column :user_preferences, :dismissed_enterprise_banners, :jsonb, default: {}, null: false
end
end
@@ -1,39 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class ChangeRemoteIdentitiesForeignKeyIndices < ActiveRecord::Migration[8.0]
def change
# Not needed, covered by composite unique index
remove_index :remote_identities, :user_id
# Not needed, we never query for this
remove_index :remote_identities, :origin_user_id
end
end
@@ -31,7 +31,7 @@
require Rails.root.join("db/migrate/migration_utils/migration_squasher").to_s
class SquashedMigration < ActiveRecord::Migration[8.0]
class_attribute :minimum_version, default: "15"
class_attribute :minimum_version, default: "16"
def self.squashed_migrations(*migrations)
if migrations.any?
@@ -1,6 +1,6 @@
# frozen_string_literal: true
#-- copyright
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
@@ -26,18 +26,20 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
# ++
class ExportSettings < ActiveRecord::Migration[8.0]
def change
create_table :export_settings do |t|
require_relative "base"
class Tables::ExportSettings < Tables::Base
def self.table(migration)
create_table migration do |t|
t.references :query, null: false, foreign_key: true
t.string :format, null: false
t.jsonb :settings, default: {}, null: false
t.timestamps
end
add_index :export_settings, %i[query_id format], unique: true
t.index %i[query_id format], unique: true
end
end
end
+1
View File
@@ -44,6 +44,7 @@ class Tables::GoodJobBatches < Tables::Base
t.datetime :enqueued_at
t.datetime :discarded_at
t.datetime :finished_at
t.datetime :jobs_finished_at
end
end
end
+5
View File
@@ -42,9 +42,14 @@ class Tables::GoodJobExecutions < Tables::Base
t.datetime :finished_at
t.text :error
t.integer :error_event, limit: 2
t.text :error_backtrace, array: true
t.uuid :process_id
t.interval :duration
t.index %i[active_job_id created_at],
name: :index_good_job_executions_on_active_job_id_and_created_at
t.index %i[process_id created_at],
name: :index_good_job_executions_on_process_id_and_created_at
end
end
end
+1
View File
@@ -35,6 +35,7 @@ class Tables::GoodJobProcesses < Tables::Base
create_table migration, id: :uuid do |t|
t.timestamps
t.jsonb :state
t.integer :lock_type, limit: 2
end
end
end
+9
View File
@@ -53,6 +53,8 @@ class Tables::GoodJobs < Tables::Base
t.text :job_class
t.integer :error_event, limit: 2
t.text :labels, array: true
t.uuid :locked_by_id
t.datetime :locked_at
t.index :scheduled_at,
where: "(finished_at IS NULL)",
@@ -89,6 +91,13 @@ class Tables::GoodJobs < Tables::Base
order: { priority: "ASC NULLS LAST", created_at: :asc },
where: "finished_at IS NULL",
name: :index_good_job_jobs_for_candidate_lookup
t.index %i[priority scheduled_at],
order: { priority: "ASC NULLS LAST", scheduled_at: :asc },
where: "finished_at IS NULL AND locked_by_id IS NULL",
name: :index_good_jobs_on_priority_scheduled_at_unfinished_unlocked
t.index :locked_by_id,
where: "locked_by_id IS NOT NULL",
name: :index_good_jobs_on_locked_by_id
end
end
end
+3
View File
@@ -40,6 +40,9 @@ class Tables::HierarchicalItems < Tables::Base
t.boolean :is_deleted, default: false, null: false
t.timestamps
t.references :custom_field, foreign_key: true
t.bigint :position_cache, null: true
t.index :position_cache
end
end
end
+1
View File
@@ -42,6 +42,7 @@ class Tables::Journals < Tables::Base
t.references :data, polymorphic: true, index: false, null: false
t.jsonb :cause, default: {}
t.tstzrange :validity_period
t.boolean :restricted, default: false, null: false
t.index :journable_id
t.index :journable_type
@@ -0,0 +1,48 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
require_relative "base"
class Tables::ProjectPhaseDefinitions < Tables::Base
def self.table(migration)
create_table migration do |t|
t.string :name
t.integer :position, null: true
t.references :color, foreign_key: true
t.timestamps
t.column :start_gate, :boolean, default: false, null: false
t.column :start_gate_name, :string
t.column :finish_gate, :boolean, default: false, null: false
t.column :finish_gate_name, :string
t.index :name, unique: true
end
end
end
@@ -1,6 +1,6 @@
# frozen_string_literal: true
#-- copyright
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
@@ -26,16 +26,18 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
# ++
class CreateProjectLifeCycleStepJournals < ActiveRecord::Migration[7.1]
def change
create_table :project_life_cycle_step_journals do |t| # rubocop:disable Rails/CreateTableWithTimestamps
require_relative "base"
class Tables::ProjectPhaseJournals < Tables::Base
def self.table(migration)
create_table migration do |t| # rubocop:disable Rails/CreateTableWithTimestamps
t.belongs_to :journal, null: false, foreign_key: true
t.belongs_to :life_cycle_step, null: false
t.belongs_to :phase, null: false
t.date :start_date
t.date :end_date
t.date :finish_date
t.boolean :active, default: false, null: false
end
end
@@ -1,6 +1,6 @@
# frozen_string_literal: true
#-- copyright
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
@@ -26,30 +26,22 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
# ++
class CreateProjectLifeCycles < ActiveRecord::Migration[7.1]
def change
create_table :project_life_cycle_step_definitions do |t|
t.string :type
t.string :name
t.integer :position, null: true
t.references :color, foreign_key: true
require_relative "base"
t.timestamps
end
create_table :project_life_cycle_steps do |t|
t.string :type
t.date :start_date
t.date :end_date
class Tables::ProjectPhases < Tables::Base
def self.table(migration)
create_table migration do |t|
t.date :start_date, index: true
t.date :finish_date, index: true
t.boolean :active, default: false, null: false
t.references :project, foreign_key: true
t.references :definition, foreign_key: { to_table: :project_life_cycle_step_definitions }
t.references :definition, foreign_key: { to_table: :project_phase_definitions }
t.timestamps
end
add_reference :work_packages, :project_life_cycle_step, null: true
t.index %i[project_id definition_id], unique: true
end
end
end
@@ -28,17 +28,19 @@
# See COPYRIGHT and LICENSE files for more details.
#++
class CreateReminderNotifications < ActiveRecord::Migration[7.1]
def change
create_table :reminder_notifications do |t|
require_relative "base"
class Tables::ReminderNotifications < Tables::Base
def self.table(migration)
create_table migration do |t|
t.references :reminder, foreign_key: true
t.references :notification, foreign_key: true
t.timestamps
end
add_index :reminder_notifications, :notification_id,
t.index :notification_id,
unique: true,
name: "index_reminder_notifications_unique"
end
end
end
@@ -28,9 +28,11 @@
# See COPYRIGHT and LICENSE files for more details.
#++
class CreateReminders < ActiveRecord::Migration[7.1]
def change
create_table :reminders do |t|
require_relative "base"
class Tables::Reminders < Tables::Base
def self.table(migration)
create_table migration do |t|
t.references :remindable, polymorphic: true, null: false
t.references :creator, null: false, foreign_key: { to_table: :users }
t.datetime :remind_at, null: false
+11 -6
View File
@@ -33,13 +33,18 @@ require_relative "base"
class Tables::RemoteIdentities < Tables::Base
def self.table(migration)
create_table migration do |t|
t.references :user, index: true, null: false, foreign_key: { to_table: :users, on_delete: :cascade }
t.references :oauth_client, index: true, null: false, foreign_key: { to_table: :oauth_clients, on_delete: :cascade }
t.string :origin_user_id, null: false, index: true
t.references :user, null: false, index: false, foreign_key: { to_table: :users, on_delete: :cascade }
t.bigint :auth_source_id, null: false
t.string :origin_user_id, null: false
t.timestamps
t.index %i[user_id oauth_client_id], unique: true
t.string :auth_source_type, null: false
t.string :integration_type, null: false
t.bigint :integration_id, null: false
t.index %i[auth_source_type auth_source_id]
t.index %i[integration_type integration_id]
t.index %i[user_id auth_source_type auth_source_id integration_id integration_type],
unique: true
end
end
end
@@ -28,9 +28,11 @@
# See COPYRIGHT and LICENSE files for more details.
#++
class CreateServiceAccountAssociations < ActiveRecord::Migration[7.1]
def change
create_table :service_account_associations do |t|
require_relative "base"
class Tables::ServiceAccountAssociations < Tables::Base
def self.table(migration)
create_table migration do |t|
t.belongs_to :service_account, null: false, index: { unique: true }
t.belongs_to :service, null: false, index: false # necessary index covered by composite
t.string :service_type, null: false
+2
View File
@@ -43,6 +43,8 @@ class Tables::Types < Tables::Base
t.boolean :is_standard, default: false, null: false
t.text :attribute_groups
t.text :description
t.text :patterns, null: true
t.jsonb :pdf_export_templates_config, default: {}
end
end
end
+2 -1
View File
@@ -35,7 +35,8 @@ class Tables::UserPreferences < Tables::Base
create_table migration do |t|
t.bigint :user_id, null: false
t.jsonb :settings, default: {}
t.timestamps default: DateTime.now
t.timestamps
t.jsonb :dismissed_enterprise_banners, null: false, default: {}
t.index :user_id,
name: "index_user_preferences_on_user_id"
+3 -1
View File
@@ -51,7 +51,7 @@ class Tables::WorkPackages < Tables::Base
t.date :start_date, index: true
t.belongs_to :responsible
t.float :derived_estimated_hours
t.boolean :schedule_manually, default: false # rubocop:disable Rails/ThreeStateBooleanColumn
t.boolean :schedule_manually, default: true, null: false
t.bigint :parent_id, null: true, index: true
t.integer :duration
t.boolean :ignore_non_working_days, default: false, null: false
@@ -62,6 +62,8 @@ class Tables::WorkPackages < Tables::Base
t.index :schedule_manually, where: :schedule_manually
t.check_constraint "due_date >= start_date", name: "work_packages_due_larger_start_date"
t.references :project_phase, foreign_key: false, null: true
end
end
end
@@ -38,16 +38,10 @@ require_relative "tables/time_entry_journals"
class AggregatedCostsMigrations < SquashedMigration
squashed_migrations *%w[
20180323133404_to_v710_aggregated_costs_migrations
20200327074416_rename_fixed_version_in_cost_query
20200807083952_rename_time_and_cost_module
20210726065912_rename_cost_object_type
20201001184404_rename_timestamp_on_time_and_cost_entry
20220608213712_add_logged_by_id_to_time_entries
20220707192304_backfill_time_entries_with_logged_by_id
20220815072420_add_logged_by_to_time_entries_journals
20221018160449_add_logged_by_to_cost_entries
20230622074222_add_ongoing_to_time_entry
1009015_aggregated_costs_migrations
20241120103858_add_start_end_times_to_time_entries
20241125104347_add_timezone_identifier_to_time_entry
20250219103939_make_time_entry_comment_text_field
].freeze
tables Tables::CostEntries,
@@ -1,36 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class MakeTimeEntryCommentTextField < ActiveRecord::Migration[7.1]
def up
change_column :time_entries, :comments, :text
change_column :time_entry_journals, :comments, :text
end
end
@@ -37,7 +37,7 @@ class Tables::TimeEntries < Tables::Base
t.bigint :user_id, null: false
t.belongs_to :work_package, index: false
t.float :hours, null: true
t.string :comments
t.text :comments
t.bigint :activity_id, null: true
t.date :spent_on, null: false
t.integer :tyear, null: false
@@ -49,6 +49,8 @@ class Tables::TimeEntries < Tables::Base
t.bigint :rate_id
t.references :logged_by, foreign_key: { to_table: :users }, index: true, null: false
t.boolean :ongoing, null: false, default: false, index: true
t.integer :start_time, null: true
t.string :time_zone, null: true
t.index :activity_id, name: "index_time_entries_on_activity_id"
t.index :created_at, name: "index_time_entries_on_created_at"
@@ -31,7 +31,7 @@
require Rails.root.join("db/migrate/tables/base").to_s
class Tables::TimeEntryJournals < Tables::Base
def self.table(migration)
def self.table(migration) # rubocop:disable Metrics/AbcSize
create_table migration do |t|
t.bigint :project_id, null: false, index: true
t.bigint :user_id, null: false
@@ -47,6 +47,8 @@ class Tables::TimeEntryJournals < Tables::Base
t.decimal :costs, precision: 15, scale: 2, null: true
t.bigint :rate_id
t.references :logged_by, foreign_key: { to_table: :users }, index: true, null: false
t.integer :start_time, null: true
t.string :time_zone, null: true
end
end
end
@@ -34,23 +34,14 @@ Dir[File.join(__dir__, "tables/*.rb")].each { |file| require file }
class AggregatedMeetingMigrations < SquashedMigration
squashed_migrations *%w[
20180323135408_to_v710_aggregated_meeting_migrations
20230816141222_create_meeting_agenda_items
20230823113310_add_work_package_to_meeting_agenda_items
20230829122717_add_state_to_meetings
20230911102918_add_type_to_meeting
20230918135247_change_meeting_agenda_item_description_to_notes
20231003151656_create_meeting_agenda_item_journals
20231012124745_add_item_type_to_meeting_agenda_items
20231013114720_add_item_type_to_meeting_agenda_item_journal
20231020154219_add_trgm_index_to_meeting_agenda_item_notes
20231025144701_migrate_agenda_item_permissions
20231119192222_add_locking_to_meeting
20240313102951_add_presenter_to_meeting
20240405131352_create_meeting_sections
20240408161233_add_state_to_meeting_journal
20240418110249_set_author_as_presenter
20240516102219_fix_untitled_meetings
1003015_aggregated_meeting_migrations
20250318123314_add_backlog_to_meeting_sections
20240426073948_create_recurring_meetings
20241122143600_add_interval_to_recurring_meeting
20241128190428_create_scheduled_meetings
20250211185841_create_meeting_outcomes
20250227140619_change_unique_constraint_on_scheduled_meetings
20250304082924_add_time_zone_to_recurring_meetings
].freeze
tables Tables::MeetingContents,
@@ -60,5 +51,17 @@ class AggregatedMeetingMigrations < SquashedMigration
Tables::MeetingContentJournals,
Tables::MeetingSections,
Tables::MeetingAgendaItems,
Tables::MeetingAgendaItemJournals
Tables::MeetingAgendaItemJournals,
Tables::RecurringMeetings,
Tables::ScheduledMeetings,
Tables::MeetingOutcomes
modifications do
# There's no easy way to express deferrable unique constraints in Rails migrations
execute <<~SQL.squish
ALTER TABLE scheduled_meetings
ADD CONSTRAINT unique_recurring_meeting_start_time
UNIQUE (recurring_meeting_id, start_time) DEFERRABLE INITIALLY DEFERRED;
SQL
end
end
@@ -1,21 +0,0 @@
# frozen_string_literal: true
class CreateRecurringMeetings < ActiveRecord::Migration[7.1]
def change
create_table :recurring_meetings do |t|
t.datetime :start_time
t.date :end_date, null: true
t.text :title
t.integer :frequency, default: 0, null: false
t.integer :end_after, default: 0, null: false
t.integer :iterations, null: true
t.belongs_to :project, foreign_key: true, index: true
t.belongs_to :author, foreign_key: { to_table: :users }
t.timestamps
end
add_reference :meetings, :recurring_meeting, index: true
add_column :meetings, :template, :boolean, default: false, null: false
end
end
@@ -1,7 +0,0 @@
# frozen_string_literal: true
class AddIntervalToRecurringMeeting < ActiveRecord::Migration[7.1]
def change
add_column :recurring_meetings, :interval, :integer,
default: 1, null: false
end
end
@@ -1,23 +0,0 @@
# frozen_string_literal: true
class CreateScheduledMeetings < ActiveRecord::Migration[7.1]
def change
create_table :scheduled_meetings do |t|
t.belongs_to :recurring_meeting,
null: false,
foreign_key: { index: true, on_delete: :cascade }
t.belongs_to :meeting,
null: true,
foreign_key: { index: true, unique: true, on_delete: :nullify }
t.datetime :start_time, null: false
t.boolean :cancelled, default: false, null: false
t.timestamps
end
add_index :scheduled_meetings,
%i[recurring_meeting_id start_time],
unique: true
end
end
@@ -1,53 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class ChangeUniqueConstraintOnScheduledMeetings < ActiveRecord::Migration[6.0]
def up
remove_index :scheduled_meetings,
%i[recurring_meeting_id start_time],
unique: true
execute <<~SQL.squish
ALTER TABLE scheduled_meetings
ADD CONSTRAINT unique_recurring_meeting_start_time
UNIQUE (recurring_meeting_id, start_time) DEFERRABLE INITIALLY DEFERRED;
SQL
end
def down
execute <<~SQL.squish
ALTER TABLE scheduled_meetings
DROP CONSTRAINT unique_recurring_meeting_start_time;
SQL
add_index :scheduled_meetings,
%i[recurring_meeting_id start_time],
unique: true
end
end
@@ -1,53 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddTimeZoneToRecurringMeetings < ActiveRecord::Migration[7.1]
def change
add_column :recurring_meetings, :time_zone, :string, null: true
reversible do |dir|
dir.up do
execute <<-SQL.squish
UPDATE recurring_meetings
SET time_zone = COALESCE(
(
SELECT (user_preferences.settings->>'time_zone')
FROM user_preferences
WHERE user_preferences.user_id = recurring_meetings.author_id
LIMIT 1
),
'Etc/UTC'
)
SQL
end
end
change_column_null :recurring_meetings, :time_zone, false
end
end
@@ -1,6 +1,6 @@
# frozen_string_literal: true
#-- copyright
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
@@ -26,12 +26,13 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
#
# ++
class CreateMeetingOutcomes < ActiveRecord::Migration[7.1]
def change
create_table :meeting_outcomes do |t|
require Rails.root.join("db/migrate/tables/base").to_s
class Tables::MeetingOutcomes < Tables::Base
def self.table(migration)
create_table migration do |t|
t.text :notes
t.belongs_to :meeting_agenda_item, foreign_key: true
t.belongs_to :work_package, foreign_key: true
@@ -36,8 +36,8 @@ class Tables::MeetingSections < Tables::Base
t.integer :position
t.string :title
t.references :meeting, null: false, foreign_key: true
t.timestamps
t.boolean :backlog, default: false, null: false
end
end
end
@@ -43,6 +43,8 @@ class Tables::Meetings < Tables::Base
t.integer :state, default: 0, null: false
t.integer :lock_version, default: 0, null: false
t.string :type, default: "Meeting", null: false
t.references :recurring_meeting, index: true
t.boolean :template, default: false, null: false
t.index %i[project_id updated_at]
end
@@ -0,0 +1,51 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
require Rails.root.join("db/migrate/tables/base").to_s
class Tables::RecurringMeetings < Tables::Base
def self.table(migration)
create_table migration do |t|
t.datetime :start_time
t.date :end_date, null: true
t.text :title
t.integer :frequency, default: 0, null: false
t.integer :end_after, default: 0, null: false
t.integer :iterations, null: true
t.belongs_to :project, foreign_key: true, index: true
t.belongs_to :author, foreign_key: { to_table: :users }
t.timestamps
t.integer :interval, default: 1, null: false
t.string :time_zone, null: false
end
end
end
@@ -0,0 +1,50 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
require Rails.root.join("db/migrate/tables/base").to_s
class Tables::ScheduledMeetings < Tables::Base
def self.table(migration)
create_table migration do |t|
t.belongs_to :recurring_meeting,
null: false,
foreign_key: { index: true, on_delete: :cascade }
t.belongs_to :meeting,
null: true,
foreign_key: { index: true, unique: true, on_delete: :nullify }
t.datetime :start_time, null: false
t.boolean :cancelled, default: false, null: false
t.timestamps
end
end
end
@@ -30,12 +30,15 @@
require Rails.root.join("db/migrate/migration_utils/squashed_migration").to_s
require_relative "tables/oidc_user_session_links"
require_relative "tables/oidc_user_tokens"
class AggregatedOpenIDConnectMigrations < SquashedMigration
tables Tables::OidcUserSessionLinks
tables Tables::OidcUserSessionLinks,
Tables::OidcUserTokens
squashed_migrations *%w[
20221122072857_add_oidc_session_link
20240829140616_migrate_oidc_settings_to_providers
1018015_aggregated_openid_connect_migrations
20241212131910_add_oidc_user_tokens
20250218133700_add_expires_at_to_oidc_user_tokens
]
end
@@ -1,35 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class AddExpiresAtToOidcUserTokens < ActiveRecord::Migration[7.1]
def change
add_column :oidc_user_tokens, :expires_at, :datetime, null: true, precision: 0
end
end
@@ -1,6 +1,6 @@
# frozen_string_literal: true
#-- copyright
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
@@ -26,11 +26,13 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
# ++
class AddOidcUserTokens < ActiveRecord::Migration[7.1]
def change
create_table :oidc_user_tokens do |t|
require Rails.root.join("db/migrate/tables/base").to_s
class Tables::OidcUserTokens < Tables::Base
def self.table(migration)
create_table migration do |t|
t.references :user, null: false, index: true, foreign_key: { on_delete: :cascade }
t.string :access_token, null: false
@@ -38,6 +40,8 @@ class AddOidcUserTokens < ActiveRecord::Migration[7.1]
t.jsonb :audiences, null: false, default: []
t.timestamps
t.datetime :expires_at, null: true, precision: 0
end
end
end
@@ -1,66 +0,0 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
require Rails.root.join("db/migrate/migration_utils/squashed_migration").to_s
require Rails.root.join("db/migrate/tables/base").to_s
Dir[File.join(__dir__, "tables/*.rb")].each { |file| require file }
class AggregatedStoragesMigrations < SquashedMigration
squashed_migrations *%w[
20220113144323_create_storage
20220113144759_create_file_links
20220121090847_create_projects_storages
20220712165928_add_storages_permissions_to_roles
20230123092649_make_containter_id_and_containter_type_optional_for_file_links
20230321194150_add_project_folder_to_projects_storages
20230420063148_add_provider_fields_to_storages
20230420071113_migrate_storages_to_use_provider_type_as_sti_column
20230512153303_change_storage_provider_fields_default
20230517075214_add_automatic_to_project_folder_modes
20230601082746_create_last_project_folders
20230713144232_create_storages_file_link_journals
20230721123022_remove_project_folder_mode_default
20230802085026_rename_projects_storages_table
20230824130730_remove_not_null_constraint_for_storage_host
20231009135807_remove_renamed_cronjobs
20231109080454_add_health_info_to_storages
20231208143303_add_health_checked_at_to_storages
20240405135016_update_access_management_of_configured_one_drive_storages
20240610130953_rename_manage_storages_in_project_permission
20230725165505_add_storage_name_to_storages_file_links_journals
20230731153909_add_file_link_journals_to_existing_containers
].freeze
tables Tables::Storages,
Tables::FileLinks,
Tables::ProjectStorages,
Tables::LastProjectFolders,
Tables::StoragesFileLinksJournals
end
@@ -1,6 +1,6 @@
# frozen_string_literal: true
#-- copyright
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
@@ -26,16 +26,21 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
# ++
require Rails.root.join("db/migrate/migration_utils/permission_adder")
require Rails.root.join("db/migrate/migration_utils/squashed_migration").to_s
require Rails.root.join("db/migrate/tables/base").to_s
Dir[File.join(__dir__, "tables/*.rb")].each { |file| require file }
class AddProjectLifeCycleStepRoles < ActiveRecord::Migration[7.1]
def change
::Migration::MigrationUtils::PermissionAdder
.add(:view_project, :view_project_stages_and_gates, force: true)
class AggregatedStoragesMigrations < SquashedMigration
squashed_migrations *%w[
1017015_aggregated_storages_migrations
20250115100336_set_default_authentication_method
].freeze
::Migration::MigrationUtils::PermissionAdder
.add(:edit_project, :edit_project_stages_and_gates, force: true)
end
tables Tables::Storages,
Tables::FileLinks,
Tables::ProjectStorages,
Tables::LastProjectFolders,
Tables::StoragesFileLinksJournals
end
@@ -1,46 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class SetDefaultAuthenticationMethod < ActiveRecord::Migration[7.1]
def up
update_sql = <<~SQL.squish
UPDATE storages
SET provider_fields = provider_fields || '{ "authentication_method": "two_way_oauth2" }'::jsonb
WHERE provider_type = 'Storages::NextcloudStorage' AND NOT provider_fields ? 'authentication_method'
SQL
ActiveRecord::Base.connection.execute(update_sql)
end
def down
# up-direction is backwards-compatible, no need to restrict a migration rollback
# but also nothing to do in case of a rollback
end
end
@@ -1,137 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require "spec_helper"
require Rails.root.join("db/migrate/20241126111225_add_project_life_cycle_step_roles.rb")
RSpec.describe AddProjectLifeCycleStepRoles, type: :model do
# Silencing migration logs, since we are not interested in that during testing
subject { ActiveRecord::Migration.suppress_messages { described_class.new.change } }
shared_examples_for "not changing permissions" do
it "is not changed" do
expect { subject }.not_to change { role.reload.permissions }
end
it "does not adds any new permissions" do
expect { subject }.not_to change(RolePermission, :count)
end
end
shared_examples_for "migration is idempotent" do
context "when the migration is ran twice" do
before { subject }
it_behaves_like "not changing permissions"
end
end
shared_examples_for "adding permissions" do |new_permissions|
it "adds the #{new_permissions} permissions for the role" do
public_permissions = OpenProject::AccessControl.public_permissions.map(&:name)
expect { subject }.to change { role.reload.permissions }
.from(match_array(permissions + public_permissions))
.to match_array(permissions + public_permissions + new_permissions)
end
it "adds #{new_permissions.size} new permissions" do
expect { subject }.to change(RolePermission, :count).by(new_permissions.size)
end
end
context "for a role not eligible to view_project_stages_and_gates" do
let!(:role) do
create(:project_role,
add_public_permissions: false,
permissions: %i[permission1 permission2])
end
it_behaves_like "not changing permissions"
it_behaves_like "migration is idempotent"
end
context "for a role eligible to view_project_stages_and_gates" do
let(:permissions) { %i[view_project permission1 permission2] }
let!(:role) { create(:project_role, permissions:) }
it_behaves_like "adding permissions", %i[view_project_stages_and_gates]
it_behaves_like "migration is idempotent"
end
context "for a role with view_project_stages_and_gates" do
let(:permissions) { %i[view_project_stages_and_gates view_project permission1 permission2] }
let!(:role) { create(:project_role, permissions:) }
it_behaves_like "not changing permissions"
it_behaves_like "migration is idempotent"
end
context "for a role not eligible to edit_project_stages_and_gates" do
let(:permissions) do
%i[view_project_stages_and_gates permission1 permission2]
end
let!(:role) { create(:project_role, permissions:) }
it_behaves_like "not changing permissions"
it_behaves_like "migration is idempotent"
end
context "for a role eligible to edit_project_stages_and_gates having view_project_stages_and_gates" do
let(:permissions) do
%i[view_project_stages_and_gates edit_project
view_project permission1 permission2]
end
let!(:role) { create(:project_role, permissions:) }
it_behaves_like "adding permissions", %i[edit_project_stages_and_gates]
it_behaves_like "migration is idempotent"
end
context "for a role eligible to edit_project_stages_and_gates not having view_project_stages_and_gates" do
let(:permissions) do
%i[edit_project view_project permission1 permission2]
end
let!(:role) { create(:project_role, permissions:) }
it_behaves_like "adding permissions", %i[edit_project_stages_and_gates view_project_stages_and_gates]
it_behaves_like "migration is idempotent"
end
context "for a role that already has the edit_project_stages_and_gates and view_project_stages_and_gates permission" do
let(:permissions) do
%i[edit_project_stages_and_gates view_project_stages_and_gates
edit_project view_project permission1 permission2]
end
let!(:role) { create(:project_role, permissions:) }
it_behaves_like "not changing permissions"
it_behaves_like "migration is idempotent"
end
end
@@ -1,58 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require "spec_helper"
require Rails.root.join("db/migrate/20250102161733_adds_position_cache_to_hierarchy_items.rb")
RSpec.describe AddsPositionCacheToHierarchyItems, type: :model, with_ee: [:custom_field_hierarchies] do
let(:custom_field) { create(:hierarchy_wp_custom_field, hierarchy_root: nil) }
let(:service) { CustomFields::Hierarchy::HierarchicalItemService.new }
let(:contract_class) { CustomFields::Hierarchy::InsertListItemContract }
it "backfills the position_cache value on already existing hierarchy items" do
ActiveRecord::Migration.suppress_messages { described_class.new.down }
root = service.generate_root(custom_field).value!
anakin = service.insert_item(contract_class:, label: "luke", parent: root).value!
chewie = service.insert_item(contract_class:, label: "chewbacca", parent: root).value!
luke = service.insert_item(contract_class:, label: "luke", parent: anakin).value!
leia = service.insert_item(contract_class:, label: "leia", parent: anakin).value!
expect(root.self_and_descendants_preordered).to eq([root, anakin, luke, leia, chewie])
ActiveRecord::Migration.suppress_messages { described_class.new.up }
expect(root.reload.position_cache).to eq(125)
expect(anakin.reload.position_cache).to eq(150)
expect(luke.reload.position_cache).to eq(155)
expect(leia.reload.position_cache).to eq(160)
expect(chewie.reload.position_cache).to eq(175)
end
end
@@ -1,165 +0,0 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
require "spec_helper"
require Rails.root.join("db/migrate/20250324161229_merge_lifecycle_steps.rb")
require Rails.root.join("db/migrate/20250403150639_link_wp_to_project_phase_definition.rb")
RSpec.describe MergeLifecycleSteps, type: :model do
shared_let(:colors) { create_list(:color, 3) }
shared_let(:project) { create(:project) }
shared_let(:project_journal) { project.journals.first }
before do
ActiveRecord::Migration.suppress_messages do
# This tested migration depends on the existence of the
# project_phase_id column in the work_packages table.
# That is why the migration renaming it needs to be rolled back first.
LinkWpToProjectPhaseDefinition.new.migrate(:down)
described_class.new.migrate(:down)
end
ActiveRecord::Base.connection.execute(
<<-SQL.squish
INSERT INTO project_life_cycle_step_definitions (id, type, name, position, color_id, created_at, updated_at)
VALUES
(1, 'Project::StageDefinition', 'Initiating', 1, #{colors.first.id}, NOW(), NOW()),
(2, 'Project::GateDefinition', 'Ready for Executing', 2, #{colors.second.id}, NOW(), NOW()),
(3, 'Project::StageDefinition', 'Executing', 3, #{colors.third.id}, NOW(), NOW())
SQL
)
ActiveRecord::Base.connection.execute(
<<-SQL.squish
INSERT INTO project_life_cycle_steps (id, type, start_date, end_date, active, project_id, definition_id, created_at, updated_at)
VALUES
(1, 'Project::Stage', '#{Time.zone.today}', '#{Time.zone.today + 5.days}', true, #{project.id}, 1, NOW(), NOW()),
(2, 'Project::Gate', '#{Time.zone.today + 5.days}', '#{Time.zone.today + 5.days}', true, #{project.id}, 2, NOW(), NOW()),
(3, 'Project::Stage', '#{Time.zone.today + 6.days}', '#{Time.zone.today + 15.days}', false, #{project.id}, 3, NOW(), NOW())
SQL
)
ActiveRecord::Base.connection.execute(
<<-SQL.squish
INSERT INTO project_life_cycle_step_journals (journal_id, life_cycle_step_id, start_date, end_date, active)
VALUES
(#{project_journal.id}, 1, '#{Time.zone.today}', '#{Time.zone.today + 5.days}', true),
(#{project_journal.id}, 2, '#{Time.zone.today + 5.days}', '#{Time.zone.today + 5.days}', true),
(#{project_journal.id}, 3, '#{Time.zone.today + 6.days}', '#{Time.zone.today + 15.days}', false)
SQL
)
# Need to be after the life cycle steps are created
query_without_lifecycle
query_with_lifecycle_any_filter
query_with_lifecycle_order
query_with_lifecycle_select
query_with_lifecycle_gate_filter
query_with_lifecycle_stage_filter
end
let(:query_without_lifecycle) { create(:project_query) }
let(:query_with_lifecycle_select) do
create(:project_query).tap do |q|
q.update_column(:selects,
[instance_double(Queries::Selects::Base, attribute: "name"),
instance_double(Queries::Selects::Base, attribute: "lcsd_2"),
instance_double(Queries::Selects::Base, attribute: "project_status")])
end
end
let(:query_with_lifecycle_order) do
create(:project_query).tap do |q|
q.update_column(:orders, [instance_double(Queries::Orders::Base, attribute: "lcsd_3", direction: "desc")])
end
end
let(:query_with_lifecycle_any_filter) do
create(:project_query).tap do |q|
q.update_column(:filters, [instance_double(Queries::Filters::Base, field: "lcsd_any", operator: "", values: [])])
end
end
let(:query_with_lifecycle_gate_filter) do
create(:project_query).tap do |q|
q.update_column(:filters, [instance_double(Queries::Filters::Base, field: "lcsd_gate_2", operator: "", values: [])])
end
end
let(:query_with_lifecycle_stage_filter) do
create(:project_query).tap do |q|
q.update_column(:filters, [instance_double(Queries::Filters::Base, field: "lcsd_stage_1", operator: "", values: [])])
end
end
subject { ActiveRecord::Migration.suppress_messages { described_class.new.migrate(:up) } }
it "removes all project life cycle steps and renames the table" do
expect(ActiveRecord::Base.connection.select_one("SELECT COUNT(*) FROM project_life_cycle_steps")["count"])
.to eq 3
subject
expect(ActiveRecord::Base.connection.table_exists?("project_life_cycle_steps"))
.to be false
expect(ActiveRecord::Base.connection.select_one("SELECT COUNT(*) FROM project_phases")["count"])
.to eq 0
end
it "removes all project life cycle step definitions and renames the table" do
expect(ActiveRecord::Base.connection.select_one("SELECT COUNT(*) FROM project_life_cycle_step_definitions")["count"])
.to eq 3
subject
expect(ActiveRecord::Base.connection.table_exists?("project_life_cycle_step_definitions"))
.to be false
expect(ActiveRecord::Base.connection.select_one("SELECT COUNT(*) FROM project_phase_definitions")["count"])
.to eq 0
end
it "removes all project life cycle step journal entries but leaves the journal - the step journal table is removed" do
expect(ActiveRecord::Base.connection.select_one("SELECT COUNT(*) FROM project_life_cycle_step_journals")["count"])
.to eq 3
subject
expect(ActiveRecord::Base.connection.table_exists?("project_life_cycle_step_journals"))
.to be false
expect(ActiveRecord::Base.connection.select_one("SELECT COUNT(*) FROM project_phase_journals")["count"])
.to eq 0
expect(Journal)
.to exist(id: project_journal.id)
end
it "removes all queries with life cycle references in order, select or filters" do
expect { subject }
.to(change(ProjectQuery, :count).from(6).to(1))
expect(ProjectQuery)
.to exist(id: query_without_lifecycle.id)
end
end
@@ -1,71 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require "spec_helper"
require Rails.root.join("db/migrate/20250108100511_remove_incorrect_manage_own_reminders_permission.rb")
RSpec.describe RemoveIncorrectManageOwnRemindersPermission, type: :model do
let(:permissions) { %i[permission1 permission2 manage_own_reminders] }
let(:non_member) { create(:non_member, permissions:) }
let(:anonymous) { create(:anonymous_role, permissions:) }
let(:other_role) { create(:work_package_role, permissions:) }
let(:anonymous_user_reminder) do
create(:reminder, :with_unread_notifications, creator: AnonymousUser.first)
end
let(:normal_user_reminder) { create(:reminder, :with_unread_notifications) }
it "removes the `manage_own_reminders` permission from non member and anonymous roles" do
expect(non_member.permissions).to include(:manage_own_reminders)
expect(anonymous.permissions).to include(:manage_own_reminders)
expect(other_role.permissions).to include(:manage_own_reminders)
expect(anonymous_user_reminder).to be_persisted
expect(normal_user_reminder.creator).to be_persisted
expect do
ActiveRecord::Migration.suppress_messages { described_class.migrate(:up) }
end.to(
change(RolePermission, :count).by(-2) &
change(Reminder, :count).by(-1) &
change(ReminderNotification, :count).by(-1) &
change(Notification, :count).by(-1)
)
expect(non_member.reload.permissions).not_to include(:manage_own_reminders)
expect(anonymous.reload.permissions).not_to include(:manage_own_reminders)
expect(other_role.reload.permissions).to include(:manage_own_reminders)
reminder_creators = Reminder.pluck(:creator_id)
expect(reminder_creators).not_to include(AnonymousUser.first.id)
expect(reminder_creators).to include(normal_user_reminder.creator_id)
end
end
@@ -1,314 +0,0 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require "spec_helper"
require Rails.root.join("db/migrate/20241120095318_update_scheduling_mode_and_lags.rb")
RSpec.describe UpdateSchedulingModeAndLags, type: :model do
# Silencing migration logs, since we are not interested in that during testing
subject(:run_migration) do
perform_enqueued_jobs do
ActiveRecord::Migration.suppress_messages { described_class.new.up }
end
table_work_packages.map(&:reload) if defined?(table_work_packages)
end
shared_let(:author) { create(:user) }
shared_let(:priority) { create(:priority, name: "Normal") }
shared_let(:project) { create(:project, name: "Main project") }
shared_let(:status_new) { create(:status, name: "New") }
before_all do
set_factory_default(:user, author)
set_factory_default(:priority, priority)
set_factory_default(:project, project)
set_factory_default(:project_with_types, project)
set_factory_default(:status, status_new)
end
describe "journal creation" do
context "when scheduling mode is changed by the migration" do
let_work_packages(<<~TABLE)
subject | scheduling mode
wp already manual | manual
wp automatic | automatic
TABLE
it "creates a journal entry only for the changed work packages" do
expect(wp_already_manual.journals.count).to eq(1)
expect(wp_automatic.journals.count).to eq(1)
expect(wp_automatic.lock_version).to eq(0)
run_migration
expect(wp_already_manual.journals.count).to eq(1)
expect(wp_automatic.journals.count).to eq(2)
expect(wp_automatic.last_journal.get_changes)
.to include("schedule_manually" => [false, true],
"cause" => [nil, { "feature" => "scheduling_mode_adjusted", "type" => "system_update" }])
aggregate_failures "the journal author is the system user" do
journal = wp_automatic.last_journal
expect(journal.user).to eq(User.system)
end
aggregate_failures "the lock_version of the work package is incremented" do
expect(wp_automatic.lock_version).to be > 0
end
aggregate_failures "changes the updated_at of the work package" do
expect(wp_automatic.updated_at).not_to eq(wp_automatic.created_at)
expect(wp_automatic.updated_at).to be > wp_automatic.created_at
first_journal, last_journal = wp_automatic.journals
expect(wp_automatic.updated_at).not_to eq(first_journal.updated_at)
expect(wp_automatic.updated_at).to eq(last_journal.updated_at)
end
end
end
end
# spec from #59539, "Migration from an earlier version" section:
#
# > - For work packages with no predecessors (or with no relations at all), they will be
# > switched to manual scheduling.
context "for work packages with no predecessors nor children" do
let_work_packages(<<~TABLE)
subject | start date | due date | scheduling mode
wp automatic 1 | 2024-11-20 | 2024-11-21 | automatic
wp automatic 2 | | 2024-11-21 | automatic
wp automatic 3 | 2024-11-20 | | automatic
wp automatic 4 | | | automatic
wp manual 1 | 2024-11-20 | 2024-11-21 | manual
wp manual 2 | | 2024-11-21 | manual
wp manual 3 | 2024-11-20 | | manual
wp manual 4 | | | manual
TABLE
it "switches to manual scheduling" do
run_migration
expect(table_work_packages).to all(be_schedule_manually)
end
end
# spec from #59539, "Migration from an earlier version" section:
#
# > - Manually scheduled work packages remain so.
context "for manually scheduled work packages following another one" do
let_work_packages(<<~TABLE)
subject | start date | due date | scheduling mode | predecessors
main | | | manual |
wp 1 | 2024-11-20 | 2024-11-21 | manual | follows main
wp 2 | | 2024-11-21 | manual | follows main
wp 3 | 2024-11-20 | | manual | follows main
wp 4 | | | manual | follows main
TABLE
it "remains manually scheduled" do
run_migration
expect(table_work_packages).to all(be_schedule_manually)
end
end
# spec from #59539, "Migration from an earlier version" section
#
# > - If the successor is in automatic scheduling mode, has dates and some predecessors
# > have dates too:
# > - The successor remains in automatic mode
context "for automatically scheduled work packages following another one having dates" do
let_work_packages(<<~TABLE)
subject | start date | due date | scheduling mode | predecessors
pred with dates | 2024-11-19 | 2024-11-19 | manual |
pred without dates | | | manual |
wp 1 | 2024-11-20 | 2024-11-21 | automatic | follows pred with dates, follows pred without dates
wp 2 | | 2024-11-21 | automatic | follows pred with dates, follows pred without dates
wp 3 | 2024-11-20 | | automatic | follows pred with dates, follows pred without dates
wp 4 | | | automatic | follows pred with dates, follows pred without dates
TABLE
it "remains automatically scheduled" do
run_migration
expect([wp1, wp2, wp3, wp4]).to all(be_schedule_automatically)
end
end
# spec from #59539, "Migration from an earlier version" section
# > - If the successor is in automatic scheduling mode and has no dates
# > - The successor remains in automatic mode and continues to have no dates,
# > regardless of having predecessor with dates or not.
# > - If the successor is in automatic scheduling mode, has dates and none of the
# > predecessors have any dates
# > - The successor is switched to manual mode to preserve its dates and duration
context "for automatically scheduled work packages without dates following another one" do
let_work_packages(<<~TABLE)
subject | start date | due date | scheduling mode | predecessors
pred without dates | | | manual |
succ | | | automatic | follows pred without dates
TABLE
it "remains automatically scheduled and continues to have no dates" do
run_migration
expect(succ).to be_schedule_automatically
end
end
# spec from #59539, "Migration from an earlier version" section
#
# > - If the successor is in automatic scheduling mode, has dates and none of the
# > predecessors have any dates
# > - The successor is switched to manual mode to preserve its dates and duration
context "for automatically scheduled work packages following another one having no dates" do
let_work_packages(<<~TABLE)
subject | start date | due date | scheduling mode | predecessors
pred without dates | | | manual |
succ 1 | 2024-11-20 | 2024-11-21 | automatic | follows pred without dates
succ 2 | | 2024-11-21 | automatic | follows pred without dates
succ 3 | 2024-11-20 | | automatic | follows pred without dates
TABLE
it "switches to manual scheduling to preserve its dates and duration" do
run_migration
expect([succ1, succ2, succ3]).to all(be_schedule_manually)
end
end
# spec from #42388, "Migration from an earlier version" section
#
# > - Manually scheduled work packages remain so.
# > - If the relationship is parent-child, there are no changes to dates; the parent
# > remains in automatic mode.
context "for parent work packages" do
let_work_packages(<<~TABLE)
hierarchy | scheduling mode |
parent_automatic | automatic |
child1 | manual |
parent_manual | manual |
child2 | manual |
TABLE
it "keep their scheduling mode" do
run_migration
expect(parent_automatic).to be_schedule_automatically
expect(parent_manual).to be_schedule_manually
end
end
context "for 2 work packages following each other with distant dates" do
shared_let_work_packages(<<~TABLE)
subject | MTWTFSS | scheduling mode | predecessors
predecessor 1 | XX | manual |
follower 1 | XX | automatic | follows predecessor 1
# only start dates
predecessor 2 | [ | manual |
follower 2 | [ | automatic | follows predecessor 2
# only due dates
# if lag is already set, it's overwritten
predecessor 3 | ] | manual |
follower 3 | ] | automatic | follows predecessor 3 with lag 2
TABLE
it "sets a lag to the relation to ensure the distance is kept" do
run_migration
expect(follower1).to be_schedule_automatically
relations = _table.relations.map(&:reload)
expect(relations.map(&:lag)).to all(eq(3))
end
context "when there are non-working days between the dates" do
before do
# Wednesday is a recurring non-working day
set_non_working_week_days("wednesday")
# Thursday is a fixed non-working day
thursday = Date.current.next_occurring(:monday) + 3.days
create(:non_working_day, date: thursday)
end
it "computes the lag correctly by excluding non-working days" do
run_migration
expect(follower1).to be_schedule_automatically
relations = _table.relations.map(&:reload)
expect(relations.map(&:lag)).to all(eq(1))
end
end
end
context "for 2 work packages following each other with missing dates" do
let_work_packages(<<~TABLE)
subject | MTWTFSS | scheduling mode | predecessors
# only predecessor has dates
predecessor 1 | XX | manual |
follower 1 | | automatic | follows predecessor 1
# only successor has dates
predecessor 2 | | manual |
follower 2 | XX | automatic | follows predecessor 2
# none have dates
predecessor 3 | | manual |
follower 3 | | automatic | follows predecessor 3 with lag 2
TABLE
it "does not change the existing lag" do
run_migration
expect(follower1).to be_schedule_automatically
relations = _table.relations.map(&:reload)
expect(relations.map(&:lag)).to eq([0, 0, 2])
end
end
context "for a work package following multiple work packages" do
shared_let_work_packages(<<~TABLE)
subject | MTWTFSS | scheduling mode | predecessors
predecessor 1 | XX | manual |
predecessor 2 | XX | manual |
predecessor 3 | X | manual |
follower | XX | automatic | follows predecessor 1, follows predecessor 2, follows predecessor 3
TABLE
it "sets a lag only to the closest relation" do
run_migration
relations = _table.relations.map(&:reload)
expect(relations.map(&:lag)).to eq([0, 2, 0])
end
end
end