From 3d976f1b3b69b181f29b1035314a9eb2940e2ec1 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 22 Nov 2020 21:20:06 +0100 Subject: [PATCH] Redmine 4.1.1 --- .rubocop.yml | 103 + .rubocop_todo.yml | 1637 +++++++++++++++ CONTRIBUTING.md | 10 +- Gemfile | 86 +- app/controllers/account_controller.rb | 20 +- app/controllers/activities_controller.rb | 17 +- app/controllers/admin_controller.rb | 19 +- app/controllers/application_controller.rb | 89 +- app/controllers/attachments_controller.rb | 41 +- app/controllers/auth_sources_controller.rb | 29 +- app/controllers/auto_completes_controller.rb | 33 +- app/controllers/boards_controller.rb | 7 +- app/controllers/calendars_controller.rb | 4 +- app/controllers/comments_controller.rb | 4 +- app/controllers/context_menus_controller.rb | 10 +- .../custom_field_enumerations_controller.rb | 4 +- app/controllers/custom_fields_controller.rb | 10 +- app/controllers/documents_controller.rb | 9 +- app/controllers/email_addresses_controller.rb | 4 +- app/controllers/enumerations_controller.rb | 8 +- app/controllers/files_controller.rb | 14 +- app/controllers/gantts_controller.rb | 4 +- app/controllers/groups_controller.rb | 4 +- app/controllers/imports_controller.rb | 64 +- .../issue_categories_controller.rb | 4 +- app/controllers/issue_relations_controller.rb | 4 +- app/controllers/issue_statuses_controller.rb | 8 +- app/controllers/issues_controller.rb | 48 +- app/controllers/journals_controller.rb | 7 +- app/controllers/mail_handler_controller.rb | 6 +- app/controllers/members_controller.rb | 4 +- app/controllers/messages_controller.rb | 18 +- app/controllers/my_controller.rb | 30 +- app/controllers/news_controller.rb | 47 +- app/controllers/previews_controller.rb | 28 +- .../principal_memberships_controller.rb | 6 +- .../project_enumerations_controller.rb | 23 +- app/controllers/projects_controller.rb | 62 +- app/controllers/queries_controller.rb | 21 +- app/controllers/reports_controller.rb | 45 +- app/controllers/repositories_controller.rb | 100 +- app/controllers/roles_controller.rb | 28 +- app/controllers/search_controller.rb | 20 +- app/controllers/settings_controller.rb | 8 +- app/controllers/sys_controller.rb | 8 +- app/controllers/timelog_controller.rb | 36 +- app/controllers/trackers_controller.rb | 6 +- app/controllers/users_controller.rb | 28 +- app/controllers/versions_controller.rb | 6 +- app/controllers/watchers_controller.rb | 4 +- app/controllers/welcome_controller.rb | 4 +- app/controllers/wiki_controller.rb | 14 +- app/controllers/wikis_controller.rb | 11 +- app/controllers/workflows_controller.rb | 6 +- app/helpers/account_helper.rb | 6 +- app/helpers/activities_helper.rb | 10 +- app/helpers/admin_helper.rb | 6 +- app/helpers/application_helper.rb | 524 +++-- app/helpers/attachments_helper.rb | 37 +- app/helpers/auth_sources_helper.rb | 6 +- app/helpers/avatars_helper.rb | 75 + app/helpers/boards_helper.rb | 6 +- app/helpers/calendars_helper.rb | 47 +- app/helpers/context_menus_helper.rb | 26 +- app/helpers/custom_fields_helper.rb | 60 +- app/helpers/documents_helper.rb | 6 +- app/helpers/email_addresses_helper.rb | 16 +- app/helpers/enumerations_helper.rb | 6 +- app/helpers/gantt_helper.rb | 16 +- app/helpers/groups_helper.rb | 12 +- app/helpers/imports_helper.rb | 16 +- app/helpers/issue_categories_helper.rb | 6 +- app/helpers/issue_relations_helper.rb | 8 +- app/helpers/issue_statuses_helper.rb | 6 +- app/helpers/issues_helper.rb | 281 ++- app/helpers/journals_helper.rb | 42 +- app/helpers/mail_handler_helper.rb | 6 +- app/helpers/members_helper.rb | 48 +- app/helpers/messages_helper.rb | 6 +- app/helpers/my_helper.rb | 32 +- app/helpers/news_helper.rb | 6 +- app/helpers/principal_memberships_helper.rb | 6 +- app/helpers/projects_helper.rb | 81 +- app/helpers/projects_queries_helper.rb | 62 + app/helpers/queries_helper.rb | 111 +- app/helpers/reports_helper.rb | 6 +- app/helpers/repositories_helper.rb | 38 +- app/helpers/roles_helper.rb | 6 +- app/helpers/routes_helper.rb | 6 +- app/helpers/search_helper.rb | 13 +- app/helpers/settings_helper.rb | 28 +- app/helpers/sort_helper.rb | 11 +- app/helpers/timelog_helper.rb | 34 +- app/helpers/trackers_helper.rb | 12 +- app/helpers/users_helper.rb | 50 +- app/helpers/versions_helper.rb | 55 +- app/helpers/watchers_helper.rb | 6 +- app/helpers/welcome_helper.rb | 6 +- app/helpers/wiki_helper.rb | 14 +- app/helpers/workflows_helper.rb | 33 +- app/models/attachment.rb | 102 +- app/models/auth_source.rb | 13 +- app/models/auth_source_ldap.rb | 54 +- app/models/board.rb | 5 +- app/models/change.rb | 5 +- app/models/changeset.rb | 28 +- app/models/comment.rb | 23 +- app/models/custom_field.rb | 44 +- app/models/custom_field_enumeration.rb | 4 +- app/models/custom_field_value.rb | 7 +- app/models/custom_value.rb | 7 +- app/models/document.rb | 9 +- app/models/document_category.rb | 4 +- app/models/document_category_custom_field.rb | 4 +- app/models/document_custom_field.rb | 4 +- app/models/email_address.rb | 47 +- app/models/enabled_module.rb | 5 +- app/models/enumeration.rb | 8 +- app/models/group.rb | 10 +- app/models/group_anonymous.rb | 4 +- app/models/group_builtin.rb | 4 +- app/models/group_custom_field.rb | 4 +- app/models/group_non_member.rb | 4 +- app/models/import.rb | 47 +- app/models/import_item.rb | 4 +- app/models/issue.rb | 297 ++- app/models/issue_category.rb | 5 +- app/models/issue_custom_field.rb | 11 +- app/models/issue_import.rb | 56 +- app/models/issue_priority.rb | 9 +- app/models/issue_priority_custom_field.rb | 5 +- app/models/issue_query.rb | 250 ++- app/models/issue_relation.rb | 24 +- app/models/issue_status.rb | 12 +- app/models/journal.rb | 35 +- app/models/journal_detail.rb | 5 +- app/models/mail_handler.rb | 286 +-- app/models/mailer.rb | 590 ++++-- app/models/member.rb | 17 +- app/models/member_role.rb | 10 +- app/models/message.rb | 32 +- app/models/news.rb | 9 +- app/models/principal.rb | 43 +- app/models/project.rb | 174 +- app/models/project_custom_field.rb | 13 +- app/models/project_query.rb | 112 ++ app/models/query.rb | 229 ++- app/models/repository.rb | 53 +- app/models/repository/bazaar.rb | 7 +- app/models/repository/cvs.rb | 23 +- app/models/repository/darcs.rb | 114 -- app/models/repository/filesystem.rb | 5 +- app/models/repository/git.rb | 11 +- app/models/repository/mercurial.rb | 11 +- app/models/repository/subversion.rb | 5 +- app/models/role.rb | 51 +- app/models/setting.rb | 85 +- app/models/time_entry.rb | 87 +- app/models/time_entry_activity.rb | 4 +- .../time_entry_activity_custom_field.rb | 4 +- app/models/time_entry_custom_field.rb | 14 +- app/models/time_entry_import.rb | 127 ++ app/models/time_entry_query.rb | 76 +- app/models/token.rb | 9 +- app/models/tracker.rb | 25 +- app/models/user.rb | 138 +- app/models/user_custom_field.rb | 5 +- app/models/user_preference.rb | 22 +- app/models/version.rb | 239 ++- app/models/version_custom_field.rb | 8 +- app/models/watcher.rb | 8 +- app/models/wiki.rb | 7 +- app/models/wiki_content.rb | 155 +- app/models/wiki_content_version.rb | 119 ++ app/models/wiki_page.rb | 57 +- app/models/wiki_redirect.rb | 5 +- app/models/workflow_permission.rb | 6 +- app/models/workflow_rule.rb | 11 +- app/models/workflow_transition.rb | 4 +- app/views/account/login.html.erb | 11 +- app/views/account/password_recovery.html.erb | 3 + app/views/account/register.html.erb | 7 +- app/views/activities/_activities.html.erb | 17 + app/views/activities/index.html.erb | 20 +- app/views/admin/projects.html.erb | 2 +- app/views/attachments/edit_all.html.erb | 4 +- app/views/attachments/file.html.erb | 2 +- app/views/attachments/other.html.erb | 12 +- .../_form_auth_source_ldap.html.erb | 6 +- app/views/auto_completes/issues.html.erb | 7 - app/views/boards/index.html.erb | 6 + app/views/boards/show.html.erb | 7 +- app/views/calendars/show.html.erb | 31 +- app/views/common/_calendar.html.erb | 9 +- app/views/common/_diff.html.erb | 6 + app/views/common/_markup.html.erb | 3 + app/views/common/_no_preview.html.erb | 8 + app/views/common/_other.html.erb | 28 +- app/views/common/_preview.html.erb | 8 +- app/views/common/_tabs.html.erb | 12 +- app/views/common/error.html.erb | 5 + app/views/common/feed.atom.builder | 2 + app/views/context_menus/issues.html.erb | 20 +- app/views/context_menus/time_entries.html.erb | 8 +- .../custom_field_enumerations/index.html.erb | 2 +- app/views/custom_fields/_form.html.erb | 133 +- .../_visibility_by_project_selector.html.erb | 11 + .../_visibility_by_role_selector.html.erb | 20 + .../_visibility_by_tracker_selector.html.erb | 13 + app/views/custom_fields/index.html.erb | 2 +- app/views/custom_fields/select_type.html.erb | 5 +- app/views/documents/_form.html.erb | 7 +- app/views/documents/index.html.erb | 2 +- app/views/enumerations/index.api.rsb | 1 + app/views/gantts/show.html.erb | 234 ++- app/views/groups/_new_users_modal.html.erb | 2 +- app/views/groups/show.html.erb | 9 + ...ml.erb => _issues_fields_mapping.html.erb} | 44 +- app/views/imports/_issues_mapping.html.erb | 16 + app/views/imports/_issues_mapping.js.erb | 1 + .../imports/_issues_saved_objects.html.erb | 7 + app/views/imports/_issues_sidebar.html.erb | 3 + .../_time_entries_fields_mapping.html.erb | 48 + .../imports/_time_entries_mapping.html.erb | 18 + .../imports/_time_entries_mapping.js.erb | 1 + .../_time_entries_saved_objects.html.erb | 26 + .../imports/_time_entries_sidebar.html.erb | 3 + app/views/imports/mapping.html.erb | 27 +- app/views/imports/mapping.js.erb | 2 +- app/views/imports/new.html.erb | 8 +- app/views/imports/run.html.erb | 6 +- app/views/imports/settings.html.erb | 20 +- app/views/imports/show.html.erb | 14 +- .../issue_categories/_new_modal.html.erb | 2 +- app/views/issue_statuses/index.html.erb | 8 + app/views/issues/_action_menu.html.erb | 14 +- app/views/issues/_action_menu_edit.html.erb | 10 + app/views/issues/_attributes.html.erb | 17 +- app/views/issues/_changesets.html.erb | 18 - app/views/issues/_edit.html.erb | 14 +- app/views/issues/_form.html.erb | 25 +- app/views/issues/_form_custom_fields.html.erb | 1 + app/views/issues/_list.html.erb | 11 +- app/views/issues/_sidebar.html.erb | 13 - .../issues/_trackers_description.html.erb | 22 + app/views/issues/bulk_edit.html.erb | 20 +- app/views/issues/index.html.erb | 32 +- app/views/issues/new.html.erb | 3 - app/views/issues/new.js.erb | 7 +- app/views/issues/show.html.erb | 40 +- app/views/issues/tabs/_changesets.html.erb | 24 + app/views/issues/{ => tabs}/_history.html.erb | 18 +- app/views/issues/tabs/_time_entries.html.erb | 28 + app/views/journals/_notes_form.html.erb | 18 +- app/views/journals/diff.html.erb | 4 +- app/views/journals/index.builder | 2 + app/views/journals/update.js.erb | 3 +- app/views/layouts/_file.html.erb | 12 +- app/views/layouts/base.html.erb | 84 +- app/views/mailer/_issue.html.erb | 2 +- app/views/mailer/_issue.text.erb | 2 +- .../account_activation_request.html.erb | 2 +- .../account_activation_request.text.erb | 2 +- app/views/mailer/issue_add.html.erb | 2 +- app/views/mailer/issue_add.text.erb | 2 +- app/views/mailer/issue_edit.html.erb | 2 +- app/views/mailer/issue_edit.text.erb | 2 +- app/views/mailer/lost_password.html.erb | 2 + app/views/mailer/lost_password.text.erb | 2 + app/views/mailer/reminder.html.erb | 4 +- app/views/mailer/reminder.text.erb | 3 +- .../mailer/security_notification.html.erb | 5 +- .../mailer/security_notification.text.erb | 5 +- app/views/mailer/settings_updated.html.erb | 4 +- app/views/mailer/settings_updated.text.erb | 4 +- app/views/members/_edit.html.erb | 7 +- app/views/members/_new_modal.html.erb | 2 +- app/views/messages/_form.html.erb | 10 +- app/views/messages/edit.html.erb | 4 +- app/views/messages/new.html.erb | 3 - app/views/messages/show.html.erb | 10 +- app/views/my/account.api.rsb | 13 + app/views/my/account.html.erb | 4 +- app/views/my/blocks/_activity.html.erb | 5 + app/views/my/blocks/_timelog.html.erb | 5 +- app/views/my/page.html.erb | 6 +- app/views/my/password.html.erb | 6 +- app/views/news/_form.html.erb | 9 +- app/views/news/edit.html.erb | 2 - app/views/news/index.html.erb | 4 +- app/views/news/new.html.erb | 2 - app/views/news/show.api.rsb | 24 + app/views/news/show.html.erb | 15 +- app/views/previews/issue.html.erb | 11 - .../principal_memberships/_edit.html.erb | 15 +- .../principal_memberships/_new_modal.html.erb | 2 +- app/views/projects/_board.html.erb | 3 + app/views/projects/_form.html.erb | 59 +- app/views/projects/_list.html.erb | 53 + app/views/projects/_sidebar.html.erb | 2 + app/views/projects/bookmark.js.erb | 2 + app/views/projects/copy.html.erb | 14 +- app/views/projects/index.api.rsb | 1 + app/views/projects/index.html.erb | 33 +- .../projects/settings/_activities.html.erb | 21 +- app/views/projects/settings/_issues.html.erb | 47 + app/views/projects/settings/_members.html.erb | 5 +- app/views/projects/settings/_modules.html.erb | 18 - .../projects/settings/_versions.html.erb | 19 +- app/views/projects/settings/_wiki.html.erb | 19 - app/views/projects/show.api.rsb | 3 + app/views/projects/show.html.erb | 45 +- app/views/queries/_columns.html.erb | 40 +- app/views/queries/_form.html.erb | 68 +- app/views/queries/_query_form.html.erb | 84 +- app/views/reports/_details.html.erb | 61 +- app/views/reports/_simple.html.erb | 8 +- app/views/reports/issue_report.html.erb | 3 +- .../reports/issue_report_details.html.erb | 3 +- app/views/repositories/_changeset.html.erb | 29 +- .../repositories/_dir_list_content.html.erb | 2 +- app/views/repositories/_navigation.html.erb | 6 + app/views/repositories/_revisions.html.erb | 13 +- app/views/repositories/annotate.html.erb | 2 +- app/views/repositories/diff.html.erb | 27 + app/views/repositories/entry.html.erb | 11 + app/views/repositories/revision.html.erb | 8 - app/views/repositories/stats.html.erb | 106 +- app/views/roles/_form.html.erb | 17 +- app/views/roles/index.html.erb | 8 + app/views/roles/permissions.html.erb | 26 +- app/views/roles/show.api.rsb | 4 + app/views/search/index.html.erb | 23 +- app/views/settings/_authentication.html.erb | 21 +- app/views/settings/_display.html.erb | 7 +- app/views/settings/_issues.html.erb | 4 + app/views/settings/_mail_handler.html.erb | 9 +- app/views/settings/_notifications.html.erb | 5 +- app/views/settings/_projects.html.erb | 8 + app/views/settings/_timelog.html.erb | 19 + app/views/settings/_users.html.erb | 20 + app/views/sudo_mode/_new_modal.html.erb | 2 +- app/views/timelog/_form.html.erb | 11 +- app/views/timelog/_list.html.erb | 10 +- app/views/timelog/_sidebar.html.erb | 1 + app/views/timelog/bulk_edit.html.erb | 71 +- app/views/timelog/bulk_edit.js.erb | 1 + app/views/timelog/edit.html.erb | 1 + app/views/timelog/index.api.rsb | 2 +- app/views/timelog/index.html.erb | 28 +- app/views/timelog/new.html.erb | 1 + app/views/timelog/report.html.erb | 29 +- app/views/trackers/_form.html.erb | 6 +- app/views/trackers/fields.html.erb | 6 +- app/views/trackers/index.api.rsb | 1 + app/views/trackers/index.html.erb | 4 + app/views/users/_form.html.erb | 11 +- app/views/users/_mail_notifications.html.erb | 3 +- app/views/users/_preferences.html.erb | 2 + app/views/users/edit.html.erb | 5 +- app/views/users/index.api.rsb | 1 + app/views/users/index.html.erb | 24 +- app/views/users/new.html.erb | 2 +- app/views/users/show.api.rsb | 5 +- app/views/users/show.html.erb | 120 +- app/views/versions/_form.html.erb | 4 +- app/views/versions/_new_modal.html.erb | 2 +- app/views/versions/_overview.html.erb | 20 +- app/views/versions/index.api.rsb | 13 +- app/views/versions/index.html.erb | 14 +- app/views/versions/show.api.rsb | 17 +- app/views/versions/show.html.erb | 14 +- app/views/watchers/_new.html.erb | 2 +- app/views/watchers/create.js.erb | 10 +- app/views/welcome/index.html.erb | 150 +- app/views/welcome/robots.html.erb | 10 - app/views/welcome/robots.text.erb | 12 + app/views/wiki/_new_modal.html.erb | 10 +- app/views/wiki/_sidebar.html.erb | 2 + app/views/wiki/annotate.html.erb | 8 +- app/views/wiki/date_index.html.erb | 5 +- app/views/wiki/diff.html.erb | 10 +- app/views/wiki/edit.html.erb | 40 +- app/views/wiki/export.html.erb | 2 +- app/views/wiki/export_multiple.html.erb | 8 +- app/views/wiki/history.html.erb | 9 +- app/views/wiki/index.html.erb | 3 + app/views/wiki/rename.html.erb | 20 +- app/views/wiki/show.html.erb | 73 +- app/views/wikis/destroy.html.erb | 3 +- app/views/workflows/_form.html.erb | 11 +- app/views/workflows/edit.html.erb | 10 +- app/views/workflows/permissions.html.erb | 10 +- appveyor.yml | 2 +- bin/bundle | 1 + bin/changelog.rb | 337 ++++ config.ru | 2 +- config/application.rb | 35 +- config/boot.rb | 2 + config/configuration.yml.example | 43 +- config/database.yml.example | 11 +- config/environment.rb | 6 +- config/environments/development.rb | 2 + config/environments/production.rb | 2 + config/environments/test.rb | 5 + config/environments/test_pgsql.rb | 2 + config/environments/test_sqlite3.rb | 2 + config/initializers/00-core_plugins.rb | 2 + config/initializers/10-patches.rb | 45 +- config/initializers/20-mime_types.rb | 5 +- config/initializers/30-redmine.rb | 20 +- config/initializers/backtrace_silencers.rb | 2 + config/initializers/inflections.rb | 2 + config/locales/ar.yml | 103 +- config/locales/az.yml | 106 +- config/locales/bg.yml | 109 +- config/locales/bs.yml | 103 +- config/locales/ca.yml | 103 +- config/locales/cs.yml | 184 +- config/locales/da.yml | 103 +- config/locales/de.yml | 100 +- config/locales/el.yml | 103 +- config/locales/en-GB.yml | 106 +- config/locales/en.yml | 139 +- config/locales/es-PA.yml | 105 +- config/locales/es.yml | 151 +- config/locales/et.yml | 103 +- config/locales/eu.yml | 103 +- config/locales/fa.yml | 1750 +++++++++-------- config/locales/fi.yml | 105 +- config/locales/fr.yml | 102 +- config/locales/gl.yml | 110 +- config/locales/he.yml | 103 +- config/locales/hr.yml | 105 +- config/locales/hu.yml | 103 +- config/locales/id.yml | 105 +- config/locales/it.yml | 193 +- config/locales/ja.yml | 190 +- config/locales/ko.yml | 104 +- config/locales/lt.yml | 107 +- config/locales/lv.yml | 103 +- config/locales/mk.yml | 103 +- config/locales/mn.yml | 104 +- config/locales/nl.yml | 103 +- config/locales/no.yml | 103 +- config/locales/pl.yml | 105 +- config/locales/pt-BR.yml | 96 +- config/locales/pt.yml | 103 +- config/locales/ro.yml | 103 +- config/locales/ru.yml | 100 +- config/locales/sk.yml | 104 +- config/locales/sl.yml | 103 +- config/locales/sq.yml | 105 +- config/locales/sr-YU.yml | 103 +- config/locales/sr.yml | 103 +- config/locales/sv.yml | 103 +- config/locales/th.yml | 106 +- config/locales/tr.yml | 104 +- config/locales/uk.yml | 173 +- config/locales/vi.yml | 104 +- config/locales/zh-TW.yml | 108 +- config/locales/zh.yml | 94 +- config/routes.rb | 81 +- config/settings.yml | 48 +- db/migrate/001_setup.rb | 3 +- db/migrate/002_issue_move.rb | 2 +- db/migrate/003_issue_add_note.rb | 2 +- db/migrate/004_export_pdf.rb | 2 +- db/migrate/005_issue_start_date.rb | 2 +- db/migrate/006_calendar_and_activity.rb | 2 +- db/migrate/007_create_journals.rb | 2 +- db/migrate/008_create_user_preferences.rb | 2 +- db/migrate/009_add_hide_mail_pref.rb | 2 +- db/migrate/010_create_comments.rb | 2 +- db/migrate/011_add_news_comments_count.rb | 2 +- db/migrate/012_add_comments_permissions.rb | 2 +- db/migrate/013_create_queries.rb | 2 +- db/migrate/014_add_queries_permissions.rb | 2 +- db/migrate/015_create_repositories.rb | 2 +- .../016_add_repositories_permissions.rb | 2 +- db/migrate/017_create_settings.rb | 2 +- .../018_set_doc_and_files_notifications.rb | 2 +- db/migrate/019_add_issue_status_position.rb | 2 +- db/migrate/020_add_role_position.rb | 2 +- db/migrate/021_add_tracker_position.rb | 2 +- db/migrate/022_serialize_possibles_values.rb | 2 +- db/migrate/023_add_tracker_is_in_roadmap.rb | 2 +- db/migrate/024_add_roadmap_permission.rb | 2 +- db/migrate/025_add_search_permission.rb | 2 +- .../026_add_repository_login_and_password.rb | 2 +- db/migrate/027_create_wikis.rb | 2 +- db/migrate/028_create_wiki_pages.rb | 2 +- db/migrate/029_create_wiki_contents.rb | 2 +- .../030_add_projects_feeds_permissions.rb | 2 +- db/migrate/031_add_repository_root_url.rb | 2 +- db/migrate/032_create_time_entries.rb | 2 +- db/migrate/033_add_timelog_permissions.rb | 2 +- db/migrate/034_create_changesets.rb | 2 +- db/migrate/035_create_changes.rb | 2 +- db/migrate/036_add_changeset_commit_date.rb | 2 +- db/migrate/037_add_project_identifier.rb | 2 +- db/migrate/038_add_custom_field_is_filter.rb | 2 +- db/migrate/039_create_watchers.rb | 2 +- db/migrate/040_create_changesets_issues.rb | 2 +- db/migrate/041_rename_comment_to_comments.rb | 4 +- db/migrate/042_create_issue_relations.rb | 2 +- db/migrate/043_add_relations_permissions.rb | 2 +- db/migrate/044_set_language_length_to_five.rb | 2 +- db/migrate/045_create_boards.rb | 2 +- db/migrate/046_create_messages.rb | 2 +- db/migrate/047_add_boards_permissions.rb | 2 +- .../048_allow_null_version_effective_date.rb | 2 +- .../049_add_wiki_destroy_page_permission.rb | 2 +- .../050_add_wiki_attachments_permissions.rb | 2 +- db/migrate/051_add_project_status.rb | 2 +- db/migrate/052_add_changes_revision.rb | 2 +- db/migrate/053_add_changes_branch.rb | 2 +- db/migrate/054_add_changesets_scmid.rb | 2 +- db/migrate/055_add_repositories_type.rb | 2 +- ...056_add_repositories_changes_permission.rb | 2 +- .../057_add_versions_wiki_page_title.rb | 2 +- ...058_add_issue_categories_assigned_to_id.rb | 2 +- db/migrate/059_add_roles_assignable.rb | 2 +- .../060_change_changesets_committer_limit.rb | 2 +- db/migrate/061_add_roles_builtin.rb | 2 +- db/migrate/062_insert_builtin_roles.rb | 2 +- db/migrate/063_add_roles_permissions.rb | 2 +- db/migrate/064_drop_permissions.rb | 2 +- db/migrate/065_add_settings_updated_on.rb | 2 +- .../066_add_custom_value_customized_index.rb | 2 +- db/migrate/067_create_wiki_redirects.rb | 2 +- db/migrate/068_create_enabled_modules.rb | 2 +- db/migrate/069_add_issues_estimated_hours.rb | 2 +- ...0_change_attachments_content_type_limit.rb | 2 +- db/migrate/071_add_queries_column_names.rb | 2 +- db/migrate/072_add_enumerations_position.rb | 2 +- db/migrate/073_add_enumerations_is_default.rb | 2 +- db/migrate/074_add_auth_sources_tls.rb | 2 +- .../075_add_members_mail_notification.rb | 2 +- db/migrate/076_allow_null_position.rb | 2 +- .../077_remove_issue_statuses_html_color.rb | 2 +- db/migrate/078_add_custom_fields_position.rb | 2 +- .../079_add_user_preferences_time_zone.rb | 2 +- db/migrate/080_add_users_type.rb | 2 +- db/migrate/081_create_projects_trackers.rb | 2 +- db/migrate/082_add_messages_locked.rb | 2 +- db/migrate/083_add_messages_sticky.rb | 2 +- .../084_change_auth_sources_account_limit.rb | 2 +- ...e_tracker_old_status_index_to_workflows.rb | 2 +- .../086_add_custom_fields_searchable.rb | 2 +- ...087_change_projects_description_to_text.rb | 2 +- .../088_add_custom_fields_default_value.rb | 2 +- db/migrate/089_add_attachments_description.rb | 2 +- db/migrate/090_change_versions_name_limit.rb | 2 +- ...91_change_changesets_revision_to_string.rb | 2 +- ..._change_changes_from_revision_to_string.rb | 2 +- db/migrate/093_add_wiki_pages_protected.rb | 2 +- .../094_change_projects_homepage_limit.rb | 2 +- db/migrate/095_add_wiki_pages_parent_id.rb | 2 +- .../096_add_commit_access_permission.rb | 2 +- .../097_add_view_wiki_edits_permission.rb | 2 +- .../098_set_topic_authors_as_watchers.rb | 2 +- ...elete_wiki_pages_attachments_permission.rb | 2 +- db/migrate/100_add_changesets_user_id.rb | 2 +- db/migrate/101_populate_changesets_user_id.rb | 2 +- db/migrate/102_add_custom_fields_editable.rb | 2 +- db/migrate/103_set_custom_fields_editable.rb | 2 +- db/migrate/104_add_projects_lft_and_rgt.rb | 2 +- db/migrate/105_build_projects_tree.rb | 2 +- .../106_remove_projects_projects_count.rb | 2 +- .../107_add_open_id_authentication_tables.rb | 2 +- db/migrate/108_add_identity_url_to_users.rb | 2 +- ...4190337_add_watchers_user_id_type_index.rb | 2 +- ...0090312172426_add_queries_sort_criteria.rb | 2 +- ...4159_add_projects_trackers_unique_index.rb | 2 +- .../20090318181151_extend_settings_name.rb | 2 +- ...20090323224724_add_type_to_enumerations.rb | 2 +- ...090401221305_update_enumerations_to_sti.rb | 2 +- ...231134_add_active_field_to_enumerations.rb | 2 +- ...90403001910_add_project_to_enumerations.rb | 2 +- ...406161854_add_parent_id_to_enumerations.rb | 2 +- .../20090425161243_add_queries_group_by.rb | 2 +- .../20090503121501_create_member_roles.rb | 2 +- .../20090503121505_populate_member_roles.rb | 2 +- .../20090503121510_drop_members_role_id.rb | 2 +- ...20090614091200_fix_messages_sticky_null.rb | 2 +- .../20090704172350_populate_users_type.rb | 2 +- .../20090704172355_create_groups_users.rb | 2 +- ...4172358_add_member_roles_inherited_from.rb | 2 +- .../20091010093521_fix_users_custom_values.rb | 2 +- ...212227_add_missing_indexes_to_workflows.rb | 2 +- ...ssing_indexes_to_custom_fields_projects.rb | 2 +- ...7212644_add_missing_indexes_to_messages.rb | 2 +- ...938_add_missing_indexes_to_repositories.rb | 2 +- ...7213027_add_missing_indexes_to_comments.rb | 2 +- ...113_add_missing_indexes_to_enumerations.rb | 2 +- ...13151_add_missing_indexes_to_wiki_pages.rb | 2 +- ...7213228_add_missing_indexes_to_watchers.rb | 2 +- ...257_add_missing_indexes_to_auth_sources.rb | 2 +- ...213332_add_missing_indexes_to_documents.rb | 2 +- ...017213444_add_missing_indexes_to_tokens.rb | 2 +- ...13536_add_missing_indexes_to_changesets.rb | 2 +- ...add_missing_indexes_to_issue_categories.rb | 2 +- ...716_add_missing_indexes_to_member_roles.rb | 2 +- ...017213757_add_missing_indexes_to_boards.rb | 2 +- ...add_missing_indexes_to_user_preferences.rb | 2 +- ...017213910_add_missing_indexes_to_issues.rb | 2 +- ...17214015_add_missing_indexes_to_members.rb | 2 +- ...07_add_missing_indexes_to_custom_fields.rb | 2 +- ...17214136_add_missing_indexes_to_queries.rb | 2 +- ...236_add_missing_indexes_to_time_entries.rb | 2 +- ...91017214308_add_missing_indexes_to_news.rb | 2 +- ...1017214336_add_missing_indexes_to_users.rb | 2 +- ...4406_add_missing_indexes_to_attachments.rb | 2 +- ...40_add_missing_indexes_to_wiki_contents.rb | 2 +- ...19_add_missing_indexes_to_custom_values.rb | 2 +- ...7214611_add_missing_indexes_to_journals.rb | 2 +- ..._add_missing_indexes_to_issue_relations.rb | 2 +- ...0_add_missing_indexes_to_wiki_redirects.rb | 2 +- ...ssing_indexes_to_custom_fields_trackers.rb | 2 +- .../20091025163651_add_activity_indexes.rb | 2 +- .../20091108092559_add_versions_status.rb | 2 +- ...091114105931_add_view_issues_permission.rb | 2 +- ..._add_default_done_ratio_to_issue_status.rb | 2 +- .../20091205124427_add_versions_sharing.rb | 2 +- ...509_add_lft_and_rgt_indexes_to_projects.rb | 2 +- ...091220183727_add_index_to_settings_name.rb | 2 +- ...91220184736_add_indexes_to_issue_status.rb | 2 +- .../20091225164732_remove_enumerations_opt.rb | 2 +- ...7112908_change_wiki_contents_text_limit.rb | 4 +- ...hange_users_mail_notification_to_string.rb | 2 +- ...9193813_update_mail_notification_values.rb | 2 +- ...221100219_add_index_on_changesets_scmid.rb | 2 +- ...13132032_add_issues_nested_sets_columns.rb | 2 +- ...13171051_add_index_on_issues_nested_set.rb | 2 +- ...164950_change_changes_path_length_limit.rb | 2 +- ...dar_and_gantt_modules_where_appropriate.rb | 2 +- ...01104182107_add_unique_index_on_members.rb | 2 +- ...0101107130441_add_custom_fields_visible.rb | 2 +- ...101114115114_change_projects_name_limit.rb | 2 +- ...115359_change_projects_identifier_limit.rb | 2 +- ...60626_add_workflows_assignee_and_author.rb | 2 +- db/migrate/20110223180944_add_users_salt.rb | 2 +- .../20110223180953_salt_user_passwords.rb | 4 +- ...24000000_add_repositories_path_encoding.rb | 2 +- ...0112_change_repositories_password_limit.rb | 2 +- ...nge_auth_sources_account_password_limit.rb | 2 +- ...0_change_journal_details_values_to_text.rb | 2 +- ...228000000_add_repositories_log_encoding.rb | 2 +- ...28000100_copy_repositories_log_encoding.rb | 4 +- .../20110401192910_add_index_to_users_type.rb | 2 +- ...10408103312_add_roles_issues_visibility.rb | 2 +- .../20110412065600_add_issues_is_private.rb | 2 +- ...10511000000_add_repositories_extra_info.rb | 2 +- ...20110902000000_create_changeset_parents.rb | 2 +- ...315_add_unique_index_to_issue_relations.rb | 2 +- ...20115143024_add_repositories_identifier.rb | 2 +- ...20115143100_add_repositories_is_default.rb | 2 +- ...20120115143126_set_default_repositories.rb | 2 +- ...120127174243_add_custom_fields_multiple.rb | 2 +- ...20120205111326_change_users_login_limit.rb | 2 +- ...9_change_attachments_container_defaults.rb | 2 +- .../20120301153455_add_auth_sources_filter.rb | 2 +- ...2150750_change_repositories_to_full_sti.rb | 2 +- ...20120705074331_add_trackers_fields_bits.rb | 2 +- ...20120707064544_add_auth_sources_timeout.rb | 2 +- .../20120714122000_add_workflows_type.rb | 2 +- .../20120714122100_update_workflows_to_sti.rb | 2 +- ...0120714122200_add_workflows_rule_fields.rb | 2 +- .../20120731164049_add_boards_parent_id.rb | 2 +- ...120930112914_add_journals_private_notes.rb | 2 +- ...26002032_add_enumerations_position_name.rb | 2 +- ...537_populate_enumerations_position_name.rb | 2 +- db/migrate/20121209123234_add_queries_type.rb | 2 +- .../20121209123358_update_queries_to_sti.rb | 2 +- ...13084931_add_attachments_disk_directory.rb | 2 +- ...30110122628_split_documents_permissions.rb | 2 +- ...184705_add_unique_index_on_tokens_value.rb | 4 +- ...0202090625_add_projects_inherit_members.rb | 2 +- ..._unique_index_on_custom_fields_trackers.rb | 2 +- ..._unique_index_on_custom_fields_projects.rb | 2 +- ...721_change_users_lastname_length_to_255.rb | 2 +- .../20130215111127_add_issues_closed_on.rb | 2 +- ...0130215111141_populate_issues_closed_on.rb | 2 +- ...7094251_remove_issues_default_fk_values.rb | 2 +- .../20130602092539_create_queries_roles.rb | 2 +- .../20130710182539_add_queries_visibility.rb | 2 +- ...130713104233_create_custom_fields_roles.rb | 2 +- .../20130713111657_add_queries_options.rb | 2 +- ...0729070143_add_users_must_change_passwd.rb | 2 +- ...0_remove_eols_from_attachments_filename.rb | 2 +- ...37_support_for_multiple_commit_keywords.rb | 2 +- ...31005100610_add_repositories_created_on.rb | 2 +- ...24175346_add_custom_fields_format_store.rb | 2 +- ...210180802_add_custom_fields_description.rb | 2 +- ...om_fields_min_max_length_default_values.rb | 2 +- ..._store_relation_type_in_journal_details.rb | 2 +- ...elete_orphan_time_entries_custom_values.rb | 2 +- ...130325_change_changesets_comments_limit.rb | 4 +- ...3143914_add_password_changed_at_to_user.rb | 2 +- .../20140920094058_insert_builtin_groups.rb | 2 +- ...29181752_add_trackers_default_status_id.rb | 2 +- ...181824_remove_issue_statuses_is_default.rb | 2 +- ...141109112308_add_roles_users_visibility.rb | 2 +- ...add_wiki_redirects_redirects_to_wiki_id.rb | 2 +- .../20150113194759_create_email_addresses.rb | 6 +- ...20150113211532_populate_email_addresses.rb | 2 +- .../20150113213922_remove_users_mail.rb | 2 +- ...13955_add_email_addresses_user_id_index.rb | 2 +- ...08105930_replace_move_issues_permission.rb | 4 +- ...0510083747_change_documents_title_limit.rb | 2 +- ..._clear_estimated_hours_on_parent_issues.rb | 2 +- ...83158_add_roles_time_entries_visibility.rb | 2 +- ...50528084820_add_roles_all_roles_managed.rb | 2 +- ...150528092912_create_roles_managed_roles.rb | 2 +- ...add_unique_index_on_roles_managed_roles.rb | 2 +- ..._insert_allowed_statuses_for_new_issues.rb | 2 +- db/migrate/20150730122707_create_imports.rb | 2 +- .../20150730122735_create_import_items.rb | 2 +- ...nge_time_entries_comments_limit_to_1024.rb | 2 +- ...ge_wiki_contents_comments_limit_to_1024.rb | 2 +- ..._change_attachments_filesize_limit_to_8.rb | 4 +- ..._fix_comma_in_user_format_setting_value.rb | 4 +- ...hange_issue_categories_name_limit_to_60.rb | 4 +- ...5456_change_auth_sources_filter_to_text.rb | 4 +- ...r_preferences_hide_mail_default_to_true.rb | 2 +- .../20151024082034_add_tokens_updated_on.rb | 2 +- ...072118_create_custom_field_enumerations.rb | 2 +- ...1095005_add_projects_default_version_id.rb | 2 +- ...80304_force_password_reset_during_setup.rb | 2 +- ...20160416072926_remove_position_defaults.rb | 2 +- .../20160529063352_add_roles_settings.rb | 2 +- ...22012_add_tracker_id_index_to_workflows.rb | 2 +- ...dd_index_on_member_roles_inherited_from.rb | 2 +- ...0081301_change_issues_description_limit.rb | 4 +- ...1528_change_journal_details_value_limit.rb | 4 +- ...61010081600_change_journals_notes_limit.rb | 4 +- ...add_index_on_changesets_issues_issue_id.rb | 2 +- ...220091118_add_index_on_issues_parent_id.rb | 2 +- ...d_index_on_disk_filename_to_attachments.rb | 2 +- ...5_change_attachments_digest_limit_to_64.rb | 3 +- ...4320_add_project_default_assigned_to_id.rb | 2 +- ...50_change_repositories_extra_info_limit.rb | 4 +- ...031_add_view_news_to_all_existing_roles.rb | 2 +- ...add_view_messages_to_all_existing_roles.rb | 2 +- ...170723112801_rename_comments_to_content.rb | 5 + ...501132547_add_author_id_to_time_entries.rb | 11 + ...3072918_add_verify_peer_to_auth_sources.rb | 7 + ...82945_change_sqlite_booleans_to_0_and_1.rb | 46 + ...23091603_change_sqlite_booleans_default.rb | 93 + ...094151_change_custom_values_value_limit.rb | 12 + ...20190315102101_add_trackers_description.rb | 5 + ...510070108_add_unique_id_to_import_items.rb | 8 + .../20190620135549_change_roles_name_limit.rb | 9 + doc/CHANGELOG | 987 +++++++++- doc/INSTALL | 16 +- doc/README_FOR_APP | 2 +- doc/RUNNING_TESTS | 15 +- doc/UPGRADING | 2 +- extra/mail_handler/rdm-mailhandler.rb | 14 +- .../db/migrate/001_create_meetings.rb | 2 +- extra/sample_plugin/init.rb | 2 +- .../test/integration/routing_test.rb | 1 - extra/svn/reposman.rb | 5 +- lib/SVG/GPL.txt | 340 ---- lib/SVG/Graph/Bar.rb | 148 -- lib/SVG/Graph/BarBase.rb | 139 -- lib/SVG/Graph/BarHorizontal.rb | 149 -- lib/SVG/Graph/Graph.rb | 977 --------- lib/SVG/Graph/Line.rb | 444 ----- lib/SVG/Graph/Pie.rb | 395 ---- lib/SVG/Graph/Plot.rb | 500 ----- lib/SVG/Graph/Schedule.rb | 373 ---- lib/SVG/Graph/TimeSeries.rb | 238 --- lib/SVG/LICENSE.txt | 57 - lib/diff.rb | 16 +- lib/generators/redmine_plugin/USAGE | 2 +- .../redmine_plugin_generator.rb | 20 + .../redmine_plugin_controller/USAGE | 2 +- .../redmine_plugin_controller_generator.rb | 27 +- lib/generators/redmine_plugin_migration/USAGE | 5 + .../redmine_plugin_migration_generator.rb | 39 + .../templates/migration.rb.tt | 4 + lib/generators/redmine_plugin_model/USAGE | 2 +- .../redmine_plugin_model_generator.rb | 36 +- .../templates/migration.rb | 2 +- .../templates/model.rb.erb | 2 +- lib/plugins/acts_as_activity_provider/init.rb | 2 + .../lib/acts_as_activity_provider.rb | 4 +- lib/plugins/acts_as_attachable/init.rb | 2 + .../lib/acts_as_attachable.rb | 10 +- lib/plugins/acts_as_customizable/init.rb | 2 + .../lib/acts_as_customizable.rb | 12 +- lib/plugins/acts_as_event/init.rb | 2 + .../acts_as_event/lib/acts_as_event.rb | 4 +- lib/plugins/acts_as_list/README | 23 - lib/plugins/acts_as_list/init.rb | 3 - .../lib/active_record/acts/list.rb | 281 --- lib/plugins/acts_as_list/test/list_test.rb | 332 ---- lib/plugins/acts_as_searchable/init.rb | 2 + .../lib/acts_as_searchable.rb | 9 +- lib/plugins/acts_as_tree/Rakefile | 2 + lib/plugins/acts_as_tree/init.rb | 2 + .../lib/active_record/acts/tree.rb | 2 + .../acts_as_tree/test/acts_as_tree_test.rb | 2 + lib/plugins/acts_as_versioned/CHANGELOG | 74 - lib/plugins/acts_as_versioned/MIT-LICENSE | 20 - lib/plugins/acts_as_versioned/README | 28 - .../acts_as_versioned/RUNNING_UNIT_TESTS | 41 - lib/plugins/acts_as_versioned/Rakefile | 182 -- lib/plugins/acts_as_versioned/init.rb | 1 - .../lib/acts_as_versioned.rb | 569 ------ .../acts_as_versioned/test/abstract_unit.rb | 41 - .../acts_as_versioned/test/database.yml | 18 - .../test/fixtures/authors.yml | 6 - .../test/fixtures/landmark.rb | 3 - .../test/fixtures/landmark_versions.yml | 7 - .../test/fixtures/landmarks.yml | 6 - .../test/fixtures/locked_pages.yml | 10 - .../test/fixtures/locked_pages_revisions.yml | 27 - .../migrations/1_add_versioned_tables.rb | 13 - .../acts_as_versioned/test/fixtures/page.rb | 43 - .../test/fixtures/page_versions.yml | 16 - .../acts_as_versioned/test/fixtures/pages.yml | 7 - .../acts_as_versioned/test/fixtures/widget.rb | 6 - .../acts_as_versioned/test/migration_test.rb | 46 - lib/plugins/acts_as_versioned/test/schema.rb | 68 - .../acts_as_versioned/test/versioned_test.rb | 347 ---- lib/plugins/acts_as_watchable/init.rb | 2 + .../lib/acts_as_watchable.rb | 3 +- lib/plugins/gravatar/init.rb | 2 + lib/plugins/gravatar/lib/gravatar.rb | 29 +- lib/plugins/open_id_authentication/init.rb | 4 +- .../lib/open_id_authentication.rb | 8 +- .../lib/open_id_authentication/association.rb | 2 + .../lib/open_id_authentication/db_store.rb | 4 +- .../open_id_authentication/mem_cache_store.rb | 2 + .../lib/open_id_authentication/nonce.rb | 2 + .../lib/open_id_authentication/request.rb | 2 + .../open_id_authentication/timeout_fixes.rb | 4 +- .../test/status_test.rb | 2 +- lib/redmine.rb | 112 +- lib/redmine/access_control.rb | 4 +- lib/redmine/access_keys.rb | 4 +- lib/redmine/activity.rb | 4 +- lib/redmine/activity/fetcher.rb | 4 +- lib/redmine/acts/positioned.rb | 23 +- lib/redmine/ciphering.rb | 4 +- lib/redmine/codeset_util.rb | 23 +- lib/redmine/configuration.rb | 13 +- lib/redmine/core_ext.rb | 2 + lib/redmine/core_ext/active_record.rb | 6 +- lib/redmine/core_ext/date.rb | 5 - lib/redmine/core_ext/string.rb | 5 +- lib/redmine/core_ext/string/conversions.rb | 13 +- lib/redmine/core_ext/string/inflections.rb | 13 +- lib/redmine/database.rb | 29 +- lib/redmine/default_data/loader.rb | 25 +- lib/redmine/export/csv.rb | 21 +- lib/redmine/export/pdf.rb | 16 +- lib/redmine/export/pdf/issues_pdf_helper.rb | 166 +- lib/redmine/export/pdf/wiki_pdf_helper.rb | 25 +- lib/redmine/field_format.rb | 59 +- lib/redmine/helpers/calendar.rb | 4 +- lib/redmine/helpers/diff.rb | 6 +- lib/redmine/helpers/gantt.rb | 461 +++-- lib/redmine/helpers/time_report.rb | 18 +- lib/redmine/helpers/url.rb | 8 +- lib/redmine/hook.rb | 4 +- lib/redmine/hook/listener.rb | 6 +- lib/redmine/hook/view_listener.rb | 8 +- lib/redmine/i18n.rb | 85 +- lib/redmine/imap.rb | 4 +- lib/redmine/info.rb | 8 +- lib/redmine/menu_manager.rb | 30 +- lib/redmine/mime_type.rb | 28 +- lib/redmine/my_page.rb | 8 +- lib/redmine/nested_set/issue_nested_set.rb | 14 +- lib/redmine/nested_set/project_nested_set.rb | 6 +- lib/redmine/nested_set/traversing.rb | 4 +- lib/redmine/notifiable.rb | 3 + lib/redmine/pagination.rb | 8 +- lib/redmine/platform.rb | 8 +- lib/redmine/plugin.rb | 115 +- lib/redmine/pop3.rb | 4 +- lib/redmine/project_jump_box.rb | 113 ++ lib/redmine/safe_attributes.rb | 10 +- lib/redmine/scm/adapters.rb | 4 +- lib/redmine/scm/adapters/abstract_adapter.rb | 88 +- lib/redmine/scm/adapters/bazaar_adapter.rb | 39 +- lib/redmine/scm/adapters/command_failed.rb | 7 +- lib/redmine/scm/adapters/cvs_adapter.rb | 53 +- lib/redmine/scm/adapters/darcs_adapter.rb | 239 --- .../scm/adapters/filesystem_adapter.rb | 6 +- lib/redmine/scm/adapters/git_adapter.rb | 72 +- lib/redmine/scm/adapters/mercurial_adapter.rb | 32 +- .../scm/adapters/subversion_adapter.rb | 30 +- lib/redmine/scm/base.rb | 2 + lib/redmine/search.rb | 10 +- lib/redmine/sort_criteria.rb | 12 +- lib/redmine/subclass_factory.rb | 10 +- lib/redmine/sudo_mode.rb | 4 +- lib/redmine/syntax_highlighting.rb | 83 +- lib/redmine/themes.rb | 9 +- lib/redmine/thumbnail.rb | 37 +- lib/redmine/unified_diff.rb | 29 +- lib/redmine/utils.rb | 14 +- lib/redmine/version.rb | 15 +- lib/redmine/views/api_template_handler.rb | 4 +- lib/redmine/views/builders.rb | 28 +- lib/redmine/views/builders/json.rb | 6 +- lib/redmine/views/builders/structure.rb | 16 +- lib/redmine/views/builders/xml.rb | 4 +- lib/redmine/views/labelled_form_builder.rb | 10 +- lib/redmine/views/other_formats_builder.rb | 4 +- lib/redmine/wiki_formatting.rb | 81 +- lib/redmine/wiki_formatting/html_parser.rb | 17 +- lib/redmine/wiki_formatting/macros.rb | 66 +- .../wiki_formatting/markdown/formatter.rb | 27 +- .../wiki_formatting/markdown/helper.rb | 8 +- .../wiki_formatting/markdown/html_parser.rb | 22 +- .../wiki_formatting/textile/formatter.rb | 16 +- lib/redmine/wiki_formatting/textile/helper.rb | 11 +- .../wiki_formatting/textile/html_parser.rb | 17 +- .../wiki_formatting/textile/redcloth3.rb | 441 ++--- lib/tasks/ciphering.rake | 2 +- lib/tasks/email.rake | 15 +- lib/tasks/locales.rake | 4 +- lib/tasks/migrate_from_mantis.rake | 2 +- lib/tasks/migrate_from_trac.rake | 8 +- lib/tasks/permissions.rake | 2 +- lib/tasks/redmine.rake | 44 +- lib/tasks/reminder.rake | 12 +- lib/tasks/testing.rake | 32 +- lib/tasks/yardoc.rake | 2 +- .../ar/wiki_syntax_detailed_markdown.html | 59 +- .../help/ar/wiki_syntax_detailed_textile.html | 54 +- public/help/ar/wiki_syntax_markdown.html | 22 +- public/help/ar/wiki_syntax_textile.html | 19 +- .../az/wiki_syntax_detailed_markdown.html | 59 +- .../help/az/wiki_syntax_detailed_textile.html | 54 +- public/help/az/wiki_syntax_markdown.html | 22 +- public/help/az/wiki_syntax_textile.html | 19 +- .../bg/wiki_syntax_detailed_markdown.html | 59 +- .../help/bg/wiki_syntax_detailed_textile.html | 54 +- public/help/bg/wiki_syntax_markdown.html | 22 +- public/help/bg/wiki_syntax_textile.html | 19 +- .../bs/wiki_syntax_detailed_markdown.html | 59 +- .../help/bs/wiki_syntax_detailed_textile.html | 54 +- public/help/bs/wiki_syntax_markdown.html | 22 +- public/help/bs/wiki_syntax_textile.html | 19 +- .../ca/wiki_syntax_detailed_markdown.html | 59 +- .../help/ca/wiki_syntax_detailed_textile.html | 54 +- public/help/ca/wiki_syntax_markdown.html | 22 +- public/help/ca/wiki_syntax_textile.html | 19 +- .../cs/wiki_syntax_detailed_markdown.html | 57 +- .../help/cs/wiki_syntax_detailed_textile.html | 54 +- public/help/cs/wiki_syntax_markdown.html | 22 +- public/help/cs/wiki_syntax_textile.html | 19 +- .../da/wiki_syntax_detailed_markdown.html | 59 +- .../help/da/wiki_syntax_detailed_textile.html | 54 +- public/help/da/wiki_syntax_markdown.html | 22 +- public/help/da/wiki_syntax_textile.html | 19 +- .../de/wiki_syntax_detailed_markdown.html | 59 +- .../help/de/wiki_syntax_detailed_textile.html | 54 +- public/help/de/wiki_syntax_markdown.html | 22 +- public/help/de/wiki_syntax_textile.html | 19 +- .../el/wiki_syntax_detailed_markdown.html | 59 +- .../help/el/wiki_syntax_detailed_textile.html | 54 +- public/help/el/wiki_syntax_markdown.html | 22 +- public/help/el/wiki_syntax_textile.html | 19 +- .../en-gb/wiki_syntax_detailed_markdown.html | 59 +- .../en-gb/wiki_syntax_detailed_textile.html | 54 +- public/help/en-gb/wiki_syntax_markdown.html | 22 +- public/help/en-gb/wiki_syntax_textile.html | 19 +- .../en/wiki_syntax_detailed_markdown.html | 59 +- .../help/en/wiki_syntax_detailed_textile.html | 54 +- public/help/en/wiki_syntax_markdown.html | 22 +- public/help/en/wiki_syntax_textile.html | 19 +- .../es-pa/wiki_syntax_detailed_markdown.html | 59 +- .../es-pa/wiki_syntax_detailed_textile.html | 54 +- public/help/es-pa/wiki_syntax_markdown.html | 22 +- public/help/es-pa/wiki_syntax_textile.html | 19 +- .../es/wiki_syntax_detailed_markdown.html | 59 +- .../help/es/wiki_syntax_detailed_textile.html | 54 +- public/help/es/wiki_syntax_markdown.html | 22 +- public/help/es/wiki_syntax_textile.html | 19 +- .../et/wiki_syntax_detailed_markdown.html | 59 +- .../help/et/wiki_syntax_detailed_textile.html | 54 +- public/help/et/wiki_syntax_markdown.html | 22 +- public/help/et/wiki_syntax_textile.html | 19 +- .../eu/wiki_syntax_detailed_markdown.html | 59 +- .../help/eu/wiki_syntax_detailed_textile.html | 54 +- public/help/eu/wiki_syntax_markdown.html | 22 +- public/help/eu/wiki_syntax_textile.html | 19 +- .../fa/wiki_syntax_detailed_markdown.html | 59 +- .../help/fa/wiki_syntax_detailed_textile.html | 54 +- public/help/fa/wiki_syntax_markdown.html | 22 +- public/help/fa/wiki_syntax_textile.html | 19 +- .../fi/wiki_syntax_detailed_markdown.html | 59 +- .../help/fi/wiki_syntax_detailed_textile.html | 54 +- public/help/fi/wiki_syntax_markdown.html | 22 +- public/help/fi/wiki_syntax_textile.html | 19 +- .../fr/wiki_syntax_detailed_markdown.html | 59 +- .../help/fr/wiki_syntax_detailed_textile.html | 47 +- public/help/fr/wiki_syntax_markdown.html | 22 +- public/help/fr/wiki_syntax_textile.html | 19 +- .../gl/wiki_syntax_detailed_markdown.html | 58 +- .../help/gl/wiki_syntax_detailed_textile.html | 55 +- public/help/gl/wiki_syntax_markdown.html | 22 +- public/help/gl/wiki_syntax_textile.html | 19 +- .../he/wiki_syntax_detailed_markdown.html | 59 +- .../help/he/wiki_syntax_detailed_textile.html | 54 +- public/help/he/wiki_syntax_markdown.html | 22 +- public/help/he/wiki_syntax_textile.html | 19 +- .../hr/wiki_syntax_detailed_markdown.html | 59 +- .../help/hr/wiki_syntax_detailed_textile.html | 54 +- public/help/hr/wiki_syntax_markdown.html | 22 +- public/help/hr/wiki_syntax_textile.html | 19 +- .../hu/wiki_syntax_detailed_markdown.html | 59 +- .../help/hu/wiki_syntax_detailed_textile.html | 54 +- public/help/hu/wiki_syntax_markdown.html | 22 +- public/help/hu/wiki_syntax_textile.html | 19 +- .../id/wiki_syntax_detailed_markdown.html | 59 +- .../help/id/wiki_syntax_detailed_textile.html | 54 +- public/help/id/wiki_syntax_markdown.html | 22 +- public/help/id/wiki_syntax_textile.html | 19 +- .../it/wiki_syntax_detailed_markdown.html | 59 +- .../help/it/wiki_syntax_detailed_textile.html | 54 +- public/help/it/wiki_syntax_markdown.html | 22 +- public/help/it/wiki_syntax_textile.html | 19 +- .../ja/wiki_syntax_detailed_markdown.html | 61 +- .../help/ja/wiki_syntax_detailed_textile.html | 58 +- public/help/ja/wiki_syntax_markdown.html | 21 +- public/help/ja/wiki_syntax_textile.html | 19 +- .../ko/wiki_syntax_detailed_markdown.html | 59 +- .../help/ko/wiki_syntax_detailed_textile.html | 54 +- public/help/ko/wiki_syntax_markdown.html | 22 +- public/help/ko/wiki_syntax_textile.html | 19 +- .../lt/wiki_syntax_detailed_markdown.html | 59 +- .../help/lt/wiki_syntax_detailed_textile.html | 55 +- public/help/lt/wiki_syntax_markdown.html | 22 +- public/help/lt/wiki_syntax_textile.html | 19 +- .../lv/wiki_syntax_detailed_markdown.html | 59 +- .../help/lv/wiki_syntax_detailed_textile.html | 54 +- public/help/lv/wiki_syntax_markdown.html | 22 +- public/help/lv/wiki_syntax_textile.html | 19 +- .../mk/wiki_syntax_detailed_markdown.html | 59 +- .../help/mk/wiki_syntax_detailed_textile.html | 54 +- public/help/mk/wiki_syntax_markdown.html | 22 +- public/help/mk/wiki_syntax_textile.html | 19 +- .../mn/wiki_syntax_detailed_markdown.html | 59 +- .../help/mn/wiki_syntax_detailed_textile.html | 54 +- public/help/mn/wiki_syntax_markdown.html | 22 +- public/help/mn/wiki_syntax_textile.html | 19 +- .../nl/wiki_syntax_detailed_markdown.html | 59 +- .../help/nl/wiki_syntax_detailed_textile.html | 54 +- public/help/nl/wiki_syntax_markdown.html | 22 +- public/help/nl/wiki_syntax_textile.html | 19 +- .../no/wiki_syntax_detailed_markdown.html | 59 +- .../help/no/wiki_syntax_detailed_textile.html | 54 +- public/help/no/wiki_syntax_markdown.html | 22 +- public/help/no/wiki_syntax_textile.html | 19 +- .../pl/wiki_syntax_detailed_markdown.html | 59 +- .../help/pl/wiki_syntax_detailed_textile.html | 54 +- public/help/pl/wiki_syntax_markdown.html | 22 +- public/help/pl/wiki_syntax_textile.html | 19 +- .../pt-br/wiki_syntax_detailed_markdown.html | 59 +- .../pt-br/wiki_syntax_detailed_textile.html | 54 +- public/help/pt-br/wiki_syntax_markdown.html | 22 +- public/help/pt-br/wiki_syntax_textile.html | 19 +- .../pt/wiki_syntax_detailed_markdown.html | 59 +- .../help/pt/wiki_syntax_detailed_textile.html | 54 +- public/help/pt/wiki_syntax_markdown.html | 22 +- public/help/pt/wiki_syntax_textile.html | 19 +- .../ro/wiki_syntax_detailed_markdown.html | 59 +- .../help/ro/wiki_syntax_detailed_textile.html | 54 +- public/help/ro/wiki_syntax_markdown.html | 22 +- public/help/ro/wiki_syntax_textile.html | 19 +- .../ru/wiki_syntax_detailed_markdown.html | 59 +- .../help/ru/wiki_syntax_detailed_textile.html | 49 +- public/help/ru/wiki_syntax_markdown.html | 22 +- public/help/ru/wiki_syntax_textile.html | 20 +- .../sk/wiki_syntax_detailed_markdown.html | 59 +- .../help/sk/wiki_syntax_detailed_textile.html | 54 +- public/help/sk/wiki_syntax_markdown.html | 22 +- public/help/sk/wiki_syntax_textile.html | 19 +- .../sl/wiki_syntax_detailed_markdown.html | 59 +- .../help/sl/wiki_syntax_detailed_textile.html | 54 +- public/help/sl/wiki_syntax_markdown.html | 22 +- public/help/sl/wiki_syntax_textile.html | 19 +- .../sq/wiki_syntax_detailed_markdown.html | 59 +- .../help/sq/wiki_syntax_detailed_textile.html | 54 +- public/help/sq/wiki_syntax_markdown.html | 22 +- public/help/sq/wiki_syntax_textile.html | 19 +- .../sr-yu/wiki_syntax_detailed_markdown.html | 59 +- .../sr-yu/wiki_syntax_detailed_textile.html | 54 +- public/help/sr-yu/wiki_syntax_markdown.html | 22 +- public/help/sr-yu/wiki_syntax_textile.html | 19 +- .../sr/wiki_syntax_detailed_markdown.html | 59 +- .../help/sr/wiki_syntax_detailed_textile.html | 54 +- public/help/sr/wiki_syntax_markdown.html | 22 +- public/help/sr/wiki_syntax_textile.html | 19 +- .../sv/wiki_syntax_detailed_markdown.html | 59 +- .../help/sv/wiki_syntax_detailed_textile.html | 54 +- public/help/sv/wiki_syntax_markdown.html | 22 +- public/help/sv/wiki_syntax_textile.html | 19 +- .../th/wiki_syntax_detailed_markdown.html | 59 +- .../help/th/wiki_syntax_detailed_textile.html | 54 +- public/help/th/wiki_syntax_markdown.html | 22 +- public/help/th/wiki_syntax_textile.html | 19 +- .../tr/wiki_syntax_detailed_markdown.html | 59 +- .../help/tr/wiki_syntax_detailed_textile.html | 54 +- public/help/tr/wiki_syntax_markdown.html | 22 +- public/help/tr/wiki_syntax_textile.html | 19 +- .../uk/wiki_syntax_detailed_markdown.html | 57 +- .../help/uk/wiki_syntax_detailed_textile.html | 54 +- public/help/uk/wiki_syntax_markdown.html | 21 +- public/help/uk/wiki_syntax_textile.html | 19 +- .../vi/wiki_syntax_detailed_markdown.html | 59 +- .../help/vi/wiki_syntax_detailed_textile.html | 54 +- public/help/vi/wiki_syntax_markdown.html | 22 +- public/help/vi/wiki_syntax_textile.html | 19 +- public/help/wiki_syntax.css | 13 +- public/help/wiki_syntax_detailed.css | 21 +- .../zh-tw/wiki_syntax_detailed_markdown.html | 57 +- .../zh-tw/wiki_syntax_detailed_textile.html | 54 +- public/help/zh-tw/wiki_syntax_markdown.html | 21 +- public/help/zh-tw/wiki_syntax_textile.html | 19 +- .../zh/wiki_syntax_detailed_markdown.html | 59 +- .../help/zh/wiki_syntax_detailed_textile.html | 56 +- public/help/zh/wiki_syntax_markdown.html | 22 +- public/help/zh/wiki_syntax_textile.html | 19 +- public/images/1downarrow.png | Bin 228 -> 0 bytes public/images/1uparrow.png | Bin 220 -> 0 bytes public/images/2downarrow.png | Bin 282 -> 0 bytes public/images/2uparrow.png | Bin 292 -> 0 bytes public/images/3_bullets.png | Bin 0 -> 1250 bytes public/images/arrow_collapsed.png | Bin 165 -> 0 bytes public/images/arrow_down.png | Bin 115 -> 257 bytes public/images/arrow_expanded.png | Bin 157 -> 0 bytes public/images/arrow_left.png | Bin 0 -> 273 bytes public/images/arrow_right.png | Bin 0 -> 287 bytes public/images/arrow_up.png | Bin 0 -> 261 bytes public/images/bullet_arrow_left.png | Bin 161 -> 0 bytes public/images/bullet_arrow_right.png | Bin 165 -> 0 bytes public/images/bullet_toggle_minus.png | Bin 218 -> 121 bytes public/images/bullet_toggle_plus.png | Bin 217 -> 136 bytes public/images/database_go.png | Bin 0 -> 698 bytes public/images/download.png | Bin 744 -> 388 bytes public/images/draft.png | Bin 1885 -> 0 bytes public/images/tag_blue_add.png | Bin 0 -> 671 bytes public/images/tag_blue_delete.png | Bin 0 -> 701 bytes public/images/transparent.png | Bin 0 -> 135 bytes public/javascripts/Chart.bundle.min.js | 7 + public/javascripts/application.js | 255 ++- public/javascripts/attachments.js | 41 +- public/javascripts/context_menu.js | 12 +- public/javascripts/gantt.js | 132 +- ...js => jquery-2.2.4-ui-1.11.0-ujs-5.2.3.js} | 15 +- .../jstoolbar/jstoolbar-textile.min.js | 1 - public/javascripts/jstoolbar/jstoolbar.js | 110 +- .../jstoolbar/lang/jstoolbar-ar.js | 2 + .../jstoolbar/lang/jstoolbar-az.js | 2 + .../jstoolbar/lang/jstoolbar-bg.js | 2 + .../jstoolbar/lang/jstoolbar-bs.js | 2 + .../jstoolbar/lang/jstoolbar-ca.js | 2 + .../jstoolbar/lang/jstoolbar-cs.js | 2 + .../jstoolbar/lang/jstoolbar-da.js | 2 + .../jstoolbar/lang/jstoolbar-de.js | 2 + .../jstoolbar/lang/jstoolbar-en-gb.js | 2 + .../jstoolbar/lang/jstoolbar-en.js | 2 + .../jstoolbar/lang/jstoolbar-es-pa.js | 2 + .../jstoolbar/lang/jstoolbar-es.js | 2 + .../jstoolbar/lang/jstoolbar-et.js | 2 + .../jstoolbar/lang/jstoolbar-eu.js | 2 + .../jstoolbar/lang/jstoolbar-fa.js | 2 + .../jstoolbar/lang/jstoolbar-fi.js | 2 + .../jstoolbar/lang/jstoolbar-fr.js | 2 + .../jstoolbar/lang/jstoolbar-gl.js | 6 +- .../jstoolbar/lang/jstoolbar-he.js | 2 + .../jstoolbar/lang/jstoolbar-hr.js | 4 +- .../jstoolbar/lang/jstoolbar-hu.js | 2 + .../jstoolbar/lang/jstoolbar-id.js | 2 + .../jstoolbar/lang/jstoolbar-it.js | 2 + .../jstoolbar/lang/jstoolbar-ja.js | 2 + .../jstoolbar/lang/jstoolbar-ko.js | 2 + .../jstoolbar/lang/jstoolbar-lt.js | 2 + .../jstoolbar/lang/jstoolbar-lv.js | 2 + .../jstoolbar/lang/jstoolbar-mk.js | 3 +- .../jstoolbar/lang/jstoolbar-mn.js | 2 + .../jstoolbar/lang/jstoolbar-nl.js | 2 + .../jstoolbar/lang/jstoolbar-no.js | 2 + .../jstoolbar/lang/jstoolbar-pl.js | 2 + .../jstoolbar/lang/jstoolbar-pt-br.js | 2 + .../jstoolbar/lang/jstoolbar-pt.js | 2 + .../jstoolbar/lang/jstoolbar-ro.js | 2 + .../jstoolbar/lang/jstoolbar-ru.js | 2 + .../jstoolbar/lang/jstoolbar-sk.js | 2 + .../jstoolbar/lang/jstoolbar-sl.js | 2 + .../jstoolbar/lang/jstoolbar-sq.js | 2 + .../jstoolbar/lang/jstoolbar-sr-yu.js | 2 + .../jstoolbar/lang/jstoolbar-sr.js | 2 + .../jstoolbar/lang/jstoolbar-sv.js | 2 + .../jstoolbar/lang/jstoolbar-th.js | 2 + .../jstoolbar/lang/jstoolbar-tr.js | 2 + .../jstoolbar/lang/jstoolbar-uk.js | 2 + .../jstoolbar/lang/jstoolbar-vi.js | 2 + .../jstoolbar/lang/jstoolbar-zh-tw.js | 2 + .../jstoolbar/lang/jstoolbar-zh.js | 2 + public/javascripts/jstoolbar/markdown.js | 13 +- public/javascripts/project_identifier.js | 2 +- public/javascripts/raphael.js | 11 +- public/javascripts/repository_navigation.js | 2 +- public/javascripts/revision_graph.js | 2 +- public/javascripts/tribute-3.7.3.min.js | 2 + public/javascripts/tribute.min.js.map | 1 + public/stylesheets/application.css | 688 +++++-- public/stylesheets/context_menu.css | 7 +- public/stylesheets/context_menu_rtl.css | 2 +- public/stylesheets/jstoolbar.css | 44 +- public/stylesheets/responsive.css | 48 +- public/stylesheets/rtl.css | 10 +- public/stylesheets/scm.css | 37 +- public/stylesheets/tribute-3.7.3.css | 27 + .../alternate/stylesheets/application.css | 3 +- script/about | 2 - script/rails | 2 - test/application_system_test_case.rb | 87 + test/controllers/empty | 0 test/coverage/html_formatter.rb | 6 +- test/coverage/views/index.erb | 5 +- .../redmine_pm/repository_git_test_pm.rb | 4 +- .../repository_subversion_test_pm.rb | 4 +- test/extra/redmine_pm/test_case.rb | 6 +- test/fixtures/attachments.yml | 75 +- test/fixtures/comments.yml | 4 +- test/fixtures/configuration/default.yml | 8 - test/fixtures/configuration/empty.yml | 7 - test/fixtures/configuration/no_default.yml | 8 - test/fixtures/configuration/overrides.yml | 9 - test/fixtures/documents.yml | 11 +- .../files/2006/07/060719210727_source.rb | 2 + .../04/190430092344_redmine_logo.ai.unknown | 232 +++ .../2019/05/190511141819_ecookbook-gantt.pdf | Bin 0 -> 31620 bytes test/fixtures/files/hello.js | 1 + test/fixtures/files/import_dates_ja.csv | 2 + test/fixtures/files/import_issues.csv | 8 +- .../files/import_subtasks_with_unique_id.csv | 5 + test/fixtures/files/import_time_entries.csv | 5 + test/fixtures/files/testfile.md | 3 + test/fixtures/files/testfile.textile | 5 + test/fixtures/issues.yml | 4 + .../different_contents_in_text_and_html.eml | 38 + .../fullname_of_sender_in_parentheses.eml | 8 + .../mail_handler/subject_japanese_3.eml | 9 + .../mail_handler/ticket_by_unknown_user.eml | 1 + .../mail_handler/ticket_on_given_project.eml | 1 + .../ticket_with_localized_private_flag.eml | 41 + .../_other_plugin_settings.html.erb | 1 + test/fixtures/projects_trackers.yml | 3 + .../repositories/darcs_repository.tar.gz | Bin 8075 -> 0 bytes .../repositories/git_repository.tar.gz | Bin 21021 -> 21103 bytes test/fixtures/roles.yml | 25 +- test/fixtures/time_entries.yml | 23 +- test/fixtures/trackers.yml | 2 + test/fixtures/user_preferences.yml | 35 +- test/fixtures/versions.yml | 1 + .../account_controller_openid_test.rb | 6 +- test/functional/account_controller_test.rb | 16 +- test/functional/activities_controller_test.rb | 10 +- test/functional/admin_controller_test.rb | 16 +- .../functional/application_controller_test.rb | 27 + .../functional/attachments_controller_test.rb | 104 +- .../functional/attachments_visibility_test.rb | 10 +- .../auth_sources_controller_test.rb | 7 +- .../auto_completes_controller_test.rb | 20 +- test/functional/boards_controller_test.rb | 4 +- test/functional/calendars_controller_test.rb | 55 +- test/functional/comments_controller_test.rb | 10 +- .../context_menus_controller_test.rb | 11 +- ...stom_field_enumerations_controller_test.rb | 14 +- .../custom_fields_controller_test.rb | 87 +- test/functional/documents_controller_test.rb | 67 +- .../email_addresses_controller_test.rb | 5 +- .../enumerations_controller_test.rb | 19 +- test/functional/files_controller_test.rb | 8 +- test/functional/gantts_controller_test.rb | 64 +- test/functional/groups_controller_test.rb | 20 +- test/functional/imports_controller_test.rb | 89 +- .../issue_categories_controller_test.rb | 10 +- .../issue_relations_controller_test.rb | 4 +- .../issue_statuses_controller_test.rb | 25 +- test/functional/issues_controller_test.rb | 835 ++++++-- .../issues_controller_transaction_test.rb | 58 +- .../issues_custom_fields_visibility_test.rb | 36 +- test/functional/journals_controller_test.rb | 13 +- .../mail_handler_controller_test.rb | 20 +- test/functional/members_controller_test.rb | 4 +- test/functional/messages_controller_test.rb | 58 +- test/functional/my_controller_test.rb | 173 +- test/functional/news_controller_test.rb | 28 +- test/functional/previews_controller_test.rb | 101 +- .../principal_memberships_controller_test.rb | 10 +- .../project_enumerations_controller_test.rb | 14 +- test/functional/projects_controller_test.rb | 393 +++- test/functional/queries_controller_test.rb | 280 ++- test/functional/reports_controller_test.rb | 112 +- .../repositories_bazaar_controller_test.rb | 18 +- .../repositories_controller_test.rb | 62 +- .../repositories_cvs_controller_test.rb | 19 +- .../repositories_darcs_controller_test.rb | 178 -- ...repositories_filesystem_controller_test.rb | 15 +- .../repositories_git_controller_test.rb | 108 +- .../repositories_mercurial_controller_test.rb | 78 +- ...repositories_subversion_controller_test.rb | 42 +- test/functional/roles_controller_test.rb | 59 +- test/functional/search_controller_test.rb | 12 +- .../search_custom_fields_visibility_test.rb | 9 +- test/functional/sessions_controller_test.rb | 4 +- test/functional/settings_controller_test.rb | 18 +- test/functional/sys_controller_test.rb | 4 +- test/functional/timelog_controller_test.rb | 426 +++- .../timelog_custom_fields_visibility_test.rb | 99 +- ...troller_test.rb => timelog_report_test.rb} | 107 +- test/functional/trackers_controller_test.rb | 7 +- test/functional/users_controller_test.rb | 121 +- test/functional/versions_controller_test.rb | 98 +- .../versions_custom_fields_visibility_test.rb | 79 + test/functional/watchers_controller_test.rb | 4 +- test/functional/welcome_controller_test.rb | 13 +- test/functional/wiki_controller_test.rb | 154 +- test/functional/wikis_controller_test.rb | 47 +- test/functional/workflows_controller_test.rb | 40 +- .../helpers/activities_helper_test.rb | 6 +- .../helpers/application_helper_test.rb | 966 ++++++--- test/helpers/avatars_helper_test.rb | 93 + .../helpers/custom_fields_helper_test.rb | 33 +- test/{unit => }/helpers/groups_helper_test.rb | 6 +- test/{unit => }/helpers/issues_helper_test.rb | 29 +- .../helpers/journals_helper_test.rb | 9 +- .../{unit => }/helpers/members_helper_test.rb | 6 +- .../helpers/projects_helper_test.rb | 6 +- .../helpers/projects_queries_helper_test.rb | 32 +- .../{unit => }/helpers/queries_helper_test.rb | 8 +- test/{unit => }/helpers/routes_helper_test.rb | 8 +- test/{unit => }/helpers/search_helper_test.rb | 8 +- .../helpers/settings_helper_test.rb | 6 +- test/{unit => }/helpers/sort_helper_test.rb | 6 +- .../{unit => }/helpers/timelog_helper_test.rb | 18 +- test/helpers/version_helper_test.rb | 112 ++ .../helpers/watchers_helper_test.rb | 6 +- test/{unit => }/helpers/wiki_helper_test.rb | 6 +- test/integration/account_test.rb | 63 +- test/integration/admin_test.rb | 6 +- test/integration/api_test/api_routing_test.rb | 4 +- test/integration/api_test/api_test.rb | 15 +- test/integration/api_test/attachments_test.rb | 20 +- .../api_test/authentication_test.rb | 21 +- .../api_test/custom_fields_attribute_test.rb | 47 +- .../api_test/custom_fields_test.rb | 4 +- .../api_test/disabled_rest_api_test.rb | 22 +- .../integration/api_test/enumerations_test.rb | 12 +- test/integration/api_test/files_test.rb | 109 +- test/integration/api_test/groups_test.rb | 12 +- .../api_test/issue_categories_test.rb | 37 +- .../api_test/issue_relations_test.rb | 6 +- .../api_test/issue_statuses_test.rb | 4 +- test/integration/api_test/issues_test.rb | 394 ++-- test/integration/api_test/jsonp_test.rb | 4 +- test/integration/api_test/memberships_test.rb | 8 +- test/integration/api_test/my_test.rb | 105 + test/integration/api_test/news_test.rb | 340 +++- test/integration/api_test/projects_test.rb | 57 +- test/integration/api_test/queries_test.rb | 4 +- test/integration/api_test/roles_test.rb | 9 +- test/integration/api_test/search_test.rb | 6 +- .../integration/api_test/time_entries_test.rb | 113 +- test/integration/api_test/trackers_test.rb | 5 +- test/integration/api_test/users_test.rb | 91 +- test/integration/api_test/versions_test.rb | 69 +- test/integration/api_test/wiki_pages_test.rb | 10 +- test/integration/application_test.rb | 8 +- test/integration/attachments_test.rb | 25 +- test/integration/feeds_test.rb | 4 +- test/integration/issues_test.rb | 20 +- test/integration/layout_test.rb | 6 +- .../field_format/attachment_format_test.rb | 7 +- test/integration/lib/redmine/hook_test.rb | 18 +- .../lib/redmine/menu_manager_test.rb | 39 +- test/integration/lib/redmine/themes_test.rb | 13 +- test/integration/projects_test.rb | 4 +- test/integration/repositories_git_test.rb | 64 +- test/integration/routing/account_test.rb | 4 +- test/integration/routing/activities_test.rb | 4 +- test/integration/routing/admin_test.rb | 4 +- test/integration/routing/attachments_test.rb | 7 +- test/integration/routing/auth_sources_test.rb | 4 +- .../routing/auto_completes_test.rb | 4 +- test/integration/routing/boards_test.rb | 4 +- test/integration/routing/calendars_test.rb | 4 +- test/integration/routing/comments_test.rb | 4 +- .../integration/routing/context_menus_test.rb | 4 +- .../integration/routing/custom_fields_test.rb | 4 +- test/integration/routing/documents_test.rb | 4 +- test/integration/routing/enumerations_test.rb | 4 +- test/integration/routing/files_test.rb | 4 +- test/integration/routing/gantts_test.rb | 4 +- test/integration/routing/groups_test.rb | 4 +- test/integration/routing/imports_test.rb | 7 +- .../routing/issue_categories_test.rb | 4 +- .../routing/issue_relations_test.rb | 4 +- .../routing/issue_statuses_test.rb | 4 +- test/integration/routing/issues_test.rb | 6 +- test/integration/routing/journals_test.rb | 4 +- test/integration/routing/mail_handler_test.rb | 4 +- test/integration/routing/members_test.rb | 4 +- test/integration/routing/messages_test.rb | 4 +- test/integration/routing/my_test.rb | 6 +- test/integration/routing/news_test.rb | 4 +- test/integration/routing/previews_test.rb | 18 +- .../routing/principal_memberships_test.rb | 4 +- .../routing/project_enumerations_test.rb | 4 +- test/integration/routing/projects_test.rb | 4 +- test/integration/routing/queries_test.rb | 4 +- test/integration/routing/reports_test.rb | 4 +- test/integration/routing/repositories_test.rb | 105 +- test/integration/routing/roles_test.rb | 6 +- test/integration/routing/search_test.rb | 4 +- test/integration/routing/settings_test.rb | 4 +- test/integration/routing/sys_test.rb | 4 +- test/integration/routing/timelog_test.rb | 5 +- test/integration/routing/trackers_test.rb | 4 +- test/integration/routing/users_test.rb | 4 +- test/integration/routing/versions_test.rb | 4 +- test/integration/routing/watchers_test.rb | 4 +- test/integration/routing/welcome_test.rb | 6 +- test/integration/routing/wiki_test.rb | 4 +- test/integration/routing/wikis_test.rb | 6 +- test/integration/routing/workflows_test.rb | 4 +- test/integration/sessions_test.rb | 4 +- test/integration/sudo_mode_test.rb | 12 +- test/integration/users_test.rb | 4 +- test/integration/welcome_test.rb | 33 + test/integration/wiki_test.rb | 25 +- test/mailers/empty | 0 test/mocks/open_id_authentication_mock.rb | 4 +- test/models/empty | 0 test/object_helpers.rb | 55 +- test/system/issues_import_test.rb | 53 + .../issues_test.rb} | 156 +- .../my_page_test.rb} | 54 +- test/system/quick_jump_test.rb | 68 + .../sudo_mode_test.rb} | 10 +- .../timelog_test.rb} | 39 +- test/test_helper.rb | 98 +- test/ui/base.rb | 74 - test/unit/activity_test.rb | 8 +- test/unit/attachment_test.rb | 127 +- test/unit/attachment_transaction_test.rb | 8 +- test/unit/auth_source_ldap_test.rb | 50 +- test/unit/board_test.rb | 7 +- test/unit/changeset_test.rb | 39 +- test/unit/comment_test.rb | 9 +- test/unit/custom_field_test.rb | 36 +- test/unit/custom_field_user_format_test.rb | 4 +- test/unit/custom_field_version_format_test.rb | 4 +- test/unit/custom_value_test.rb | 4 +- test/unit/default_data_test.rb | 4 +- test/unit/document_category_test.rb | 6 +- test/unit/document_test.rb | 12 +- test/unit/email_address_test.rb | 33 + test/unit/enabled_module_test.rb | 4 +- test/unit/enumeration_test.rb | 13 +- test/unit/group_test.rb | 7 +- test/unit/helpers/version_helper_test.rb | 54 - test/unit/initializers/patches_test.rb | 61 +- test/unit/issue_category_test.rb | 4 +- test/unit/issue_custom_field_test.rb | 5 +- test/unit/issue_import_test.rb | 86 +- .../unit/issue_nested_set_concurrency_test.rb | 8 +- test/unit/issue_nested_set_test.rb | 8 +- test/unit/issue_priority_test.rb | 11 +- test/unit/issue_relation_test.rb | 4 +- test/unit/issue_scopes_test.rb | 4 +- test/unit/issue_status_test.rb | 21 +- test/unit/issue_subtasking_test.rb | 17 +- test/unit/issue_test.rb | 197 +- test/unit/issue_transaction_test.rb | 6 +- test/unit/journal_observer_test.rb | 42 +- test/unit/journal_test.rb | 6 +- test/unit/lib/redmine/access_control_test.rb | 4 +- .../acts/positioned_with_scope_test.rb | 4 +- .../acts/positioned_without_scope_test.rb | 4 +- test/unit/lib/redmine/ciphering_test.rb | 6 +- test/unit/lib/redmine/codeset_util_test.rb | 31 +- test/unit/lib/redmine/configuration_test.rb | 4 +- test/unit/lib/redmine/export/csv_test.rb | 24 +- .../lib/redmine/export/pdf/issues_pdf_test.rb | 50 + test/unit/lib/redmine/export/pdf_test.rb | 33 +- .../field_format/attachment_format_test.rb | 5 +- .../attachment_format_visibility_test.rb | 5 +- .../redmine/field_format/bool_format_test.rb | 4 +- .../field_format/enumeration_format_test.rb | 4 +- .../redmine/field_format/field_format_test.rb | 12 +- .../redmine/field_format/link_format_test.rb | 18 +- .../redmine/field_format/list_format_test.rb | 8 +- .../field_format/numeric_format_test.rb | 72 +- .../field_format/user_field_format_test.rb | 16 +- .../field_format/version_field_format_test.rb | 9 +- .../unit/lib/redmine/helpers/calendar_test.rb | 6 +- test/unit/lib/redmine/helpers/diff_test.rb | 76 +- test/unit/lib/redmine/helpers/gantt_test.rb | 83 +- test/unit/lib/redmine/helpers/url_test.rb | 36 + test/unit/lib/redmine/hook_test.rb | 5 +- test/unit/lib/redmine/i18n_test.rb | 21 +- test/unit/lib/redmine/info_test.rb | 4 +- .../lib/redmine/menu_manager/mapper_test.rb | 7 +- .../redmine/menu_manager/menu_helper_test.rb | 77 +- .../redmine/menu_manager/menu_item_test.rb | 4 +- test/unit/lib/redmine/menu_manager_test.rb | 4 +- test/unit/lib/redmine/mime_type_test.rb | 10 +- test/unit/lib/redmine/notifiable_test.rb | 4 +- .../lib/redmine/pagination_helper_test.rb | 4 +- test/unit/lib/redmine/pagination_test.rb | 4 +- test/unit/lib/redmine/plugin_test.rb | 78 +- .../unit/lib/redmine/project_jump_box_test.rb | 145 ++ test/unit/lib/redmine/safe_attributes_test.rb | 4 +- .../scm/adapters/bazaar_adapter_test.rb | 4 +- .../redmine/scm/adapters/cvs_adapter_test.rb | 4 +- .../scm/adapters/darcs_adapter_test.rb | 60 - .../scm/adapters/filesystem_adapter_test.rb | 9 +- .../redmine/scm/adapters/git_adapter_test.rb | 168 +- .../scm/adapters/mercurial_adapter_test.rb | 34 +- .../scm/adapters/subversion_adapter_test.rb | 4 +- .../syntax_highlighting/coderay_test.rb | 37 - .../redmine/syntax_highlighting/rouge_test.rb | 65 + test/unit/lib/redmine/themes_test.rb | 4 +- test/unit/lib/redmine/unified_diff_test.rb | 313 +-- .../lib/redmine/utils/date_calculation.rb | 4 +- .../lib/redmine/views/builders/json_test.rb | 19 +- .../lib/redmine/views/builders/xml_test.rb | 8 +- .../views/labelled_form_builder_test.rb | 4 +- .../wiki_formatting/html_parser_test.rb | 34 +- .../redmine/wiki_formatting/macros_test.rb | 128 +- .../markdown_formatter_test.rb | 119 +- .../markdown_html_parser_test.rb | 21 +- .../wiki_formatting/textile_formatter_test.rb | 178 +- .../textile_html_parser_test.rb | 21 +- test/unit/lib/redmine/wiki_formatting_test.rb | 21 +- test/unit/lib/redmine_test.rb | 4 +- test/unit/mail_handler_test.rb | 244 ++- test/unit/mailer_localisation_test.rb | 141 ++ test/unit/mailer_test.rb | 506 +++-- test/unit/member_test.rb | 8 +- test/unit/message_test.rb | 7 +- test/unit/news_test.rb | 6 +- test/unit/principal_test.rb | 26 +- test/unit/project_copy_test.rb | 62 +- test/unit/project_members_inheritance_test.rb | 4 +- .../project_nested_set_concurrency_test.rb | 8 +- test/unit/project_nested_set_test.rb | 5 +- test/unit/project_query_test.rb | 63 + test/unit/project_test.rb | 96 +- test/unit/query_test.rb | 343 +++- test/unit/repository_bazaar_test.rb | 25 +- test/unit/repository_cvs_test.rb | 20 +- test/unit/repository_darcs_test.rb | 129 -- test/unit/repository_filesystem_test.rb | 7 +- test/unit/repository_git_test.rb | 40 +- test/unit/repository_mercurial_test.rb | 24 +- test/unit/repository_subversion_test.rb | 6 +- test/unit/repository_test.rb | 54 +- test/unit/role_test.rb | 4 +- test/unit/search_test.rb | 11 +- test/unit/setting_test.rb | 39 +- test/unit/time_entry_activity_test.rb | 7 +- test/unit/time_entry_import_test.rb | 196 ++ test/unit/time_entry_query_test.rb | 46 +- test/unit/time_entry_test.rb | 82 +- test/unit/token_test.rb | 4 +- test/unit/tracker_test.rb | 14 +- test/unit/user_preference_test.rb | 4 +- test/unit/user_test.rb | 99 +- test/unit/version_test.rb | 35 +- test/unit/watcher_test.rb | 4 +- test/unit/wiki_content_test.rb | 40 +- test/unit/wiki_content_version_test.rb | 22 +- test/unit/wiki_page_test.rb | 18 +- test/unit/wiki_redirect_test.rb | 4 +- test/unit/wiki_test.rb | 10 +- test/unit/workflow_test.rb | 4 +- test/unit/workflow_transition_test.rb | 4 +- 1593 files changed, 36180 insertions(+), 19489 deletions(-) create mode 100644 .rubocop.yml create mode 100644 .rubocop_todo.yml create mode 100644 app/helpers/avatars_helper.rb create mode 100644 app/helpers/projects_queries_helper.rb create mode 100644 app/models/project_query.rb delete mode 100644 app/models/repository/darcs.rb create mode 100644 app/models/time_entry_import.rb create mode 100644 app/models/wiki_content_version.rb create mode 100644 app/views/activities/_activities.html.erb delete mode 100644 app/views/auto_completes/issues.html.erb create mode 100644 app/views/common/_markup.html.erb create mode 100644 app/views/common/_no_preview.html.erb create mode 100644 app/views/custom_fields/_visibility_by_project_selector.html.erb create mode 100644 app/views/custom_fields/_visibility_by_role_selector.html.erb create mode 100644 app/views/custom_fields/_visibility_by_tracker_selector.html.erb rename app/views/imports/{_fields_mapping.html.erb => _issues_fields_mapping.html.erb} (56%) create mode 100644 app/views/imports/_issues_mapping.html.erb create mode 100644 app/views/imports/_issues_mapping.js.erb create mode 100644 app/views/imports/_issues_saved_objects.html.erb create mode 100644 app/views/imports/_issues_sidebar.html.erb create mode 100644 app/views/imports/_time_entries_fields_mapping.html.erb create mode 100644 app/views/imports/_time_entries_mapping.html.erb create mode 100644 app/views/imports/_time_entries_mapping.js.erb create mode 100644 app/views/imports/_time_entries_saved_objects.html.erb create mode 100644 app/views/imports/_time_entries_sidebar.html.erb create mode 100644 app/views/issues/_action_menu_edit.html.erb delete mode 100644 app/views/issues/_changesets.html.erb create mode 100644 app/views/issues/_trackers_description.html.erb create mode 100644 app/views/issues/tabs/_changesets.html.erb rename app/views/issues/{ => tabs}/_history.html.erb (66%) create mode 100644 app/views/issues/tabs/_time_entries.html.erb create mode 100644 app/views/my/account.api.rsb create mode 100644 app/views/my/blocks/_activity.html.erb create mode 100644 app/views/news/show.api.rsb delete mode 100644 app/views/previews/issue.html.erb create mode 100644 app/views/projects/_board.html.erb create mode 100644 app/views/projects/_list.html.erb create mode 100644 app/views/projects/_sidebar.html.erb create mode 100644 app/views/projects/bookmark.js.erb create mode 100644 app/views/projects/settings/_issues.html.erb delete mode 100644 app/views/projects/settings/_modules.html.erb delete mode 100644 app/views/projects/settings/_wiki.html.erb create mode 100644 app/views/settings/_users.html.erb create mode 100644 app/views/timelog/_sidebar.html.erb create mode 100644 app/views/timelog/bulk_edit.js.erb delete mode 100644 app/views/welcome/robots.html.erb create mode 100644 app/views/welcome/robots.text.erb create mode 100644 bin/changelog.rb create mode 100644 db/migrate/20170723112801_rename_comments_to_content.rb create mode 100644 db/migrate/20180501132547_add_author_id_to_time_entries.rb create mode 100644 db/migrate/20180913072918_add_verify_peer_to_auth_sources.rb create mode 100644 db/migrate/20180923082945_change_sqlite_booleans_to_0_and_1.rb create mode 100644 db/migrate/20180923091603_change_sqlite_booleans_default.rb create mode 100644 db/migrate/20190315094151_change_custom_values_value_limit.rb create mode 100644 db/migrate/20190315102101_add_trackers_description.rb create mode 100644 db/migrate/20190510070108_add_unique_id_to_import_items.rb create mode 100644 db/migrate/20190620135549_change_roles_name_limit.rb delete mode 100644 lib/SVG/GPL.txt delete mode 100644 lib/SVG/Graph/Bar.rb delete mode 100644 lib/SVG/Graph/BarBase.rb delete mode 100644 lib/SVG/Graph/BarHorizontal.rb delete mode 100644 lib/SVG/Graph/Graph.rb delete mode 100644 lib/SVG/Graph/Line.rb delete mode 100644 lib/SVG/Graph/Pie.rb delete mode 100644 lib/SVG/Graph/Plot.rb delete mode 100644 lib/SVG/Graph/Schedule.rb delete mode 100644 lib/SVG/Graph/TimeSeries.rb delete mode 100644 lib/SVG/LICENSE.txt create mode 100644 lib/generators/redmine_plugin_migration/USAGE create mode 100644 lib/generators/redmine_plugin_migration/redmine_plugin_migration_generator.rb create mode 100644 lib/generators/redmine_plugin_migration/templates/migration.rb.tt delete mode 100644 lib/plugins/acts_as_list/README delete mode 100644 lib/plugins/acts_as_list/init.rb delete mode 100644 lib/plugins/acts_as_list/lib/active_record/acts/list.rb delete mode 100644 lib/plugins/acts_as_list/test/list_test.rb delete mode 100644 lib/plugins/acts_as_versioned/CHANGELOG delete mode 100644 lib/plugins/acts_as_versioned/MIT-LICENSE delete mode 100644 lib/plugins/acts_as_versioned/README delete mode 100644 lib/plugins/acts_as_versioned/RUNNING_UNIT_TESTS delete mode 100644 lib/plugins/acts_as_versioned/Rakefile delete mode 100644 lib/plugins/acts_as_versioned/init.rb delete mode 100644 lib/plugins/acts_as_versioned/lib/acts_as_versioned.rb delete mode 100644 lib/plugins/acts_as_versioned/test/abstract_unit.rb delete mode 100644 lib/plugins/acts_as_versioned/test/database.yml delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/authors.yml delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/landmark.rb delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/landmark_versions.yml delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/landmarks.yml delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/locked_pages.yml delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/locked_pages_revisions.yml delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/page.rb delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/page_versions.yml delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/pages.yml delete mode 100644 lib/plugins/acts_as_versioned/test/fixtures/widget.rb delete mode 100644 lib/plugins/acts_as_versioned/test/migration_test.rb delete mode 100644 lib/plugins/acts_as_versioned/test/schema.rb delete mode 100644 lib/plugins/acts_as_versioned/test/versioned_test.rb delete mode 100644 lib/redmine/core_ext/date.rb create mode 100644 lib/redmine/project_jump_box.rb delete mode 100644 lib/redmine/scm/adapters/darcs_adapter.rb delete mode 100644 public/images/1downarrow.png delete mode 100644 public/images/1uparrow.png delete mode 100644 public/images/2downarrow.png delete mode 100644 public/images/2uparrow.png create mode 100644 public/images/3_bullets.png delete mode 100644 public/images/arrow_collapsed.png delete mode 100644 public/images/arrow_expanded.png create mode 100644 public/images/arrow_left.png create mode 100644 public/images/arrow_right.png create mode 100644 public/images/arrow_up.png delete mode 100644 public/images/bullet_arrow_left.png delete mode 100644 public/images/bullet_arrow_right.png create mode 100644 public/images/database_go.png delete mode 100644 public/images/draft.png create mode 100644 public/images/tag_blue_add.png create mode 100644 public/images/tag_blue_delete.png create mode 100644 public/images/transparent.png create mode 100644 public/javascripts/Chart.bundle.min.js rename public/javascripts/{jquery-1.11.1-ui-1.11.0-ujs-3.1.4.js => jquery-2.2.4-ui-1.11.0-ujs-5.2.3.js} (69%) delete mode 100644 public/javascripts/jstoolbar/jstoolbar-textile.min.js create mode 100644 public/javascripts/tribute-3.7.3.min.js create mode 100644 public/javascripts/tribute.min.js.map create mode 100644 public/stylesheets/tribute-3.7.3.css delete mode 100755 script/about delete mode 100755 script/rails create mode 100644 test/application_system_test_case.rb create mode 100644 test/controllers/empty delete mode 100644 test/fixtures/configuration/default.yml delete mode 100644 test/fixtures/configuration/empty.yml delete mode 100644 test/fixtures/configuration/no_default.yml delete mode 100644 test/fixtures/configuration/overrides.yml create mode 100644 test/fixtures/files/2019/04/190430092344_redmine_logo.ai.unknown create mode 100644 test/fixtures/files/2019/05/190511141819_ecookbook-gantt.pdf create mode 100644 test/fixtures/files/hello.js create mode 100644 test/fixtures/files/import_dates_ja.csv create mode 100644 test/fixtures/files/import_subtasks_with_unique_id.csv create mode 100644 test/fixtures/files/import_time_entries.csv create mode 100644 test/fixtures/files/testfile.md create mode 100644 test/fixtures/files/testfile.textile create mode 100644 test/fixtures/mail_handler/different_contents_in_text_and_html.eml create mode 100644 test/fixtures/mail_handler/fullname_of_sender_in_parentheses.eml create mode 100644 test/fixtures/mail_handler/subject_japanese_3.eml create mode 100644 test/fixtures/mail_handler/ticket_with_localized_private_flag.eml create mode 100644 test/fixtures/plugins/other_plugin/_other_plugin_settings.html.erb delete mode 100644 test/fixtures/repositories/darcs_repository.tar.gz create mode 100644 test/functional/application_controller_test.rb delete mode 100644 test/functional/repositories_darcs_controller_test.rb rename test/functional/{time_entry_reports_controller_test.rb => timelog_report_test.rb} (78%) create mode 100644 test/functional/versions_custom_fields_visibility_test.rb rename test/{unit => }/helpers/activities_helper_test.rb (95%) rename test/{unit => }/helpers/application_helper_test.rb (66%) create mode 100644 test/helpers/avatars_helper_test.rb rename test/{unit => }/helpers/custom_fields_helper_test.rb (76%) rename test/{unit => }/helpers/groups_helper_test.rb (92%) rename test/{unit => }/helpers/issues_helper_test.rb (94%) rename test/{unit => }/helpers/journals_helper_test.rb (91%) rename test/{unit => }/helpers/members_helper_test.rb (92%) rename test/{unit => }/helpers/projects_helper_test.rb (95%) rename lib/redmine/core_ext/date/calculations.rb => test/helpers/projects_queries_helper_test.rb (57%) rename test/{unit => }/helpers/queries_helper_test.rb (96%) rename test/{unit => }/helpers/routes_helper_test.rb (92%) rename test/{unit => }/helpers/search_helper_test.rb (93%) rename test/{unit => }/helpers/settings_helper_test.rb (89%) rename test/{unit => }/helpers/sort_helper_test.rb (95%) rename test/{unit => }/helpers/timelog_helper_test.rb (83%) create mode 100644 test/helpers/version_helper_test.rb rename test/{unit => }/helpers/watchers_helper_test.rb (94%) rename test/{unit => }/helpers/wiki_helper_test.rb (92%) create mode 100644 test/integration/api_test/my_test.rb create mode 100644 test/integration/welcome_test.rb create mode 100644 test/mailers/empty create mode 100644 test/models/empty create mode 100644 test/system/issues_import_test.rb rename test/{ui/issues_test_ui.rb => system/issues_test.rb} (73%) rename test/{ui/my_page_test_ui.rb => system/my_page_test.rb} (54%) create mode 100644 test/system/quick_jump_test.rb rename test/{ui/sudo_mode_test_ui.rb => system/sudo_mode_test.rb} (90%) rename test/{ui/timelog_test_ui.rb => system/timelog_test.rb} (68%) delete mode 100644 test/ui/base.rb create mode 100644 test/unit/email_address_test.rb delete mode 100644 test/unit/helpers/version_helper_test.rb create mode 100644 test/unit/lib/redmine/export/pdf/issues_pdf_test.rb create mode 100644 test/unit/lib/redmine/helpers/url_test.rb create mode 100644 test/unit/lib/redmine/project_jump_box_test.rb delete mode 100644 test/unit/lib/redmine/scm/adapters/darcs_adapter_test.rb delete mode 100644 test/unit/lib/redmine/syntax_highlighting/coderay_test.rb create mode 100644 test/unit/lib/redmine/syntax_highlighting/rouge_test.rb create mode 100644 test/unit/mailer_localisation_test.rb create mode 100644 test/unit/project_query_test.rb delete mode 100644 test/unit/repository_darcs_test.rb create mode 100644 test/unit/time_entry_import_test.rb diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..a893304 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,103 @@ +inherit_from: .rubocop_todo.yml + +AllCops: + TargetRubyVersion: 2.3 + TargetRailsVersion: 5.2 + + Exclude: + - '**/vendor/**/*' + - '**/tmp/**/*' + - '**/bin/**/*' + - '**/plugins/**/*' + - '**/extra/**/*' + - '**/lib/generators/**/templates/*' + - '**/lib/tasks/**/*' + - '**/files/**/*' + - 'db/schema.rb' + +# Enable extensions + +require: + - rubocop-performance + - rubocop-rails + +# Rules for Redmine + +Bundler/OrderedGems: + Enabled: false + +Layout/EmptyLineBetweenDefs: + AllowAdjacentOneLineDefs: true + +Layout/SpaceBeforeBlockBraces: + # "space" is used more than "no_space". + # But "no_space" is more natural in one liner. + # str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/") + Enabled: false + +# You can see results by "rubocop --only Layout/SpaceInsideBlockBraces" +Layout/SpaceInsideBlockBraces: + EnforcedStyle: no_space + SpaceBeforeBlockParameters: false + +# You can see results by "rubocop --only Layout/SpaceInsideHashLiteralBraces" +Layout/SpaceInsideHashLiteralBraces: + EnforcedStyle: no_space + +Layout/TrailingWhitespace: + AllowInHeredoc: true + +Lint/HandleExceptions: + AllowComments: true + +Metrics: + Enabled: false + +Naming/AccessorMethodName: + Enabled: false + +Naming/BinaryOperatorParameterName: + Enabled: false + +Naming/PredicateName: + Enabled: false + +Rails/BulkChangeTable: + Exclude: + - 'db/migrate/20120714122200_add_workflows_rule_fields.rb' + - 'db/migrate/20131214094309_remove_custom_fields_min_max_length_default_values.rb' + +Rails/HelperInstanceVariable: + Enabled: false + +# Configuration parameters: AllowedChars. +Style/AsciiComments: + Exclude: + # Copyright credit has non ascii character. + # We can not change nor remove it. + - 'app/models/repository/git.rb' + +Style/FormatStringToken: + Enabled: false + +Style/FrozenStringLiteralComment: + Enabled: true + EnforcedStyle: always + Exclude: + - 'db/**/*.rb' + - 'Gemfile' + - 'Rakefile' + - 'config.ru' + - 'config/additional_environment.rb' + +Style/HashSyntax: + Enabled: true + EnforcedStyle: no_mixed_keys + +Style/IdenticalConditionalBranches: + Exclude: + - 'config/initializers/10-patches.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + +Style/TrailingCommaInArrayLiteral: + Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..39fd8a0 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,1637 @@ +# This configuration was generated by +# `rubocop --auto-gen-config --exclude-limit 20 --no-offense-counts --no-auto-gen-timestamp` +# using RuboCop version 0.76.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: with_first_argument, with_fixed_indentation +Layout/AlignArguments: + Exclude: + - 'config/application.rb' + - 'lib/redmine/scm/adapters/bazaar_adapter.rb' + - 'lib/redmine/scm/adapters/subversion_adapter.rb' + - 'test/functional/journals_controller_test.rb' + - 'test/functional/my_controller_test.rb' + - 'test/functional/roles_controller_test.rb' + - 'test/integration/api_test/attachments_test.rb' + - 'test/integration/api_test/groups_test.rb' + - 'test/integration/api_test/issue_relations_test.rb' + - 'test/integration/api_test/memberships_test.rb' + - 'test/integration/api_test/projects_test.rb' + - 'test/integration/api_test/wiki_pages_test.rb' + - 'test/test_helper.rb' + - 'test/unit/changeset_test.rb' + - 'test/unit/lib/redmine/field_format/version_field_format_test.rb' + - 'test/unit/lib/redmine/wiki_formatting/html_parser_test.rb' + - 'test/unit/lib/redmine/wiki_formatting/markdown_formatter_test.rb' + - 'test/unit/lib/redmine/wiki_formatting/markdown_html_parser_test.rb' + - 'test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb' + - 'test/unit/lib/redmine/wiki_formatting/textile_html_parser_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. +# SupportedHashRocketStyles: key, separator, table +# SupportedColonStyles: key, separator, table +# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit +Layout/AlignHash: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentOneStep, IndentationWidth. +# SupportedStyles: case, end +Layout/CaseIndentation: + Exclude: + - 'config/initializers/10-patches.rb' + +# Cop supports --auto-correct. +Layout/ClosingHeredocIndentation: + Exclude: + - 'test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb' + - 'test/unit/lib/redmine/wiki_formatting_test.rb' + +# Cop supports --auto-correct. +Layout/ClosingParenthesisIndentation: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: leading, trailing +Layout/DotPosition: + Enabled: false + +# Cop supports --auto-correct. +Layout/EmptyLineAfterGuardClause: + Enabled: false + +# Cop supports --auto-correct. +Layout/EmptyLines: + Exclude: + - 'config/routes.rb' + - 'db/migrate/001_setup.rb' + - 'lib/redmine/sudo_mode.rb' + - 'test/helpers/application_helper_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: around, only_before +Layout/EmptyLinesAroundAccessModifier: + Exclude: + - 'config/initializers/10-patches.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only +Layout/EmptyLinesAroundClassBody: + Enabled: false + +# Cop supports --auto-correct. +Layout/EmptyLinesAroundExceptionHandlingKeywords: + Exclude: + - 'app/controllers/activities_controller.rb' + - 'app/controllers/imports_controller.rb' + - 'app/controllers/wiki_controller.rb' + - 'test/functional/settings_controller_test.rb' + +# Cop supports --auto-correct. +Layout/EmptyLinesAroundMethodBody: + Exclude: + - 'app/models/query.rb' + - 'db/migrate/001_setup.rb' + - 'db/migrate/20111201201315_add_unique_index_to_issue_relations.rb' + - 'test/functional/journals_controller_test.rb' + - 'test/functional/users_controller_test.rb' + - 'test/integration/account_test.rb' + - 'test/unit/attachment_test.rb' + - 'test/unit/lib/redmine/menu_manager/mapper_test.rb' + - 'test/unit/lib/redmine/menu_manager/menu_helper_test.rb' + - 'test/unit/lib/redmine/unified_diff_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines +Layout/EmptyLinesAroundModuleBody: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. +Layout/ExtraSpacing: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses +Layout/IndentFirstArgument: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_brackets +Layout/IndentFirstArrayElement: + Exclude: + - 'app/models/setting.rb' + - 'lib/redmine/nested_set/issue_nested_set.rb' + - 'lib/redmine/nested_set/project_nested_set.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + - 'test/functional/auth_sources_controller_test.rb' + - 'test/functional/repositories_mercurial_controller_test.rb' + - 'test/functional/settings_controller_test.rb' + - 'test/helpers/activities_helper_test.rb' + - 'test/helpers/issues_helper_test.rb' + - 'test/unit/issue_test.rb' + - 'test/unit/lib/redmine/scm/adapters/git_adapter_test.rb' + - 'test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb' + - 'test/unit/project_test.rb' + - 'test/unit/repository_git_test.rb' + - 'test/unit/version_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_braces +Layout/IndentFirstHashElement: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: squiggly, active_support, powerpack, unindent +Layout/IndentHeredoc: + Exclude: + - 'test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb' + - 'test/unit/lib/redmine/wiki_formatting_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: normal, indented_internal_methods +Layout/IndentationConsistency: + Exclude: + - 'test/mocks/open_id_authentication_mock.rb' + +# Cop supports --auto-correct. +# Configuration parameters: Width, IgnoredPatterns. +Layout/IndentationWidth: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineArrayBraceLayout: + Exclude: + - 'app/helpers/settings_helper.rb' + - 'app/helpers/users_helper.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineHashBraceLayout: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineMethodCallBraceLayout: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented, indented_relative_to_receiver +Layout/MultilineMethodCallIndentation: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented +Layout/MultilineOperationIndentation: + Enabled: false + +# Cop supports --auto-correct. +Layout/RescueEnsureAlignment: + Exclude: + - 'db/migrate/085_add_role_tracker_old_status_index_to_workflows.rb' + +# Cop supports --auto-correct. +Layout/SpaceAfterComma: + Enabled: false + +# Cop supports --auto-correct. +Layout/SpaceAfterNot: + Exclude: + - 'app/controllers/application_controller.rb' + - 'app/models/repository/cvs.rb' + - 'app/models/repository/git.rb' + - 'lib/redmine/codeset_util.rb' + - 'test/functional/account_controller_test.rb' + - 'test/functional/documents_controller_test.rb' + - 'test/functional/issues_controller_test.rb' + - 'test/functional/repositories_git_controller_test.rb' + - 'test/functional/timelog_controller_test.rb' + - 'test/functional/workflows_controller_test.rb' + - 'test/helpers/application_helper_test.rb' + - 'test/unit/attachment_test.rb' + - 'test/unit/lib/redmine/export/pdf_test.rb' + - 'test/unit/project_copy_test.rb' + - 'test/unit/project_test.rb' + - 'test/unit/query_test.rb' + - 'test/unit/role_test.rb' + - 'test/unit/user_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: space, no_space +Layout/SpaceAroundEqualsInParameterDefault: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment. +Layout/SpaceAroundOperators: + Enabled: false + +# Cop supports --auto-correct. +Layout/SpaceBeforeComma: + Exclude: + - 'test/mocks/open_id_authentication_mock.rb' + +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment. +Layout/SpaceBeforeFirstArg: + Exclude: + - 'test/helpers/issues_helper_test.rb' + - 'test/helpers/search_helper_test.rb' + - 'test/unit/lib/redmine/menu_manager_test.rb' + +# Cop supports --auto-correct. +Layout/SpaceBeforeSemicolon: + Exclude: + - 'app/models/user_preference.rb' + - 'config/initializers/10-patches.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: require_no_space, require_space +Layout/SpaceInLambdaLiteral: + Exclude: + - 'app/helpers/application_helper.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. +# SupportedStyles: space, no_space, compact +# SupportedStylesForEmptyBrackets: space, no_space +Layout/SpaceInsideArrayLiteralBrackets: + Exclude: + - 'app/controllers/projects_controller.rb' + - 'app/helpers/timelog_helper.rb' + - 'app/models/query.rb' + - 'lib/diff.rb' + - 'lib/redmine/i18n.rb' + - 'test/mocks/open_id_authentication_mock.rb' + - 'test/unit/mailer_localisation_test.rb' + - 'test/unit/mailer_test.rb' + - 'test/unit/search_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. +# SupportedStyles: space, no_space +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceInsideBlockBraces: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. +# SupportedStyles: space, no_space, compact +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceInsideHashLiteralBraces: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: space, no_space +Layout/SpaceInsideParens: + Exclude: + - 'app/controllers/application_controller.rb' + - 'app/helpers/issues_helper.rb' + - 'app/models/auth_source_ldap.rb' + - 'app/models/repository/cvs.rb' + - 'lib/redmine/scm/adapters/abstract_adapter.rb' + - 'lib/redmine/scm/adapters/cvs_adapter.rb' + - 'lib/redmine/scm/adapters/git_adapter.rb' + - 'lib/redmine/sudo_mode.rb' + - 'lib/redmine/wiki_formatting/textile/formatter.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + - 'test/helpers/application_helper_test.rb' + - 'test/unit/changeset_test.rb' + - 'test/unit/issue_subtasking_test.rb' + - 'test/unit/lib/redmine/export/pdf_test.rb' + - 'test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb' + - 'test/unit/query_test.rb' + - 'test/unit/repository_test.rb' + - 'test/unit/user_test.rb' + +# Cop supports --auto-correct. +Layout/SpaceInsidePercentLiteralDelimiters: + Exclude: + - 'app/models/project.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: space, no_space +Layout/SpaceInsideStringInterpolation: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/helpers/workflows_helper.rb' + - 'app/models/issue_query.rb' + - 'app/models/mail_handler.rb' + - 'lib/redmine/core_ext/string/inflections.rb' + - 'test/integration/admin_test.rb' + +Lint/AmbiguousBlockAssociation: + Enabled: false + +Lint/AmbiguousOperator: + Exclude: + - 'app/controllers/application_controller.rb' + - 'app/helpers/application_helper.rb' + - 'test/unit/custom_field_test.rb' + - 'test/unit/member_test.rb' + +Lint/AmbiguousRegexpLiteral: + Enabled: false + +# Configuration parameters: AllowSafeAssignment. +Lint/AssignmentInCondition: + Enabled: false + +# Cop supports --auto-correct. +Lint/DeprecatedClassMethods: + Exclude: + - 'Gemfile' + - 'app/models/import.rb' + - 'config/application.rb' + - 'config/boot.rb' + - 'config/routes.rb' + - 'lib/redmine/scm/adapters/abstract_adapter.rb' + - 'lib/redmine/thumbnail.rb' + - 'lib/redmine/utils.rb' + - 'test/functional/issues_controller_test.rb' + - 'test/unit/attachment_test.rb' + - 'test/unit/issue_import_test.rb' + +Lint/EmptyWhen: + Exclude: + - 'app/controllers/issues_controller.rb' + - 'app/controllers/wiki_controller.rb' + +# Configuration parameters: AllowComments. +Lint/HandleExceptions: + Exclude: + - 'app/controllers/activities_controller.rb' + - 'app/models/import.rb' + - 'db/migrate/085_add_role_tracker_old_status_index_to_workflows.rb' + - 'lib/redmine/scm/adapters/cvs_adapter.rb' + - 'lib/redmine/scm/adapters/subversion_adapter.rb' + +Lint/IneffectiveAccessModifier: + Exclude: + - 'app/models/auth_source_ldap.rb' + +Lint/InterpolationCheck: + Exclude: + - 'app/models/user.rb' + +# Cop supports --auto-correct. +Lint/LiteralInInterpolation: + Exclude: + - 'test/unit/mail_handler_test.rb' + +Lint/Loop: + Exclude: + - 'lib/redmine/helpers/gantt.rb' + +Lint/ParenthesesAsGroupedExpression: + Exclude: + - 'lib/redmine/field_format.rb' + - 'test/functional/account_controller_test.rb' + - 'test/functional/email_addresses_controller_test.rb' + - 'test/functional/my_controller_test.rb' + - 'test/functional/settings_controller_test.rb' + - 'test/functional/users_controller_test.rb' + - 'test/helpers/application_helper_test.rb' + - 'test/unit/attachment_test.rb' + - 'test/unit/lib/redmine/export/pdf_test.rb' + +# Cop supports --auto-correct. +Lint/SendWithMixinArgument: + Exclude: + - 'lib/redmine/acts/positioned.rb' + - 'test/object_helpers.rb' + +Lint/ShadowingOuterLocalVariable: + Enabled: false + +# Cop supports --auto-correct. +Lint/StringConversionInInterpolation: + Exclude: + - 'lib/redmine/export/pdf/issues_pdf_helper.rb' + - 'test/functional/repositories_filesystem_controller_test.rb' + - 'test/functional/repositories_git_controller_test.rb' + - 'test/functional/repositories_mercurial_controller_test.rb' + +# Cop supports --auto-correct. +Lint/UnifiedInteger: + Exclude: + - 'test/unit/query_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. +Lint/UnusedBlockArgument: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods. +Lint/UnusedMethodArgument: + Enabled: false + +Lint/UriEscapeUnescape: + Exclude: + - 'lib/redmine/field_format.rb' + - 'lib/redmine/scm/adapters/subversion_adapter.rb' + - 'test/functional/wiki_controller_test.rb' + +Lint/UselessAssignment: + Enabled: false + +# Configuration parameters: CheckForMethodsWithNoSideEffects. +Lint/Void: + Exclude: + - 'app/models/query.rb' + - 'app/models/time_entry.rb' + - 'app/models/wiki_content_version.rb' + - 'lib/redmine/unified_diff.rb' + +Naming/ConstantName: + Exclude: + - 'app/models/document_category.rb' + - 'app/models/issue_priority.rb' + - 'app/models/time_entry_activity.rb' + - 'lib/redmine/helpers/gantt.rb' + +# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS +Naming/FileName: + Exclude: + - 'config/initializers/00-core_plugins.rb' + - 'config/initializers/10-patches.rb' + - 'config/initializers/20-mime_types.rb' + - 'config/initializers/30-redmine.rb' + +# Configuration parameters: EnforcedStyleForLeadingUnderscores. +# SupportedStylesForLeadingUnderscores: disallowed, required, optional +Naming/MemoizedInstanceVariableName: + Exclude: + - 'app/controllers/email_addresses_controller.rb' + - 'app/controllers/users_controller.rb' + - 'app/controllers/workflows_controller.rb' + - 'app/models/issue.rb' + - 'app/models/project.rb' + - 'app/models/query.rb' + - 'app/models/role.rb' + - 'lib/redmine/field_format.rb' + - 'lib/redmine/helpers/calendar.rb' + - 'lib/redmine/search.rb' + +# Configuration parameters: EnforcedStyle, IgnoredPatterns. +# SupportedStyles: snake_case, camelCase +Naming/MethodName: + Exclude: + - 'lib/redmine/export/pdf.rb' + - 'lib/redmine/scm/adapters/cvs_adapter.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + - 'test/helpers/application_helper_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: PreferredName. +Naming/RescuedExceptionsVariableName: + Exclude: + - 'app/models/user.rb' + - 'lib/redmine/scm/adapters/abstract_adapter.rb' + - 'lib/redmine/scm/adapters/filesystem_adapter.rb' + +# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. +# AllowedNames: io, id, to, by, on, in, at, ip, db, os +Naming/UncommunicativeMethodParamName: + Enabled: false + +# Configuration parameters: EnforcedStyle. +# SupportedStyles: snake_case, camelCase +Naming/VariableName: + Exclude: + - 'lib/redmine/scm/adapters/cvs_adapter.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + +# Configuration parameters: EnforcedStyle. +# SupportedStyles: snake_case, normalcase, non_integer +Naming/VariableNumber: + Exclude: + - 'test/functional/versions_controller_test.rb' + - 'test/helpers/application_helper_test.rb' + - 'test/unit/lib/redmine/export/pdf_test.rb' + - 'test/unit/lib/redmine/scm/adapters/git_adapter_test.rb' + - 'test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb' + - 'test/unit/project_test.rb' + +Performance/FixedSize: + Exclude: + - 'test/integration/api_test/issues_test.rb' + - 'test/integration/attachments_test.rb' + +# Cop supports --auto-correct. +Performance/RedundantMatch: + Exclude: + - 'app/models/issue_relation.rb' + - 'lib/redmine/wiki_formatting/textile/formatter.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + +# Cop supports --auto-correct. +# Configuration parameters: MaxKeyValuePairs. +Performance/RedundantMerge: + Exclude: + - 'app/controllers/issues_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/avatars_helper.rb' + - 'app/helpers/custom_fields_helper.rb' + - 'app/helpers/workflows_helper.rb' + - 'app/models/auth_source_ldap.rb' + - 'app/models/principal.rb' + - 'lib/redmine/access_control.rb' + - 'test/functional/imports_controller_test.rb' + - 'test/unit/issue_import_test.rb' + - 'test/unit/time_entry_import_test.rb' + +# Cop supports --auto-correct. +Performance/StringReplacement: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/helpers/imports_helper.rb' + - 'app/helpers/settings_helper.rb' + - 'lib/redmine/core_ext/string/conversions.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + - 'test/functional/repositories_cvs_controller_test.rb' + - 'test/functional/repositories_git_controller_test.rb' + - 'test/helpers/application_helper_test.rb' + - 'test/integration/repositories_git_test.rb' + - 'test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb' + - 'test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb' + - 'test/unit/repository_cvs_test.rb' + - 'test/unit/repository_git_test.rb' + +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/ActiveRecordOverride: + Exclude: + - 'app/models/email_address.rb' + - 'app/models/issue.rb' + - 'app/models/journal.rb' + - 'app/models/member.rb' + +# Cop supports --auto-correct. +Rails/ApplicationRecord: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: **/test/**/* +Rails/AssertNot: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: NilOrEmpty, NotPresent, UnlessPresent. +Rails/Blank: + Exclude: + - 'app/controllers/application_controller.rb' + - 'app/controllers/context_menus_controller.rb' + - 'app/controllers/repositories_controller.rb' + - 'app/controllers/watchers_controller.rb' + - 'app/helpers/queries_helper.rb' + - 'app/helpers/repositories_helper.rb' + - 'app/models/mailer.rb' + - 'app/models/query.rb' + - 'app/models/repository/git.rb' + - 'app/models/role.rb' + - 'lib/redmine/field_format.rb' + - 'lib/redmine/wiki_formatting/macros.rb' + +# Configuration parameters: Include. +# Include: db/migrate/*.rb +Rails/CreateTableWithTimestamps: + Enabled: false + +# Configuration parameters: EnforcedStyle. +# SupportedStyles: strict, flexible +Rails/Date: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforceForPrefixed. +Rails/Delegate: + Exclude: + - 'app/models/changeset.rb' + - 'app/models/custom_field.rb' + - 'app/models/custom_field_enumeration.rb' + - 'app/models/custom_field_value.rb' + - 'app/models/custom_value.rb' + - 'app/models/group.rb' + - 'app/models/message.rb' + - 'app/models/repository.rb' + - 'app/models/repository/git.rb' + - 'app/models/time_entry_activity.rb' + - 'app/models/wiki_content.rb' + - 'app/models/wiki_content_version.rb' + - 'lib/redmine/menu_manager.rb' + +# Cop supports --auto-correct. +# Configuration parameters: Whitelist. +# Whitelist: find_by_sql +Rails/DynamicFindBy: + Enabled: false + +# Configuration parameters: Include. +# Include: app/**/*.rb, config/**/*.rb, lib/**/*.rb +Rails/Exit: + Exclude: + - 'lib/**/*.rake' + - 'config/environment.rb' + - 'config/initializers/10-patches.rb' + - 'config/routes.rb' + +# Configuration parameters: EnforcedStyle. +# SupportedStyles: slashes, arguments +Rails/FilePath: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/FindBy: + Exclude: + - 'app/models/attachment.rb' + - 'app/models/enumeration.rb' + - 'app/models/issue_import.rb' + - 'app/models/repository.rb' + - 'app/models/repository/cvs.rb' + - 'app/models/repository/git.rb' + - 'app/models/repository/mercurial.rb' + - 'app/models/time_entry_query.rb' + - 'app/models/user.rb' + - 'app/models/wiki.rb' + - 'app/models/wiki_content_version.rb' + +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/FindEach: + Exclude: + - 'app/models/auth_source.rb' + - 'app/models/group.rb' + - 'app/models/issue.rb' + - 'app/models/issue_status.rb' + - 'app/models/project.rb' + - 'app/models/query.rb' + - 'app/models/repository.rb' + - 'app/models/setting.rb' + - 'app/models/watcher.rb' + - 'app/models/wiki_page.rb' + +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/HasAndBelongsToMany: + Exclude: + - 'app/models/changeset.rb' + - 'app/models/custom_field.rb' + - 'app/models/group.rb' + - 'app/models/issue.rb' + - 'app/models/issue_custom_field.rb' + - 'app/models/project.rb' + - 'app/models/query.rb' + - 'app/models/role.rb' + - 'app/models/tracker.rb' + - 'app/models/user.rb' + +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/HasManyOrHasOneDependent: + Exclude: + - 'app/models/auth_source.rb' + - 'app/models/document_category.rb' + - 'app/models/issue_priority.rb' + - 'app/models/issue_status.rb' + - 'app/models/project.rb' + - 'app/models/time_entry_activity.rb' + - 'app/models/tracker.rb' + - 'app/models/wiki.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: numeric, symbolic +Rails/HttpStatus: + Exclude: + - 'app/controllers/mail_handler_controller.rb' + - 'app/controllers/sys_controller.rb' + - 'app/controllers/watchers_controller.rb' + +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/InverseOf: + Exclude: + - 'app/models/board.rb' + - 'app/models/custom_field.rb' + - 'app/models/document_category.rb' + - 'app/models/issue.rb' + - 'app/models/issue_category.rb' + - 'app/models/issue_priority.rb' + - 'app/models/issue_status.rb' + - 'app/models/journal.rb' + - 'app/models/member.rb' + - 'app/models/news.rb' + - 'app/models/principal.rb' + - 'app/models/project.rb' + - 'app/models/repository.rb' + - 'app/models/repository/mercurial.rb' + - 'app/models/time_entry_activity.rb' + - 'app/models/user.rb' + - 'app/models/version.rb' + - 'app/models/wiki.rb' + - 'app/models/wiki_page.rb' + +# Configuration parameters: Include. +# Include: app/controllers/**/*.rb +Rails/LexicallyScopedActionFilter: + Exclude: + - 'app/controllers/projects_controller.rb' + +# Cop supports --auto-correct. +Rails/LinkToBlank: + Exclude: + - 'app/helpers/avatars_helper.rb' + +# Configuration parameters: Include. +# Include: app/**/*.rb, config/**/*.rb, db/**/*.rb, lib/**/*.rb +Rails/Output: + Exclude: + - 'app/models/mail_handler.rb' + - 'config/routes.rb' + - 'lib/redmine/unified_diff.rb' + +Rails/OutputSafety: + Enabled: false + +# Cop supports --auto-correct. +Rails/PluralizationGrammar: + Exclude: + - 'lib/redmine/helpers/time_report.rb' + - 'test/functional/gantts_controller_test.rb' + - 'test/unit/mailer_test.rb' + - 'test/unit/query_test.rb' + +# Cop supports --auto-correct. +Rails/Presence: + Exclude: + - 'app/controllers/activities_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/models/repository.rb' + - 'lib/redmine/codeset_util.rb' + - 'lib/redmine/i18n.rb' + - 'lib/redmine/scm/adapters/abstract_adapter.rb' + - 'lib/redmine/scm/adapters/filesystem_adapter.rb' + - 'lib/redmine/scm/adapters/git_adapter.rb' + - 'lib/redmine/scm/adapters/mercurial_adapter.rb' + - 'lib/redmine/sort_criteria.rb' + +# Cop supports --auto-correct. +# Configuration parameters: NotNilAndNotEmpty, NotBlank, UnlessBlank. +Rails/Present: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/ReadWriteAttribute: + Exclude: + - 'app/models/attachment.rb' + - 'app/models/auth_source_ldap.rb' + - 'app/models/changeset.rb' + - 'app/models/custom_field.rb' + - 'app/models/email_address.rb' + - 'app/models/issue.rb' + - 'app/models/journal_detail.rb' + - 'app/models/message.rb' + - 'app/models/query.rb' + - 'app/models/repository.rb' + - 'app/models/repository/git.rb' + - 'app/models/role.rb' + - 'app/models/setting.rb' + - 'app/models/time_entry.rb' + - 'app/models/user.rb' + - 'app/models/user_preference.rb' + - 'app/models/wiki_page.rb' + +Rails/ReflectionClassName: + Exclude: + - 'lib/redmine/nested_set/issue_nested_set.rb' + - 'lib/redmine/nested_set/project_nested_set.rb' + +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: **/test/**/* +Rails/RefuteMethods: + Exclude: + - 'test/functional/projects_controller_test.rb' + - 'test/functional/wiki_controller_test.rb' + - 'test/integration/account_test.rb' + - 'test/integration/api_test/my_test.rb' + - 'test/unit/attachment_test.rb' + - 'test/unit/custom_field_test.rb' + - 'test/unit/lib/redmine/project_jump_box_test.rb' + - 'test/unit/mail_handler_test.rb' + +# Configuration parameters: Blacklist, Whitelist. +# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters +Rails/SkipsModelValidations: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: strict, flexible +Rails/TimeZone: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/Validation: + Enabled: false + +Security/Eval: + Exclude: + - 'app/helpers/attachments_helper.rb' + - 'app/models/user.rb' + - 'config/initializers/00-core_plugins.rb' + +Security/Open: + Exclude: + - 'app/models/version.rb' + +# Cop supports --auto-correct. +Security/YAMLLoad: + Exclude: + - 'Gemfile' + - 'app/models/setting.rb' + - 'lib/redmine/configuration.rb' + +# Configuration parameters: EnforcedStyle. +# SupportedStyles: inline, group +Style/AccessModifierDeclarations: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: prefer_alias, prefer_alias_method +Style/Alias: + Exclude: + - 'app/controllers/repositories_controller.rb' + - 'app/models/custom_field_enumeration.rb' + - 'app/models/enumeration.rb' + - 'app/models/issue.rb' + - 'app/models/issue_category.rb' + - 'app/models/issue_query.rb' + - 'app/models/issue_status.rb' + - 'app/models/member.rb' + - 'app/models/project.rb' + - 'app/models/user.rb' + - 'app/models/version.rb' + - 'config/initializers/10-patches.rb' + - 'lib/redmine/export/pdf.rb' + - 'lib/redmine/menu_manager.rb' + - 'lib/redmine/plugin.rb' + - 'lib/redmine/wiki_formatting/markdown/formatter.rb' + - 'lib/redmine/wiki_formatting/textile/formatter.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, conditionals +Style/AndOr: + Exclude: + - 'app/controllers/account_controller.rb' + - 'app/controllers/application_controller.rb' + - 'app/controllers/calendars_controller.rb' + - 'app/helpers/repositories_helper.rb' + - 'app/models/query.rb' + - 'db/migrate/022_serialize_possibles_values.rb' + - 'lib/redmine/export/pdf.rb' + - 'lib/redmine/field_format.rb' + - 'lib/redmine/helpers/gantt.rb' + - 'lib/redmine/scm/adapters/abstract_adapter.rb' + - 'lib/redmine/scm/adapters/bazaar_adapter.rb' + - 'lib/redmine/scm/adapters/filesystem_adapter.rb' + - 'lib/redmine/scm/adapters/git_adapter.rb' + - 'lib/redmine/scm/adapters/subversion_adapter.rb' + - 'lib/redmine/wiki_formatting.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: percent_q, bare_percent +Style/BarePercentLiterals: + Exclude: + - 'test/integration/api_test/api_test.rb' + +# Cop supports --auto-correct. +Style/BlockComments: + Exclude: + - 'lib/diff.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods, AllowBracesOnProceduralOneLiners. +# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces +# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object +# FunctionalMethods: let, let!, subject, watch +# IgnoredMethods: lambda, proc, it +Style/BlockDelimiters: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: braces, no_braces, context_dependent +Style/BracesAroundHashParameters: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect, EnforcedStyle. +# SupportedStyles: nested, compact +Style/ClassAndModuleChildren: + Enabled: false + +# Cop supports --auto-correct. +Style/ClassMethods: + Exclude: + - 'lib/diff.rb' + +Style/ClassVars: + Exclude: + - 'app/models/attachment.rb' + - 'config/initializers/10-patches.rb' + - 'lib/redmine/activity.rb' + - 'lib/redmine/export/pdf.rb' + - 'lib/redmine/hook.rb' + - 'lib/redmine/i18n.rb' + - 'lib/redmine/menu_manager.rb' + - 'lib/redmine/my_page.rb' + - 'lib/redmine/scm/adapters/bazaar_adapter.rb' + - 'lib/redmine/scm/adapters/cvs_adapter.rb' + - 'lib/redmine/scm/adapters/git_adapter.rb' + - 'lib/redmine/scm/adapters/mercurial_adapter.rb' + - 'lib/redmine/scm/adapters/subversion_adapter.rb' + - 'lib/redmine/search.rb' + - 'lib/redmine/themes.rb' + - 'lib/redmine/wiki_formatting.rb' + - 'lib/redmine/wiki_formatting/macros.rb' + - 'lib/redmine/wiki_formatting/markdown/formatter.rb' + - 'test/helpers/activities_helper_test.rb' + +# Cop supports --auto-correct. +Style/ColonMethodCall: + Exclude: + - 'Gemfile' + - 'app/controllers/admin_controller.rb' + - 'app/models/setting.rb' + - 'lib/redmine/configuration.rb' + - 'lib/redmine/export/pdf.rb' + - 'lib/redmine/wiki_formatting.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + - 'test/test_helper.rb' + - 'test/unit/default_data_test.rb' + - 'test/unit/lib/redmine/export/pdf_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. +# SupportedStyles: assign_to_condition, assign_inside_condition +Style/ConditionalAssignment: + Enabled: false + +Style/Documentation: + Enabled: false + +Style/DoubleNegation: + Exclude: + - 'app/controllers/application_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/models/attachment.rb' + - 'app/models/issue_import.rb' + - 'app/models/mailer.rb' + - 'app/models/query.rb' + - 'app/models/user.rb' + - 'lib/redmine/sudo_mode.rb' + +# Cop supports --auto-correct. +Style/EachWithObject: + Exclude: + - 'app/controllers/repositories_controller.rb' + - 'app/helpers/queries_helper.rb' + - 'app/models/issue.rb' + - 'app/models/issue_import.rb' + - 'app/models/journal.rb' + - 'app/models/mail_handler.rb' + - 'app/models/project.rb' + - 'app/models/query.rb' + - 'app/models/repository.rb' + - 'app/models/setting.rb' + - 'app/models/time_entry_import.rb' + - 'app/models/workflow_permission.rb' + - 'config/initializers/10-patches.rb' + - 'lib/redmine/acts/positioned.rb' + - 'lib/redmine/configuration.rb' + - 'lib/redmine/i18n.rb' + - 'lib/redmine/mime_type.rb' + - 'lib/redmine/my_page.rb' + - 'lib/redmine/sort_criteria.rb' + - 'test/test_helper.rb' + +# Cop supports --auto-correct. +Style/EmptyCaseCondition: + Exclude: + - 'app/models/auth_source_ldap.rb' + - 'app/models/issue_priority.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty, nil, both +Style/EmptyElse: + Exclude: + - 'app/helpers/avatars_helper.rb' + - 'app/models/import.rb' + - 'app/models/mail_handler.rb' + - 'app/models/query.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: compact, expanded +Style/EmptyMethod: + Enabled: false + +Style/EvalWithLocation: + Exclude: + - 'app/helpers/attachments_helper.rb' + +# Cop supports --auto-correct. +Style/ExpandPathArguments: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: each, for +Style/For: + Exclude: + - 'lib/redmine/export/pdf/issues_pdf_helper.rb' + - 'lib/redmine/export/pdf/wiki_pdf_helper.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: format, sprintf, percent +Style/FormatString: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/helpers/queries_helper.rb' + - 'app/models/query.rb' + - 'config/initializers/10-patches.rb' + - 'lib/generators/redmine_plugin_model/redmine_plugin_model_generator.rb' + - 'lib/redmine/export/csv.rb' + - 'lib/redmine/export/pdf/issues_pdf_helper.rb' + - 'lib/redmine/helpers/gantt.rb' + - 'lib/redmine/i18n.rb' + - 'lib/redmine/info.rb' + +# Configuration parameters: AllowedVariables. +Style/GlobalVars: + Exclude: + - 'test/test_helper.rb' + +# Configuration parameters: MinBodyLength. +Style/GuardClause: + Enabled: false + +# Configuration parameters: AllowIfModifier. +Style/IfInsideElse: + Exclude: + - 'app/controllers/account_controller.rb' + - 'app/controllers/activities_controller.rb' + - 'app/controllers/application_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/issues_helper.rb' + - 'app/models/custom_field.rb' + - 'app/models/issue.rb' + - 'app/models/project.rb' + - 'app/models/query.rb' + - 'app/models/version.rb' + - 'config/initializers/10-patches.rb' + - 'lib/redmine/field_format.rb' + - 'lib/redmine/helpers/gantt.rb' + - 'lib/redmine/menu_manager.rb' + - 'lib/redmine/pop3.rb' + - 'lib/redmine/scm/adapters/bazaar_adapter.rb' + - 'lib/redmine/views/builders/structure.rb' + +# Cop supports --auto-correct. +Style/IfUnlessModifier: + Enabled: false + +Style/IfUnlessModifierOfIfUnless: + Exclude: + - 'app/models/attachment.rb' + +# Cop supports --auto-correct. +# Configuration parameters: InverseMethods, InverseBlocks. +Style/InverseMethods: + Exclude: + - 'app/controllers/roles_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/issues_helper.rb' + - 'app/helpers/repositories_helper.rb' + - 'app/models/document.rb' + - 'app/models/issue.rb' + - 'app/models/member.rb' + - 'app/models/message.rb' + - 'app/models/project.rb' + - 'app/models/tracker.rb' + - 'app/models/version.rb' + - 'app/models/wiki_content.rb' + - 'db/migrate/096_add_commit_access_permission.rb' + - 'lib/redmine/default_data/loader.rb' + - 'lib/redmine/helpers/diff.rb' + - 'lib/redmine/scm/adapters/abstract_adapter.rb' + - 'lib/redmine/scm/adapters/git_adapter.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + - 'test/unit/issue_test.rb' + - 'test/unit/query_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: line_count_dependent, lambda, literal +Style/Lambda: + Enabled: false + +# Cop supports --auto-correct. +Style/LineEndConcatenation: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: IgnoredMethods. +Style/MethodCallWithoutArgsParentheses: + Exclude: + - 'lib/redmine/export/pdf.rb' + - 'lib/redmine/helpers/gantt.rb' + - 'lib/redmine/scm/adapters/cvs_adapter.rb' + - 'lib/redmine/scm/adapters/filesystem_adapter.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: require_parentheses, require_no_parentheses, require_no_parentheses_except_multiline +Style/MethodDefParentheses: + Exclude: + - 'lib/redmine/menu_manager.rb' + +Style/MethodMissingSuper: + Exclude: + - 'lib/redmine/views/builders/structure.rb' + +Style/MissingRespondToMissing: + Exclude: + - 'lib/redmine/views/builders/structure.rb' + +Style/MixinUsage: + Exclude: + - 'test/test_helper.rb' + +# Cop supports --auto-correct. +Style/MultilineIfModifier: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/helpers/attachments_helper.rb' + - 'app/helpers/custom_fields_helper.rb' + - 'app/helpers/projects_helper.rb' + - 'app/helpers/reports_helper.rb' + - 'app/helpers/repositories_helper.rb' + - 'app/helpers/search_helper.rb' + - 'app/models/issue_query.rb' + - 'app/models/query.rb' + - 'app/models/repository/bazaar.rb' + - 'app/models/repository/subversion.rb' + - 'app/models/time_entry_query.rb' + - 'app/views/common/feed.atom.builder' + - 'lib/redmine/access_keys.rb' + - 'lib/redmine/helpers/gantt.rb' + - 'lib/redmine/scm/adapters/git_adapter.rb' + - 'lib/redmine/scm/adapters/subversion_adapter.rb' + - 'lib/redmine/wiki_formatting.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + - 'test/mocks/open_id_authentication_mock.rb' + +Style/MultilineTernaryOperator: + Exclude: + - 'app/controllers/workflows_controller.rb' + - 'app/helpers/settings_helper.rb' + - 'app/models/issue_query.rb' + - 'lib/redmine/ciphering.rb' + - 'lib/redmine/scm/adapters/filesystem_adapter.rb' + - 'lib/redmine/scm/adapters/git_adapter.rb' + +Style/MultipleComparison: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/helpers/workflows_helper.rb' + - 'app/models/import.rb' + - 'app/models/version.rb' + - 'app/models/wiki_page.rb' + - 'app/models/workflow_transition.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: literals, strict +Style/MutableConstant: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: both, prefix, postfix +Style/NegatedIf: + Exclude: + - 'app/controllers/application_controller.rb' + - 'app/controllers/messages_controller.rb' + - 'app/helpers/repositories_helper.rb' + - 'app/models/attachment.rb' + - 'app/models/auth_source_ldap.rb' + - 'app/models/custom_field.rb' + - 'app/models/project.rb' + - 'app/models/repository/cvs.rb' + - 'lib/diff.rb' + - 'lib/redmine/codeset_util.rb' + - 'lib/redmine/thumbnail.rb' + +# Cop supports --auto-correct. +Style/NegatedWhile: + Exclude: + - 'app/helpers/application_helper.rb' + +# Cop supports --auto-correct. +# Configuration parameters: Whitelist. +# Whitelist: be, be_a, be_an, be_between, be_falsey, be_kind_of, be_instance_of, be_truthy, be_within, eq, eql, end_with, include, match, raise_error, respond_to, start_with +Style/NestedParenthesizedCalls: + Exclude: + - 'lib/redmine/views/labelled_form_builder.rb' + - 'test/unit/mail_handler_test.rb' + +Style/NestedTernaryOperator: + Exclude: + - 'app/helpers/queries_helper.rb' + - 'app/models/journal.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, MinBodyLength. +# SupportedStyles: skip_modifier_ifs, always +Style/Next: + Enabled: false + +# Cop supports --auto-correct. +Style/Not: + Exclude: + - 'db/migrate/096_add_commit_access_permission.rb' + - 'lib/redmine/scm/adapters/filesystem_adapter.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedOctalStyle. +# SupportedOctalStyles: zero_with_o, zero_only +Style/NumericLiteralPrefix: + Exclude: + - 'test/unit/user_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: Strict. +Style/NumericLiterals: + MinDigits: 9 + +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods. +# SupportedStyles: predicate, comparison +Style/NumericPredicate: + Enabled: false + +# Cop supports --auto-correct. +Style/OrAssignment: + Exclude: + - 'app/helpers/sort_helper.rb' + - 'app/models/repository/cvs.rb' + - 'app/models/user.rb' + - 'lib/redmine/helpers/diff.rb' + +# Cop supports --auto-correct. +Style/ParallelAssignment: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: AllowSafeAssignment, AllowInMultilineConditions. +Style/ParenthesesAroundCondition: + Exclude: + - 'app/models/repository/subversion.rb' + - 'lib/redmine/scm/adapters/cvs_adapter.rb' + - 'lib/redmine/scm/adapters/git_adapter.rb' + +# Cop supports --auto-correct. +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Enabled: false + +# Cop supports --auto-correct. +Style/PerlBackrefs: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: short, verbose +Style/PreferredHashMethods: + Enabled: false + +# Cop supports --auto-correct. +Style/Proc: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: compact, exploded +Style/RaiseArgs: + Exclude: + - 'app/models/auth_source_ldap.rb' + - 'app/models/issue_query.rb' + - 'app/models/mailer.rb' + - 'app/models/query.rb' + - 'app/models/tracker.rb' + - 'app/models/user.rb' + - 'app/models/workflow_rule.rb' + - 'lib/redmine/access_control.rb' + - 'lib/redmine/default_data/loader.rb' + - 'lib/redmine/plugin.rb' + - 'lib/redmine/scm/adapters/abstract_adapter.rb' + - 'lib/redmine/scm/adapters/filesystem_adapter.rb' + - 'lib/redmine/sort_criteria.rb' + +# Cop supports --auto-correct. +Style/RedundantCondition: + Exclude: + - 'app/controllers/messages_controller.rb' + - 'app/controllers/previews_controller.rb' + - 'app/models/issue.rb' + +# Cop supports --auto-correct. +Style/RedundantConditional: + Exclude: + - 'app/controllers/workflows_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/models/enumeration.rb' + - 'lib/redmine/field_format.rb' + +# Cop supports --auto-correct. +Style/RedundantInterpolation: + Exclude: + - 'app/helpers/my_helper.rb' + - 'app/helpers/queries_helper.rb' + - 'app/models/query.rb' + - 'app/views/common/feed.atom.builder' + - 'app/views/journals/index.builder' + - 'lib/redmine/helpers/time_report.rb' + - 'lib/redmine/scm/adapters/subversion_adapter.rb' + - 'lib/redmine/wiki_formatting.rb' + - 'test/functional/versions_controller_test.rb' + - 'test/functional/watchers_controller_test.rb' + +# Cop supports --auto-correct. +Style/RedundantParentheses: + Exclude: + - 'app/controllers/search_controller.rb' + - 'app/helpers/users_helper.rb' + - 'app/models/enumeration.rb' + - 'app/models/principal.rb' + - 'app/models/query.rb' + - 'app/models/repository/cvs.rb' + - 'app/models/version.rb' + - 'lib/redmine/field_format.rb' + - 'lib/redmine/helpers/gantt.rb' + - 'lib/redmine/platform.rb' + - 'lib/redmine/scm/adapters/cvs_adapter.rb' + - 'lib/redmine/scm/adapters/filesystem_adapter.rb' + - 'test/helpers/application_helper_test.rb' + - 'test/unit/attachment_test.rb' + - 'test/unit/lib/redmine/export/pdf_test.rb' + - 'test/unit/project_test.rb' + - 'test/unit/user_test.rb' + - 'test/unit/version_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: + Enabled: false + +# Cop supports --auto-correct. +Style/RedundantSelf: + Enabled: false + +# Cop supports --auto-correct. +Style/RedundantSort: + Exclude: + - 'app/models/import.rb' + - 'lib/redmine/scm/adapters/abstract_adapter.rb' + - 'test/functional/issues_controller_test.rb' + - 'test/unit/member_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, AllowInnerSlashes. +# SupportedStyles: slashes, percent_r, mixed +Style/RegexpLiteral: + Enabled: false + +# Cop supports --auto-correct. +Style/RescueModifier: + Exclude: + - 'app/controllers/application_controller.rb' + - 'app/controllers/attachments_controller.rb' + - 'app/controllers/imports_controller.rb' + - 'app/controllers/watchers_controller.rb' + - 'app/helpers/avatars_helper.rb' + - 'app/models/custom_field.rb' + - 'app/models/import.rb' + - 'app/models/query.rb' + - 'app/models/repository.rb' + - 'lib/redmine/export/csv.rb' + - 'lib/redmine/field_format.rb' + - 'lib/redmine/search.rb' + - 'lib/redmine/wiki_formatting.rb' + - 'test/unit/lib/redmine/wiki_formatting/markdown_formatter_test.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, explicit +Style/RescueStandardError: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, Whitelist. +# Whitelist: present?, blank?, presence, try, try! +Style/SafeNavigation: + Enabled: false + +# Cop supports --auto-correct. +Style/SelfAssignment: + Exclude: + - 'app/controllers/repositories_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/reports_helper.rb' + - 'app/models/auth_source_ldap.rb' + - 'app/models/project.rb' + - 'app/models/query.rb' + - 'app/models/repository/cvs.rb' + - 'lib/redmine/helpers/calendar.rb' + - 'lib/redmine/helpers/gantt.rb' + - 'lib/redmine/helpers/time_report.rb' + +# Cop supports --auto-correct. +# Configuration parameters: AllowAsExpressionSeparator. +Style/Semicolon: + Exclude: + - 'app/controllers/account_controller.rb' + - 'app/controllers/context_menus_controller.rb' + - 'app/controllers/journals_controller.rb' + - 'app/controllers/messages_controller.rb' + - 'app/controllers/repositories_controller.rb' + - 'app/controllers/search_controller.rb' + - 'app/models/issue.rb' + - 'app/models/issue_query.rb' + - 'app/models/journal.rb' + - 'app/models/mail_handler.rb' + - 'app/models/project.rb' + - 'app/models/query.rb' + - 'app/models/tracker.rb' + - 'lib/redmine/configuration.rb' + - 'lib/redmine/i18n.rb' + - 'lib/redmine/scm/adapters/git_adapter.rb' + - 'lib/redmine/sort_criteria.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + +# Cop supports --auto-correct. +# Configuration parameters: AllowIfMethodIsEmpty. +Style/SingleLineMethods: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: . +# SupportedStyles: use_perl_names, use_english_names +Style/SpecialGlobalVars: + EnforcedStyle: use_perl_names + +# Cop supports --auto-correct. +Style/StderrPuts: + Exclude: + - 'config/environment.rb' + - 'config/initializers/10-patches.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiteralsInInterpolation: + Exclude: + - 'app/models/issue_query.rb' + - 'config/environment.rb' + - 'lib/redmine/scm/adapters/cvs_adapter.rb' + - 'lib/redmine/wiki_formatting.rb' + - 'lib/redmine/wiki_formatting/textile/redcloth3.rb' + - 'test/unit/member_test.rb' + +Style/StructInheritance: + Exclude: + - 'lib/redmine/notifiable.rb' + - 'lib/redmine/sudo_mode.rb' + +# Cop supports --auto-correct. +# Configuration parameters: MinSize. +# SupportedStyles: percent, brackets +Style/SymbolArray: + EnforcedStyle: brackets + +# Cop supports --auto-correct. +# Configuration parameters: IgnoredMethods. +# IgnoredMethods: respond_to, define_method +Style/SymbolProc: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, AllowSafeAssignment. +# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex +Style/TernaryParentheses: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInHashLiteral: + Enabled: false + +# Cop supports --auto-correct. +# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist. +# Whitelist: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym +Style/TrivialAccessors: + Exclude: + - 'app/models/issue.rb' + - 'app/models/journal.rb' + - 'app/models/query.rb' + - 'lib/redmine/access_control.rb' + - 'lib/redmine/scm/adapters/abstract_adapter.rb' + - 'lib/redmine/scm/adapters/cvs_adapter.rb' + - 'lib/redmine/scm/adapters/filesystem_adapter.rb' + - 'lib/redmine/scm/adapters/git_adapter.rb' + - 'lib/redmine/scm/adapters/mercurial_adapter.rb' + +# Cop supports --auto-correct. +Style/UnlessElse: + Exclude: + - 'app/controllers/auth_sources_controller.rb' + - 'app/controllers/trackers_controller.rb' + - 'lib/redmine/scm/adapters/abstract_adapter.rb' + - 'lib/redmine/unified_diff.rb' + +# Cop supports --auto-correct. +Style/VariableInterpolation: + Exclude: + - 'lib/redmine/configuration.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, MinSize, WordRegex. +# SupportedStyles: percent, brackets +Style/WordArray: + Enabled: false + +# Cop supports --auto-correct. +Style/ZeroLengthPredicate: + Exclude: + - 'app/models/import.rb' + - 'app/models/mail_handler.rb' + - 'app/models/user.rb' + - 'lib/redmine/field_format.rb' + - 'lib/redmine/unified_diff.rb' + - 'lib/redmine/wiki_formatting/macros.rb' + - 'test/functional/custom_fields_controller_test.rb' + - 'test/object_helpers.rb' + - 'test/unit/activity_test.rb' + - 'test/unit/custom_field_test.rb' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7894bca..94e13c5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,10 @@ +Your contributions to Redmine are welcome! -**Do not send a pull request to this GitHub repository**. +Please **open an issue on the [official website]** instead of sending pull requests. -For more detail, please see [official website] wiki [Contribute]. +Since the development of Redmine is not conducted on GitHub but on the [official website] and core developers are not monitoring the GitHub repo, pull requests might not get reviewed. -[official website]: http://www.redmine.org -[Contribute]: http://www.redmine.org/projects/redmine/wiki/Contribute +For more detail about how to contribute, please see the wiki page [Contribute] on the [official website]. +[official website]: https://www.redmine.org/ +[Contribute]: https://www.redmine.org/projects/redmine/wiki/Contribute diff --git a/Gemfile b/Gemfile index 68b1b43..f9a98ff 100644 --- a/Gemfile +++ b/Gemfile @@ -1,41 +1,28 @@ source 'https://rubygems.org' -gem "bundler", ">= 1.5.0", "< 2.0.0" +ruby '>= 2.3.0', '< 2.7.0' if Bundler::VERSION >= '1.12.0' +gem "bundler", ">= 1.5.0" -gem "rails", "4.2.11.1" -gem "addressable", "2.4.0" if RUBY_VERSION < "2.0" -if RUBY_VERSION < "2.1" - gem "public_suffix", (RUBY_VERSION < "2.0" ? "~> 1.4" : "~> 2.0.5") -end -gem "jquery-rails", "~> 3.1.4" -gem "coderay", "~> 1.1.1" -gem "request_store", "1.0.5" -gem "mime-types", (RUBY_VERSION >= "2.0" ? "~> 3.0" : "~> 2.99") -gem "protected_attributes" +gem 'rails', '5.2.4.2' +gem 'sprockets', '~> 3.7.2' if RUBY_VERSION < '2.5' +gem "rouge", "~> 3.12.0" +gem "request_store", "~> 1.4.1" +gem "mini_mime", "~> 1.0.1" gem "actionpack-xml_parser" -gem "roadie-rails", "~> 1.1.1" -gem "roadie", "~> 3.2.1" +gem "roadie-rails", (RUBY_VERSION < "2.5" ? "~> 1.3.0" : "~> 2.1.0") gem "mimemagic" -gem "mail", "~> 2.6.4" - -gem "nokogiri", (RUBY_VERSION >= "2.1" ? "~> 1.8.1" : "~> 1.6.8") -gem "i18n", "~> 0.7.0" -gem "ffi", "1.9.14", :platforms => :mingw if RUBY_VERSION < "2.0" -gem "xpath", "< 3.2.0" if RUBY_VERSION < "2.3" - -# Request at least rails-html-sanitizer 1.0.3 because of security advisories -gem "rails-html-sanitizer", ">= 1.0.3" - -# TODO: Remove the following line when #32223 is fixed -gem "sprockets", "~> 3.7.2" +gem "mail", "~> 2.7.1" +gem "csv", "~> 3.1.1" +gem "nokogiri", "~> 1.10.0" +gem "i18n", "~> 1.6.0" +gem "rbpdf", "~> 1.20.0" # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :x64_mingw, :mswin] -gem "rbpdf", "~> 1.19.6" # Optional gem for LDAP authentication group :ldap do - gem "net-ldap", "~> 0.12.0" + gem "net-ldap", "~> 0.16.0" end # Optional gem for OpenID authentication @@ -44,16 +31,14 @@ group :openid do gem "rack-openid" end -platforms :mri, :mingw, :x64_mingw do - # Optional gem for exporting the gantt to a PNG file, not supported with jruby - group :rmagick do - gem "rmagick", "~> 2.16.0" - end +# Optional gem for exporting the gantt to a PNG file +group :minimagick do + gem "mini_magick", "~> 4.9.5" +end - # Optional Markdown support, not for JRuby - group :markdown do - gem "redcarpet", "~> 3.4.0" - end +# Optional Markdown support, not for JRuby +group :markdown do + gem "redcarpet", "~> 3.5.0" end # Include database gems for the adapters found in the database @@ -68,15 +53,14 @@ if File.exist?(database_file) adapters.each do |adapter| case adapter when 'mysql2' - gem "mysql2", "~> 0.4.6", :platforms => [:mri, :mingw, :x64_mingw] + gem "mysql2", "~> 0.5.0", :platforms => [:mri, :mingw, :x64_mingw] when /postgresql/ - gem "pg", "~> 0.18.1", :platforms => [:mri, :mingw, :x64_mingw] + gem "pg", "~> 1.1.4", :platforms => [:mri, :mingw, :x64_mingw] when /sqlite3/ - gem "sqlite3", (RUBY_VERSION < "2.0" && RUBY_PLATFORM =~ /mingw/ ? "1.3.12" : "~>1.3.12"), - :platforms => [:mri, :mingw, :x64_mingw] + gem "sqlite3", "~> 1.4.0", :platforms => [:mri, :mingw, :x64_mingw] when /sqlserver/ - gem "tiny_tds", (RUBY_VERSION >= "2.0" ? "~> 1.0.5" : "~> 0.7.0"), :platforms => [:mri, :mingw, :x64_mingw] - gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw, :x64_mingw] + gem "tiny_tds", "~> 2.1.2", :platforms => [:mri, :mingw, :x64_mingw] + gem "activerecord-sqlserver-adapter", "~> 5.2.1", :platforms => [:mri, :mingw, :x64_mingw] else warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems") end @@ -89,20 +73,22 @@ else end group :development do - gem "rdoc", "~> 4.3" gem "yard" end group :test do - gem "minitest" gem "rails-dom-testing" gem 'mocha', '>= 1.4.0' - gem "simplecov", "~> 0.9.1", :require => false - # TODO: remove this after upgrading to Rails 5 - gem "test_after_commit", "~> 0.4.2" - # For running UI tests - gem "capybara", '~> 2.13' - gem "selenium-webdriver", "~> 2.53.4" + gem "simplecov", "~> 0.17.0", :require => false + gem "ffi", platforms: [:mingw, :x64_mingw, :mswin] + # For running system tests + gem 'puma', '~> 3.7' + gem "capybara", (RUBY_VERSION < "2.4" ? "~> 3.15.1" : "~> 3.25.0") + gem "selenium-webdriver" + # RuboCop + gem 'rubocop', '~> 0.76.0' + gem 'rubocop-performance', '~> 1.5.0' + gem 'rubocop-rails', '~> 2.3.0' end local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb index 5070295..ff8631e 100644 --- a/app/controllers/account_controller.rb +++ b/app/controllers/account_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -62,9 +64,15 @@ class AccountController < ApplicationController (redirect_to(home_url); return) unless Setting.lost_password? if prt = (params[:token] || session[:password_recovery_token]) @token = Token.find_token("recovery", prt.to_s) - if @token.nil? || @token.expired? + if @token.nil? redirect_to home_url return + elsif @token.expired? + # remove expired token from session and let user try again + session[:password_recovery_token] = nil + flash[:error] = l(:error_token_expired) + redirect_to lost_password_url + return end # redirect to remove the token query parameter from the URL and add it to the session @@ -87,7 +95,7 @@ class AccountController < ApplicationController @user.must_change_passwd = false if @user.save @token.destroy - Mailer.password_updated(@user, { remote_ip: request.remote_ip }) + Mailer.deliver_password_updated(@user, User.current) flash[:notice] = l(:notice_account_password_updated) redirect_to signin_path return @@ -119,7 +127,7 @@ class AccountController < ApplicationController if token.save # Don't use the param to send the email recipent = user.mails.detect {|e| email.casecmp(e) == 0} || user.mail - Mailer.lost_password(token, recipent).deliver + Mailer.deliver_lost_password(user, token, recipent) flash[:notice] = l(:notice_account_lost_email_sent) redirect_to signin_path return @@ -313,7 +321,7 @@ class AccountController < ApplicationController def register_by_email_activation(user, &block) token = Token.new(:user => user, :action => "register") if user.save and token.save - Mailer.register(token).deliver + Mailer.deliver_register(user, token) flash[:notice] = l(:notice_account_register_done, :email => ERB::Util.h(user.mail)) redirect_to signin_path else @@ -343,7 +351,7 @@ class AccountController < ApplicationController def register_manually_by_administrator(user, &block) if user.save # Sends an email to the administrators - Mailer.account_activation_request(user).deliver + Mailer.deliver_account_activation_request(user) account_pending(user) else yield if block_given? diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb index f82f011..d809245 100644 --- a/app/controllers/activities_controller.rb +++ b/app/controllers/activities_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -17,7 +19,7 @@ class ActivitiesController < ApplicationController menu_item :activity - before_action :find_optional_project + before_action :find_optional_project_by_id, :authorize_global accept_rss_auth :index def index @@ -76,15 +78,4 @@ class ActivitiesController < ApplicationController rescue ActiveRecord::RecordNotFound render_404 end - - private - - # TODO: refactor, duplicated in projects_controller - def find_optional_project - return true unless params[:id] - @project = Project.find(params[:id]) - authorize - rescue ActiveRecord::RecordNotFound - render_404 - end end diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index dfc73c5..ac55133 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -52,7 +54,7 @@ class AdminController < ApplicationController begin Redmine::DefaultData::Loader::load(params[:lang]) flash[:notice] = l(:notice_default_data_loaded) - rescue Exception => e + rescue => e flash[:error] = l(:error_can_t_load_default_data, ERB::Util.h(e.message)) end end @@ -60,16 +62,12 @@ class AdminController < ApplicationController end def test_email - raise_delivery_errors = ActionMailer::Base.raise_delivery_errors - # Force ActionMailer to raise delivery errors so we can catch it - ActionMailer::Base.raise_delivery_errors = true begin - @test = Mailer.test_email(User.current).deliver + Mailer.deliver_test_email(User.current) flash[:notice] = l(:notice_email_sent, ERB::Util.h(User.current.mail)) - rescue Exception => e + rescue => e flash[:error] = l(:notice_email_error, ERB::Util.h(Redmine::CodesetUtil.replace_invalid_utf8(e.message.dup))) end - ActionMailer::Base.raise_delivery_errors = raise_delivery_errors redirect_to settings_path(:tab => 'notifications') end @@ -78,8 +76,9 @@ class AdminController < ApplicationController [:text_default_administrator_account_changed, User.default_admin_account_changed?], [:text_file_repository_writable, File.writable?(Attachment.storage_path)], ["#{l :text_plugin_assets_writable} (./public/plugin_assets)", File.writable?(Redmine::Plugin.public_directory)], - [:text_rmagick_available, Object.const_defined?(:Magick)], - [:text_convert_available, Redmine::Thumbnail.convert_available?] + [:text_minimagick_available, Object.const_defined?(:MiniMagick)], + [:text_convert_available, Redmine::Thumbnail.convert_available?], + [:text_gs_available, Redmine::Thumbnail.gs_available?] ] end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1d42901..f095ac7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -18,14 +20,17 @@ require 'uri' require 'cgi' -class Unauthorized < Exception; end +class Unauthorized < StandardError; end class ApplicationController < ActionController::Base include Redmine::I18n include Redmine::Pagination include Redmine::Hook::Helper include RoutesHelper + include AvatarsHelper + helper :routes + helper :avatars class_attribute :accept_api_auth_actions class_attribute :accept_rss_auth_actions @@ -52,6 +57,7 @@ class ApplicationController < ActionController::Base end before_action :session_expiration, :user_setup, :check_if_login_required, :set_localization, :check_password_change + after_action :record_project_usage rescue_from ::Unauthorized, :with => :deny_access rescue_from ::ActionView::MissingTemplate, :with => :missing_template @@ -112,7 +118,7 @@ class ApplicationController < ActionController::Base if (key = api_key_from_request) # Use API key user = User.find_by_api_key(key) - elsif request.authorization.to_s =~ /\ABasic /i + elsif /\ABasic /i.match?(request.authorization.to_s) # HTTP Basic, either username/password or API key/random authenticate_with_http_basic do |username, password| user = User.try_to_login(username, password) || User.find_by_api_key(username) @@ -229,9 +235,14 @@ class ApplicationController < ActionController::Base format.any(:atom, :pdf, :csv) { redirect_to signin_path(:back_url => url) } - format.xml { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' } + format.api { + if Setting.rest_api_enabled? && accept_api_auth? + head(:unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"') + else + head(:forbidden) + end + } format.js { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' } - format.json { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' } format.any { head :unauthorized } end return false @@ -259,7 +270,11 @@ class ApplicationController < ActionController::Base true else if @project && @project.archived? + @archived_project = @project render_403 :message => :notice_not_authorized_archived_project + elsif @project && !@project.allows_to?(:controller => ctrl, :action => action) + # Project module is disabled + render_403 else deny_access end @@ -272,27 +287,31 @@ class ApplicationController < ActionController::Base end # Find project of id params[:id] - def find_project - @project = Project.find(params[:id]) + def find_project(project_id=params[:id]) + @project = Project.find(project_id) rescue ActiveRecord::RecordNotFound render_404 end # Find project of id params[:project_id] def find_project_by_project_id - @project = Project.find(params[:project_id]) - rescue ActiveRecord::RecordNotFound - render_404 + find_project(params[:project_id]) + end + + # Find project of id params[:id] if present + def find_optional_project_by_id + if params[:id].present? + find_project(params[:id]) + end end # Find a project based on params[:project_id] - # TODO: some subclasses override this, see about merging their logic + # and authorize the user for the requested action def find_optional_project - @project = Project.find(params[:project_id]) unless params[:project_id].blank? - allowed = User.current.allowed_to?({:controller => params[:controller], :action => params[:action]}, @project, :global => true) - allowed ? true : deny_access - rescue ActiveRecord::RecordNotFound - render_404 + if params[:project_id].present? + find_project(params[:project_id]) + end + authorize_global end # Finds and sets @project based on @object.project @@ -385,18 +404,30 @@ class ApplicationController < ActionController::Base end end + def record_project_usage + if @project && @project.id && User.current.logged? && User.current.allowed_to?(:view_project, @project) + Redmine::ProjectJumpBox.new(User.current).project_used(@project) + end + true + end + def back_url url = params[:back_url] if url.nil? && referer = request.env['HTTP_REFERER'] url = CGI.unescape(referer.to_s) + # URLs that contains the utf8=[checkmark] parameter added by Rails are + # parsed as invalid by URI.parse so the redirect to the back URL would + # not be accepted (ApplicationController#validate_back_url would return + # false) + url.gsub!(/(\?|&)utf8=\u2713&?/, '\1') end url end + helper_method :back_url def redirect_back_or_default(default, options={}) - back_url = params[:back_url].to_s - if back_url.present? && valid_url = validate_back_url(back_url) - redirect_to(valid_url) + if back_url = validate_back_url(params[:back_url].to_s) + redirect_to(back_url) return elsif options[:referer] redirect_to_referer_or default @@ -409,6 +440,8 @@ class ApplicationController < ActionController::Base # Returns a validated URL string if back_url is a valid url for redirection, # otherwise false def validate_back_url(back_url) + return false if back_url.blank? + if CGI.unescape(back_url).include?('..') return false end @@ -431,11 +464,11 @@ class ApplicationController < ActionController::Base path = uri.to_s # Ensure that the remaining URL starts with a slash, followed by a # non-slash character or the end - if path !~ %r{\A/([^/]|\z)} + if !%r{\A/([^/]|\z)}.match?(path) return false end - if path.match(%r{/(login|account/register|account/lost_password)}) + if %r{/(login|account/register|account/lost_password)}.match?(path) return false end @@ -446,11 +479,13 @@ class ApplicationController < ActionController::Base return path end private :validate_back_url + helper_method :validate_back_url def valid_back_url?(back_url) !!validate_back_url(back_url) end private :valid_back_url? + helper_method :valid_back_url? # Redirects to the request referer if present, redirects to args or call block otherwise. def redirect_to_referer_or(*args, &block) @@ -460,7 +495,7 @@ class ApplicationController < ActionController::Base if args.any? redirect_to *args elsif block_given? - block.call + yield else raise "#redirect_to_referer_or takes arguments or a block" end @@ -495,8 +530,8 @@ class ApplicationController < ActionController::Base end # Handler for ActionView::MissingTemplate exception - def missing_template - logger.warn "Missing template, responding with 404" + def missing_template(exception) + logger.warn "Missing template, responding with 404: #{exception}" @project = nil render_404 end @@ -616,7 +651,7 @@ class ApplicationController < ActionController::Base # Returns a string that can be used as filename value in Content-Disposition header def filename_for_content_disposition(name) - request.env['HTTP_USER_AGENT'] =~ %r{(MSIE|Trident|Edge)} ? ERB::Util.url_encode(name) : name + %r{(MSIE|Trident|Edge)}.match?(request.env['HTTP_USER_AGENT']) ? ERB::Util.url_encode(name) : name end def api_request? @@ -649,9 +684,9 @@ class ApplicationController < ActionController::Base render_error "An error occurred while executing the query and has been logged. Please report this error to your Redmine administrator." end - # Renders a 200 response for successful updates or deletions via the API + # Renders a 204 response for successful updates or deletions via the API def render_api_ok - render_api_head :ok + render_api_head :no_content end # Renders a head API response diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index 64cb05e..4a88079 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -32,6 +34,14 @@ class AttachmentsController < ApplicationController def show respond_to do |format| format.html { + if @attachment.container.respond_to?(:attachments) + @attachments = @attachment.container.attachments.to_a + if index = @attachments.index(@attachment) + @paginator = Redmine::Pagination::Paginator.new( + @attachments.size, 1, index+1 + ) + end + end if @attachment.is_diff? @diff = File.read(@attachment.diskfile, :mode => "rb") @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline' @@ -71,10 +81,11 @@ class AttachmentsController < ApplicationController def thumbnail if @attachment.thumbnailable? && tbnail = @attachment.thumbnail(:size => params[:size]) if stale?(:etag => tbnail, :template => false) - send_file tbnail, + send_file( + tbnail, :filename => filename_for_content_disposition(@attachment.filename), - :type => detect_content_type(@attachment), - :disposition => 'inline' + :type => detect_content_type(@attachment, true), + :disposition => 'inline') end else # No thumbnail for the attachment or thumbnail could not be created @@ -156,8 +167,10 @@ class AttachmentsController < ApplicationController # Returns the menu item that should be selected when viewing an attachment def current_menu_item - if @attachment - case @attachment.container + container = @attachment.try(:container) || @container + + if container + case container when WikiPage :wiki when Message @@ -165,7 +178,7 @@ class AttachmentsController < ApplicationController when Project, Version :files else - @attachment.container.class.name.pluralize.downcase.to_sym + container.class.name.pluralize.downcase.to_sym end end end @@ -224,12 +237,20 @@ class AttachmentsController < ApplicationController @attachment.deletable? ? true : deny_access end - def detect_content_type(attachment) + def detect_content_type(attachment, is_thumb = false) content_type = attachment.content_type if content_type.blank? || content_type == "application/octet-stream" - content_type = Redmine::MimeType.of(attachment.filename) + content_type = + Redmine::MimeType.of(attachment.filename).presence || + "application/octet-stream" end - content_type.to_s + + if is_thumb && content_type == "application/pdf" + # PDF previews are stored in PNG format + content_type = "image/png" + end + + content_type end def disposition(attachment) diff --git a/app/controllers/auth_sources_controller.rb b/app/controllers/auth_sources_controller.rb index dcbba36..295dfd1 100644 --- a/app/controllers/auth_sources_controller.rb +++ b/app/controllers/auth_sources_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -58,7 +60,7 @@ class AuthSourcesController < ApplicationController begin @auth_source.test_connection flash[:notice] = l(:notice_successful_connection) - rescue Exception => e + rescue => e flash[:error] = l(:error_unable_to_connect, e.message) end redirect_to auth_sources_path @@ -68,22 +70,25 @@ class AuthSourcesController < ApplicationController unless @auth_source.users.exists? @auth_source.destroy flash[:notice] = l(:notice_successful_delete) + else + flash[:error] = l(:error_can_not_delete_auth_source) end redirect_to auth_sources_path end def autocomplete_for_new_user results = AuthSource.search(params[:term]) - - render :json => results.map {|result| { - 'value' => result[:login], - 'label' => "#{result[:login]} (#{result[:firstname]} #{result[:lastname]})", - 'login' => result[:login].to_s, - 'firstname' => result[:firstname].to_s, - 'lastname' => result[:lastname].to_s, - 'mail' => result[:mail].to_s, - 'auth_source_id' => result[:auth_source_id].to_s - }} + render :json => results.map {|result| + { + 'value' => result[:login], + 'label' => "#{result[:login]} (#{result[:firstname]} #{result[:lastname]})", + 'login' => result[:login].to_s, + 'firstname' => result[:firstname].to_s, + 'lastname' => result[:lastname].to_s, + 'mail' => result[:mail].to_s, + 'auth_source_id' => result[:auth_source_id].to_s + } + } end private diff --git a/app/controllers/auto_completes_controller.rb b/app/controllers/auto_completes_controller.rb index 2d707f9..d055476 100644 --- a/app/controllers/auto_completes_controller.rb +++ b/app/controllers/auto_completes_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -23,20 +25,18 @@ class AutoCompletesController < ApplicationController q = (params[:q] || params[:term]).to_s.strip status = params[:status].to_s issue_id = params[:issue_id].to_s - if q.present? - scope = Issue.cross_project_scope(@project, params[:scope]).visible - if status.present? - scope = scope.open(status == 'o') - end - if issue_id.present? - scope = scope.where.not(:id => issue_id.to_i) - end - if q.match(/\A#?(\d+)\z/) - issues << scope.find_by_id($1.to_i) - end + scope = Issue.cross_project_scope(@project, params[:scope]).visible + scope = scope.open(status == 'o') if status.present? + scope = scope.where.not(:id => issue_id.to_i) if issue_id.present? + if q.present? + if q =~ /\A#?(\d+)\z/ + issues << scope.find_by(:id => $1.to_i) + end issues += scope.like(q).order(:id => :desc).limit(10).to_a issues.compact! + else + issues += scope.order(:id => :desc).limit(10).to_a end render :json => format_issues_json(issues) @@ -53,10 +53,11 @@ class AutoCompletesController < ApplicationController end def format_issues_json(issues) - issues.map {|issue| { - 'id' => issue.id, - 'label' => "#{issue.tracker} ##{issue.id}: #{issue.subject.to_s.truncate(60)}", - 'value' => issue.id + issues.map {|issue| + { + 'id' => issue.id, + 'label' => "#{issue.tracker} ##{issue.id}: #{issue.subject.to_s.truncate(60)}", + 'value' => issue.id } } end diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb index 03ca50c..bcafada 100644 --- a/app/controllers/boards_controller.rb +++ b/app/controllers/boards_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -108,7 +110,8 @@ class BoardsController < ApplicationController redirect_to_settings_in_projects end -private + private + def redirect_to_settings_in_projects redirect_to settings_project_path(@project, :tab => 'boards') end diff --git a/app/controllers/calendars_controller.rb b/app/controllers/calendars_controller.rb index e07ba2e..23e7488 100644 --- a/app/controllers/calendars_controller.rb +++ b/app/controllers/calendars_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index e7974d4..5d7d664 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/context_menus_controller.rb b/app/controllers/context_menus_controller.rb index bd69775..8622d15 100644 --- a/app/controllers/context_menus_controller.rb +++ b/app/controllers/context_menus_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -22,7 +24,7 @@ class ContextMenusController < ApplicationController before_action :find_issues, :only => :issues def issues - if (@issues.size == 1) + if @issues.size == 1 @issue = @issues.first end @issue_ids = @issues.map(&:id).sort @@ -43,6 +45,8 @@ class ContextMenusController < ApplicationController @priorities = IssuePriority.active.reverse @back = back_url + @columns = params[:c] + @options_by_custom_field = {} if @can[:edit] custom_fields = @issues.map(&:editable_custom_fields).reduce(:&).reject(&:multiple?).select {|field| field.format.bulk_edit_supported} @@ -64,7 +68,7 @@ class ContextMenusController < ApplicationController preload(:user).to_a (render_404; return) unless @time_entries.present? - if (@time_entries.size == 1) + if @time_entries.size == 1 @time_entry = @time_entries.first end diff --git a/app/controllers/custom_field_enumerations_controller.rb b/app/controllers/custom_field_enumerations_controller.rb index fc186b9..8c00edc 100644 --- a/app/controllers/custom_field_enumerations_controller.rb +++ b/app/controllers/custom_field_enumerations_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/custom_fields_controller.rb b/app/controllers/custom_fields_controller.rb index 41d4a73..f979f8b 100644 --- a/app/controllers/custom_fields_controller.rb +++ b/app/controllers/custom_fields_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -46,7 +48,11 @@ class CustomFieldsController < ApplicationController if @custom_field.save flash[:notice] = l(:notice_successful_create) call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field) - redirect_to edit_custom_field_path(@custom_field) + if params[:continue] + redirect_to new_custom_field_path({:type => @custom_field.type}) + else + redirect_to edit_custom_field_path(@custom_field) + end else render :action => 'new' end diff --git a/app/controllers/documents_controller.rb b/app/controllers/documents_controller.rb index dbf0e88..27cb1b2 100644 --- a/app/controllers/documents_controller.rb +++ b/app/controllers/documents_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -31,7 +33,8 @@ class DocumentsController < ApplicationController documents = @project.documents.includes(:attachments, :category).to_a case @sort_by when 'date' - @grouped = documents.group_by {|d| d.updated_on.to_date } + documents.sort!{|a,b| b.updated_on <=> a.updated_on} + @grouped = documents.group_by {|d| d.updated_on.to_date} when 'title' @grouped = documents.group_by {|d| d.title.first.upcase} when 'author' @@ -88,7 +91,7 @@ class DocumentsController < ApplicationController render_attachment_warning_if_needed(@document) if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added') - Mailer.attachments_added(attachments[:files]).deliver + Mailer.deliver_attachments_added(attachments[:files]) end redirect_to document_path(@document) end diff --git a/app/controllers/email_addresses_controller.rb b/app/controllers/email_addresses_controller.rb index 2202625..9af294b 100644 --- a/app/controllers/email_addresses_controller.rb +++ b/app/controllers/email_addresses_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/enumerations_controller.rb b/app/controllers/enumerations_controller.rb index a04d7b1..a3d4e47 100644 --- a/app/controllers/enumerations_controller.rb +++ b/app/controllers/enumerations_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -57,7 +59,7 @@ class EnumerationsController < ApplicationController end def update - if @enumeration.update_attributes(enumeration_params) + if @enumeration.update(enumeration_params) respond_to do |format| format.html { flash[:notice] = l(:notice_successful_update) @@ -107,7 +109,7 @@ class EnumerationsController < ApplicationController def enumeration_params # can't require enumeration on #new action - cf_ids = @enumeration.available_custom_fields.map{|c| c.id.to_s} + cf_ids = @enumeration.available_custom_fields.map {|c| c.multiple? ? {c.id.to_s => []} : c.id.to_s} params.permit(:enumeration => [:name, :active, :is_default, :position, :custom_field_values => cf_ids])[:enumeration] end end diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb index 7c59665..00b0dca 100644 --- a/app/controllers/files_controller.rb +++ b/app/controllers/files_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -44,7 +46,7 @@ class FilesController < ApplicationController end def new - @versions = @project.versions.sort + @versions = @project.versions.sorted end def create @@ -55,12 +57,13 @@ class FilesController < ApplicationController if attachments[:files].present? if Setting.notified_events.include?('file_added') - Mailer.attachments_added(attachments[:files]).deliver + Mailer.deliver_attachments_added(attachments[:files]) end respond_to do |format| format.html { flash[:notice] = l(:label_file_added) - redirect_to project_files_path(@project) } + redirect_to project_files_path(@project) + } format.api { render_api_ok } end else @@ -68,7 +71,8 @@ class FilesController < ApplicationController format.html { flash.now[:error] = l(:label_attachment) + " " + l('activerecord.errors.messages.invalid') new - render :action => 'new' } + render :action => 'new' + } format.api { render :status => :bad_request } end end diff --git a/app/controllers/gantts_controller.rb b/app/controllers/gantts_controller.rb index 3283282..04a9e35 100644 --- a/app/controllers/gantts_controller.rb +++ b/app/controllers/gantts_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 4379ee3..5cb80e2 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/imports_controller.rb b/app/controllers/imports_controller.rb index 96589ac..633cc23 100644 --- a/app/controllers/imports_controller.rb +++ b/app/controllers/imports_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -18,22 +20,23 @@ require 'csv' class ImportsController < ApplicationController - menu_item :issues - before_action :find_import, :only => [:show, :settings, :mapping, :run] - before_action :authorize_global + before_action :authorize_import + + layout :import_layout helper :issues helper :queries def new + @import = import_type.new end def create - @import = IssueImport.new + @import = import_type.new @import.user = User.current @import.file = params[:file] - @import.set_default_settings + @import.set_default_settings(:project_id => params[:project_id]) if @import.save redirect_to import_settings_path(@import) @@ -50,10 +53,12 @@ class ImportsController < ApplicationController redirect_to import_mapping_path(@import) end - rescue CSV::MalformedCSVError => e - flash.now[:error] = l(:error_invalid_csv_file_or_settings) - rescue ArgumentError, EncodingError => e - flash.now[:error] = l(:error_invalid_file_encoding, :encoding => ERB::Util.h(@import.settings['encoding'])) + rescue CSV::MalformedCSVError, EncodingError => e + if e.is_a?(CSV::MalformedCSVError) && e.message !~ /Invalid byte sequence/ + flash.now[:error] = l(:error_invalid_csv_file_or_settings) + else + flash.now[:error] = l(:error_invalid_file_encoding, :encoding => ERB::Util.h(@import.settings['encoding'])) + end rescue SystemCallError => e flash.now[:error] = l(:error_can_not_read_import_file) end @@ -94,6 +99,14 @@ class ImportsController < ApplicationController end end + def current_menu(project) + if import_layout == 'admin' + nil + else + :application_menu + end + end + private def find_import @@ -109,9 +122,9 @@ class ImportsController < ApplicationController end def update_from_params - if params[:import_settings].is_a?(Hash) + if params[:import_settings].present? @import.settings ||= {} - @import.settings.merge!(params[:import_settings]) + @import.settings.merge!(params[:import_settings].to_unsafe_hash) @import.save! end end @@ -119,4 +132,31 @@ class ImportsController < ApplicationController def max_items_per_request 5 end + + def import_layout + import_type && import_type.layout || 'base' + end + + def menu_items + menu_item = import_type ? import_type.menu_item : nil + + { self.controller_name.to_sym => { :actions => {}, :default => menu_item } } + end + + def authorize_import + return render_404 unless import_type + return render_403 unless import_type.authorized?(User.current) + end + + def import_type + return @import_type if defined? @import_type + + @import_type = + if @import + @import.class + else + type = Object.const_get(params[:type]) rescue nil + type && type < Import ? type : nil + end + end end diff --git a/app/controllers/issue_categories_controller.rb b/app/controllers/issue_categories_controller.rb index d635a28..f5decdd 100644 --- a/app/controllers/issue_categories_controller.rb +++ b/app/controllers/issue_categories_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/issue_relations_controller.rb b/app/controllers/issue_relations_controller.rb index 0bcc8c5..ee197d0 100644 --- a/app/controllers/issue_relations_controller.rb +++ b/app/controllers/issue_relations_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/issue_statuses_controller.rb b/app/controllers/issue_statuses_controller.rb index 92c0337..f9d051a 100644 --- a/app/controllers/issue_statuses_controller.rb +++ b/app/controllers/issue_statuses_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -72,8 +74,8 @@ class IssueStatusesController < ApplicationController def destroy IssueStatus.find(params[:id]).destroy redirect_to issue_statuses_path - rescue - flash[:error] = l(:error_unable_delete_issue_status) + rescue => e + flash[:error] = l(:error_unable_delete_issue_status, ERB::Util.h(e.message)) redirect_to issue_statuses_path end diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 69a947b..65caee6 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -18,7 +20,7 @@ class IssuesController < ApplicationController default_search_scope :issues - before_action :find_issue, :only => [:show, :edit, :update] + before_action :find_issue, :only => [:show, :edit, :update, :issue_tab] before_action :find_issues, :only => [:bulk_edit, :bulk_update, :destroy] before_action :authorize, :except => [:index, :new, :create] before_action :find_optional_project, :only => [:index, :new, :create] @@ -84,13 +86,10 @@ class IssuesController < ApplicationController def show @journals = @issue.visible_journals_with_index - @changesets = @issue.changesets.visible.preload(:repository, :user).to_a + @has_changesets = @issue.changesets.visible.preload(:repository, :user).exists? @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? } - if User.current.wants_comments_in_reverse_order? - @journals.reverse! - @changesets.reverse! - end + @journals.reverse! if User.current.wants_comments_in_reverse_order? if User.current.allowed_to?(:view_time_entries, @project) Issue.load_visible_spent_hours([@issue]) @@ -102,11 +101,15 @@ class IssuesController < ApplicationController @allowed_statuses = @issue.new_statuses_allowed_to(User.current) @priorities = IssuePriority.active @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project) + @time_entries = @issue.time_entries.visible.preload(:activity, :user) @relation = IssueRelation.new retrieve_previous_and_next_issue_ids render :template => 'issues/show' } - format.api + format.api { + @changesets = @issue.changesets.visible.preload(:repository, :user).to_a + @changesets.reverse! if User.current.wants_comments_in_reverse_order? + } format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' } format.pdf { send_file_headers! :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf" @@ -177,7 +180,7 @@ class IssuesController < ApplicationController if saved render_attachment_warning_if_needed(@issue) - flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record? + flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record? || params[:no_flash] respond_to do |format| format.html { redirect_back_or_default issue_path(@issue, previous_and_next_issue_ids_params) } @@ -191,6 +194,21 @@ class IssuesController < ApplicationController end end + def issue_tab + return render_error :status => 422 unless request.xhr? + tab = params[:name] + + case tab + when 'time_entries' + @time_entries = @issue.time_entries.visible.preload(:activity, :user).to_a + render :partial => 'issues/tabs/time_entries', :locals => {:time_entries => @time_entries} + when 'changesets' + @changesets = @issue.changesets.visible.preload(:repository, :user).to_a + @changesets.reverse! if User.current.wants_comments_in_reverse_order? + render :partial => 'issues/tabs/changesets', :locals => {:changesets => @changesets} + end + end + # Bulk edit/copy a set of issues def bulk_edit @issues.sort! @@ -259,14 +277,16 @@ class IssuesController < ApplicationController end @values_by_custom_field.delete_if {|k,v| v.blank?} - @custom_fields = edited_issues.map{|i|i.editable_custom_fields}.reduce(:&).select {|field| field.format.bulk_edit_supported} + @custom_fields = edited_issues.map{|i| i.editable_custom_fields}.reduce(:&).select {|field| field.format.bulk_edit_supported} @assignables = target_projects.map(&:assignable_users).reduce(:&) @versions = target_projects.map {|p| p.shared_versions.open}.reduce(:&) @categories = target_projects.map {|p| p.issue_categories}.reduce(:&) if @copy @attachments_present = @issues.detect {|i| i.attachments.any?}.present? @subtasks_present = @issues.detect {|i| !i.leaf?}.present? - @watchers_present = User.current.allowed_to?(:add_issue_watchers, @projects) && Watcher.where(:watchable_type => 'Issue', :watchable_id => @issues.map(&:id)).exists? + @watchers_present = User.current.allowed_to?(:add_issue_watchers, @projects) && + Watcher.where(:watchable_type => 'Issue', + :watchable_id => @issues.map(&:id)).exists? end @safe_attributes = edited_issues.map(&:safe_attribute_names).reduce(:&) @@ -316,7 +336,8 @@ class IssuesController < ApplicationController @issues.each do |orig_issue| orig_issue.reload if @copy - issue = orig_issue.copy({}, + issue = orig_issue.copy( + {}, :attachments => copy_attachments, :subtasks => copy_subtasks, :watchers => copy_watchers, @@ -464,6 +485,7 @@ class IssuesController < ApplicationController @issue.init_journal(User.current) issue_attributes = params[:issue] + issue_attributes[:assigned_to_id] = User.current.id if issue_attributes && issue_attributes[:assigned_to_id] == 'me' if issue_attributes && params[:conflict_resolution] case params[:conflict_resolution] when 'overwrite' @@ -520,6 +542,7 @@ class IssuesController < ApplicationController # so we can use the default version for the new project attrs.delete(:fixed_version_id) end + attrs[:assigned_to_id] = User.current.id if attrs[:assigned_to_id] == 'me' @issue.safe_attributes = attrs if @issue.project @@ -554,6 +577,7 @@ class IssuesController < ApplicationController time_entry = @time_entry || TimeEntry.new time_entry.project = @issue.project time_entry.issue = @issue + time_entry.author = User.current time_entry.user = User.current time_entry.spent_on = User.current.today time_entry.safe_attributes = params[:time_entry] diff --git a/app/controllers/journals_controller.rb b/app/controllers/journals_controller.rb index 7f07b38..7a477a0 100644 --- a/app/controllers/journals_controller.rb +++ b/app/controllers/journals_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -64,13 +66,14 @@ class JournalsController < ApplicationController if @journal user = @journal.user text = @journal.notes + @content = +"#{ll(Setting.default_language, :text_user_wrote_in, {:value => user, :link => "#note-#{params[:journal_indice]}"})}\n> " else user = @issue.author text = @issue.description + @content = +"#{ll(Setting.default_language, :text_user_wrote, user)}\n> " end # Replaces pre blocks with [...] text = text.to_s.strip.gsub(%r{
(.*?)
}m, '[...]') - @content = "#{ll(Setting.default_language, :text_user_wrote, user)}\n> " @content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n" rescue ActiveRecord::RecordNotFound render_404 diff --git a/app/controllers/mail_handler_controller.rb b/app/controllers/mail_handler_controller.rb index ccb832e..389cd6f 100644 --- a/app/controllers/mail_handler_controller.rb +++ b/app/controllers/mail_handler_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -26,7 +28,7 @@ class MailHandlerController < ActionController::Base def index options = params.dup email = options.delete(:email) - if MailHandler.receive(email, options) + if MailHandler.safe_receive(email, options) head :created else head :unprocessable_entity diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index 1583e9e..119bf8e 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 76bc19c..bbc6a35 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -63,6 +65,7 @@ class MessagesController < ApplicationController if @message.save call_hook(:controller_messages_new_after_save, { :params => params, :message => @message}) render_attachment_warning_if_needed(@message) + flash[:notice] = l(:notice_successful_create) redirect_to board_message_path(@board, @message) end end @@ -80,6 +83,7 @@ class MessagesController < ApplicationController attachments = Attachment.attach_files(@reply, params[:attachments]) render_attachment_warning_if_needed(@reply) end + flash[:notice] = l(:notice_successful_update) redirect_to board_message_path(@board, @topic, :r => @reply) end @@ -101,6 +105,7 @@ class MessagesController < ApplicationController (render_403; return false) unless @message.destroyable_by?(User.current) r = @message.to_param @message.destroy + flash[:notice] = l(:notice_successful_delete) if @message.parent redirect_to board_message_path(@board, @message.parent, :r => r) else @@ -112,18 +117,23 @@ class MessagesController < ApplicationController @subject = @message.subject @subject = "RE: #{@subject}" unless @subject.starts_with?('RE:') - @content = "#{ll(Setting.default_language, :text_user_wrote, @message.author)}\n> " + if @message.root == @message + @content = +"#{ll(Setting.default_language, :text_user_wrote, @message.author)}\n> " + else + @content = +"#{ll(Setting.default_language, :text_user_wrote_in, {:value => @message.author, :link => "message##{@message.id}"})}\n> " + end @content << @message.content.to_s.strip.gsub(%r{
(.*?)
}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n" end def preview message = @board.messages.find_by_id(params[:id]) - @text = (params[:message] || params[:reply])[:content] + @text = params[:text] ? params[:text] : nil @previewed = message render :partial => 'common/preview' end -private + private + def find_message return unless find_board @message = @board.messages.includes(:parent).find(params[:id]) diff --git a/app/controllers/my_controller.rb b/app/controllers/my_controller.rb index bf04d55..606fd5c 100644 --- a/app/controllers/my_controller.rb +++ b/app/controllers/my_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -21,13 +23,17 @@ class MyController < ApplicationController # let user change user's password when user has to skip_before_action :check_password_change, :only => :password - require_sudo_mode :account, only: :post + accept_api_auth :account + + require_sudo_mode :account, only: :put require_sudo_mode :reset_rss_key, :reset_api_key, :show_api_key, :destroy helper :issues helper :users helper :custom_fields helper :queries + helper :activities + helper :calendars def index page @@ -45,15 +51,25 @@ class MyController < ApplicationController def account @user = User.current @pref = @user.pref - if request.post? + if request.put? @user.safe_attributes = params[:user] @user.pref.safe_attributes = params[:pref] if @user.save @user.pref.save set_language_if_valid @user.language - flash[:notice] = l(:notice_account_updated) - redirect_to my_account_path + respond_to do |format| + format.html { + flash[:notice] = l(:notice_account_updated) + redirect_to my_account_path + } + format.api { render_api_ok } + end return + else + respond_to do |format| + format.html { render :action => :account } + format.api { render_validation_errors(@user) } + end end end end @@ -95,7 +111,7 @@ class MyController < ApplicationController if @user.save # The session token was destroyed by the password change, generate a new one session[:tk] = @user.generate_session_token - Mailer.password_updated(@user) + Mailer.deliver_password_updated(@user, User.current) flash[:notice] = l(:notice_account_password_updated) redirect_to my_account_path end @@ -138,7 +154,7 @@ class MyController < ApplicationController block_settings = params[:settings] || {} block_settings.each do |block, settings| - @user.pref.update_block_settings(block, settings) + @user.pref.update_block_settings(block, settings.to_unsafe_hash) end @user.pref.save @updated_blocks = block_settings.keys diff --git a/app/controllers/news_controller.rb b/app/controllers/news_controller.rb index 3df9e5e..5d63f44 100644 --- a/app/controllers/news_controller.rb +++ b/app/controllers/news_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -24,7 +26,7 @@ class NewsController < ApplicationController before_action :authorize, :except => [:index] before_action :find_optional_project, :only => :index accept_rss_auth :index - accept_api_auth :index + accept_api_auth :index, :show, :create, :update, :destroy helper :watchers helper :attachments @@ -69,13 +71,21 @@ class NewsController < ApplicationController def create @news = News.new(:project => @project, :author => User.current) @news.safe_attributes = params[:news] - @news.save_attachments(params[:attachments]) + @news.save_attachments(params[:attachments] || (params[:news] && params[:news][:uploads])) if @news.save - render_attachment_warning_if_needed(@news) - flash[:notice] = l(:notice_successful_create) - redirect_to project_news_index_path(@project) + respond_to do |format| + format.html { + render_attachment_warning_if_needed(@news) + flash[:notice] = l(:notice_successful_create) + redirect_to project_news_index_path(@project) + } + format.api { render_api_ok } + end else - render :action => 'new' + respond_to do |format| + format.html { render :action => 'new' } + format.api { render_validation_errors(@news) } + end end end @@ -84,18 +94,29 @@ class NewsController < ApplicationController def update @news.safe_attributes = params[:news] - @news.save_attachments(params[:attachments]) + @news.save_attachments(params[:attachments] || (params[:news] && params[:news][:uploads])) if @news.save - render_attachment_warning_if_needed(@news) - flash[:notice] = l(:notice_successful_update) - redirect_to news_path(@news) + respond_to do |format| + format.html { + render_attachment_warning_if_needed(@news) + flash[:notice] = l(:notice_successful_update) + redirect_to news_path(@news) + } + format.api { render_api_ok } + end else - render :action => 'edit' + respond_to do |format| + format.html { render :action => 'edit' } + format.api { render_validation_errors(@news) } + end end end def destroy @news.destroy - redirect_to project_news_index_path(@project) + respond_to do |format| + format.html { redirect_to project_news_index_path(@project) } + format.api { render_api_ok } + end end end diff --git a/app/controllers/previews_controller.rb b/app/controllers/previews_controller.rb index 37cdc46..f1ef5fa 100644 --- a/app/controllers/previews_controller.rb +++ b/app/controllers/previews_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -16,28 +18,28 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class PreviewsController < ApplicationController - before_action :find_project, :find_attachments + before_action :find_project, :except => :text + before_action :find_attachments def issue - @issue = Issue.visible.find_by_id(params[:id]) unless params[:id].blank? + @issue = Issue.visible.find_by_id(params[:issue_id]) unless params[:issue_id].blank? if @issue - @description = params[:issue] && params[:issue][:description] - if @description && @description.gsub(/(\r?\n|\n\r?)/, "\n") == @issue.description.to_s.gsub(/(\r?\n|\n\r?)/, "\n") - @description = nil - end - @notes = params[:journal] ? params[:journal][:notes] : nil - @notes ||= params[:issue] ? params[:issue][:notes] : nil - else - @description = (params[:issue] ? params[:issue][:description] : nil) + @previewed = @issue end - render :layout => false + @text = params[:text] ? params[:text] : nil + render :partial => 'common/preview' end def news if params[:id].present? && news = News.visible.find_by_id(params[:id]) @previewed = news end - @text = (params[:news] ? params[:news][:description] : nil) + @text = params[:text] ? params[:text] : nil + render :partial => 'common/preview' + end + + def text + @text = params[:text] ? params[:text] : nil render :partial => 'common/preview' end diff --git a/app/controllers/principal_memberships_controller.rb b/app/controllers/principal_memberships_controller.rb index 924ecbd..fdbd8be 100644 --- a/app/controllers/principal_memberships_controller.rb +++ b/app/controllers/principal_memberships_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -19,6 +21,8 @@ class PrincipalMembershipsController < ApplicationController layout 'admin' self.main_menu = false + helper :members + before_action :require_admin before_action :find_principal, :only => [:new, :create] before_action :find_membership, :only => [:edit, :update, :destroy] diff --git a/app/controllers/project_enumerations_controller.rb b/app/controllers/project_enumerations_controller.rb index f68d948..8b2768e 100644 --- a/app/controllers/project_enumerations_controller.rb +++ b/app/controllers/project_enumerations_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -20,15 +22,8 @@ class ProjectEnumerationsController < ApplicationController before_action :authorize def update - if params[:enumerations] - saved = Project.transaction do - params[:enumerations].each do |id, activity| - @project.update_or_create_time_entry_activity(id, activity) - end - end - if saved - flash[:notice] = l(:notice_successful_update) - end + if @project.update_or_create_time_entry_activities(update_params) + flash[:notice] = l(:notice_successful_update) end redirect_to settings_project_path(@project, :tab => 'activities') @@ -41,4 +36,12 @@ class ProjectEnumerationsController < ApplicationController flash[:notice] = l(:notice_successful_update) redirect_to settings_project_path(@project, :tab => 'activities') end + + private + + def update_params + params. + permit(:enumerations => [:parent_id, :active, {:custom_field_values => {}}]). + require(:enumerations) + end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 3e3fc69..c5c98d6 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -31,8 +33,12 @@ class ProjectsController < ApplicationController helper :custom_fields helper :issues helper :queries + include QueriesHelper + helper :projects_queries + include ProjectsQueriesHelper helper :repositories helper :members + helper :trackers # Lists visible projects def index @@ -41,14 +47,19 @@ class ProjectsController < ApplicationController return end - scope = Project.visible.sorted + retrieve_project_query + scope = project_scope respond_to do |format| format.html { - unless params[:closed] - scope = scope.active + # TODO: see what to do with the board view and pagination + if @query.display_type == 'board' + @entries = scope.to_a + else + @entry_count = scope.count + @entry_pages = Paginator.new @entry_count, per_page_option, params['page'] + @entries = scope.offset(@entry_pages.offset).limit(@entry_pages.per_page).to_a end - @projects = scope.to_a } format.api { @offset, @limit = api_offset_and_limit @@ -59,6 +70,11 @@ class ProjectsController < ApplicationController projects = scope.reorder(:created_on => :desc).limit(Setting.feeds_limit.to_i).to_a render_feed(projects, :title => "#{Setting.app_title}: #{l(:label_project_latest)}") } + format.csv { + # Export all entries + @entries = scope.to_a + send_data(query_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'projects.csv') + } end end @@ -158,6 +174,7 @@ class ProjectsController < ApplicationController if User.current.allowed_to_view_all_time_entries?(@project) @total_hours = TimeEntry.visible.where(cond).sum(:hours).to_f + @total_estimated_hours = Issue.visible.where(cond).sum(:estimated_hours).to_f end @key = User.current.rss_key @@ -176,8 +193,7 @@ class ProjectsController < ApplicationController @version_status = params[:version_status] || 'open' @version_name = params[:version_name] - @versions = @project.shared_versions.status(@version_status).like(@version_name) - @wiki ||= @project.wiki || Wiki.new(:project => @project) + @versions = @project.shared_versions.status(@version_status).like(@version_name).sorted end def edit @@ -189,7 +205,7 @@ class ProjectsController < ApplicationController respond_to do |format| format.html { flash[:notice] = l(:notice_successful_update) - redirect_to settings_project_path(@project) + redirect_to settings_project_path(@project, params[:tab]) } format.api { render_api_ok } end @@ -204,12 +220,6 @@ class ProjectsController < ApplicationController end end - def modules - @project.enabled_module_names = params[:enabled_module_names] - flash[:notice] = l(:notice_successful_update) - redirect_to settings_project_path(@project, :tab => 'modules') - end - def archive unless @project.archive flash[:error] = l(:error_can_not_archive_project) @@ -224,6 +234,19 @@ class ProjectsController < ApplicationController redirect_to_referer_or admin_projects_path(:status => params[:status]) end + def bookmark + jump_box = Redmine::ProjectJumpBox.new User.current + if request.delete? + jump_box.delete_project_bookmark @project + elsif request.post? + jump_box.bookmark_project @project + end + respond_to do |format| + format.js + format.html { redirect_to project_path(@project) } + end + end + def close @project.close redirect_to project_path(@project) @@ -247,4 +270,15 @@ class ProjectsController < ApplicationController # hide project in layout @project = nil end + + private + + # Returns the ProjectEntry scope for index + def project_scope(options={}) + @query.results_scope(options) + end + + def retrieve_project_query + retrieve_query(ProjectQuery, false, :defaults => @default_columns_names) + end end diff --git a/app/controllers/queries_controller.rb b/app/controllers/queries_controller.rb index 54f695f..56283dc 100644 --- a/app/controllers/queries_controller.rb +++ b/app/controllers/queries_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -104,6 +106,10 @@ class QueriesController < ApplicationController render_404 end + def current_menu_item + @query ? @query.queried_class.to_s.underscore.pluralize.to_sym : nil + end + private def find_query @@ -114,18 +120,11 @@ class QueriesController < ApplicationController render_404 end - def find_optional_project - @project = Project.find(params[:project_id]) if params[:project_id] - render_403 unless User.current.allowed_to?(:save_queries, @project, :global => true) - rescue ActiveRecord::RecordNotFound - render_404 - end - def update_query_from_params @query.project = params[:query_is_for_all] ? nil : @project @query.build_from_params(params) @query.column_names = nil if params[:default_columns] - @query.sort_criteria = params[:query] && params[:query][:sort_criteria] + @query.sort_criteria = (params[:query] && params[:query][:sort_criteria]) || @query.sort_criteria @query.name = params[:query] && params[:query][:name] if User.current.allowed_to?(:manage_public_queries, @query.project) || User.current.admin? @query.visibility = (params[:query] && params[:query][:visibility]) || Query::VISIBILITY_PRIVATE @@ -157,6 +156,10 @@ class QueriesController < ApplicationController redirect_to _time_entries_path(@project, nil, options) end + def redirect_to_project_query(options) + redirect_to projects_path(options) + end + # Returns the Query subclass, IssueQuery by default # for compatibility with previous behaviour def query_class diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index 08c30ef..6918cb3 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -21,55 +23,56 @@ class ReportsController < ApplicationController def issue_report @trackers = @project.rolled_up_trackers(false).visible - @versions = @project.shared_versions.sort + @versions = @project.shared_versions.sorted @priorities = IssuePriority.all.reverse @categories = @project.issue_categories - @assignees = (Setting.issue_group_assignment? ? @project.principals : @project.users).sort - @authors = @project.users.sort + @assignees = (Setting.issue_group_assignment? ? @project.principals : @project.users).sorted + @authors = @project.users.sorted @subprojects = @project.descendants.visible - - @issues_by_tracker = Issue.by_tracker(@project) - @issues_by_version = Issue.by_version(@project) - @issues_by_priority = Issue.by_priority(@project) - @issues_by_category = Issue.by_category(@project) - @issues_by_assigned_to = Issue.by_assigned_to(@project) - @issues_by_author = Issue.by_author(@project) + with_subprojects = Setting.display_subprojects_issues? + @issues_by_tracker = Issue.by_tracker(@project, with_subprojects) + @issues_by_version = Issue.by_version(@project, with_subprojects) + @issues_by_priority = Issue.by_priority(@project, with_subprojects) + @issues_by_category = Issue.by_category(@project, with_subprojects) + @issues_by_assigned_to = Issue.by_assigned_to(@project, with_subprojects) + @issues_by_author = Issue.by_author(@project, with_subprojects) @issues_by_subproject = Issue.by_subproject(@project) || [] render :template => "reports/issue_report" end def issue_report_details + with_subprojects = Setting.display_subprojects_issues? case params[:detail] when "tracker" @field = "tracker_id" @rows = @project.rolled_up_trackers(false).visible - @data = Issue.by_tracker(@project) + @data = Issue.by_tracker(@project, with_subprojects) @report_title = l(:field_tracker) when "version" @field = "fixed_version_id" - @rows = @project.shared_versions.sort - @data = Issue.by_version(@project) + @rows = @project.shared_versions.sorted + @data = Issue.by_version(@project, with_subprojects) @report_title = l(:field_version) when "priority" @field = "priority_id" @rows = IssuePriority.all.reverse - @data = Issue.by_priority(@project) + @data = Issue.by_priority(@project, with_subprojects) @report_title = l(:field_priority) when "category" @field = "category_id" @rows = @project.issue_categories - @data = Issue.by_category(@project) + @data = Issue.by_category(@project, with_subprojects) @report_title = l(:field_category) when "assigned_to" @field = "assigned_to_id" - @rows = (Setting.issue_group_assignment? ? @project.principals : @project.users).sort - @data = Issue.by_assigned_to(@project) + @rows = (Setting.issue_group_assignment? ? @project.principals : @project.users).sorted + @data = Issue.by_assigned_to(@project, with_subprojects) @report_title = l(:field_assigned_to) when "author" @field = "author_id" - @rows = @project.users.sort - @data = Issue.by_author(@project) + @rows = @project.users.sorted + @data = Issue.by_author(@project, with_subprojects) @report_title = l(:field_author) when "subproject" @field = "project_id" @@ -84,6 +87,6 @@ class ReportsController < ApplicationController private def find_issue_statuses - @statuses = IssueStatus.sorted.to_a + @statuses = @project.rolled_up_statuses.sorted.to_a end end diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 29a3b59..ef903f2 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -15,13 +17,11 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -require 'SVG/Graph/Bar' -require 'SVG/Graph/BarHorizontal' require 'digest/sha1' require 'redmine/scm/adapters' -class ChangesetNotFound < Exception; end -class InvalidRevisionParam < Exception; end +class ChangesetNotFound < StandardError; end +class InvalidRevisionParam < StandardError; end class RepositoriesController < ApplicationController menu_item :repository @@ -148,6 +148,13 @@ class RepositoriesController < ApplicationController send_opt[:disposition] = disposition(@path) send_data @repository.cat(@path, @rev), send_opt else + # set up pagination from entry to entry + parent_path = @path.split('/')[0...-1].join('/') + @entries = @repository.entries(parent_path, @rev).reject(&:is_dir?) + if index = @entries.index{|e| e.name == @entry.name} + @paginator = Redmine::Pagination::Paginator.new(@entries.size, 1, index+1) + end + if !@entry.size || @entry.size <= Setting.file_max_size_displayed.to_i.kilobyte content = @repository.cat(@path, @rev) (show_error_not_found; return) unless content @@ -232,7 +239,7 @@ class RepositoriesController < ApplicationController if params[:format] == 'diff' @diff = @repository.diff(@path, @rev, @rev_to) (show_error_not_found; return) unless @diff - filename = "changeset_r#{@rev}" + filename = +"changeset_r#{@rev}" filename << "_r#{@rev_to}" if @rev_to send_data @diff.join, :filename => "#{filename}.diff", :type => 'text/x-patch', @@ -250,18 +257,20 @@ class RepositoriesController < ApplicationController Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}") unless read_fragment(@cache_key) @diff = @repository.diff(@path, @rev, @rev_to) - show_error_not_found unless @diff + (show_error_not_found; return) unless @diff end @changeset = @repository.find_changeset_by_name(@rev) @changeset_to = @rev_to ? @repository.find_changeset_by_name(@rev_to) : nil @diff_format_revisions = @repository.diff_format_revisions(@changeset, @changeset_to) + render :diff, :formats => :html, :layout => 'base.html.erb' end end def stats end + # Returns JSON data for repository graphs def graph data = nil case params[:graph] @@ -271,8 +280,7 @@ class RepositoriesController < ApplicationController data = graph_commits_per_author(@repository) end if data - headers["Content-Type"] = "image/svg+xml" - send_data(data, :type => "image/svg+xml", :disposition => "inline") + render :json => data else render_404 end @@ -313,7 +321,7 @@ class RepositoriesController < ApplicationController @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip @rev_to = params[:rev_to] - unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE) + unless REV_PARAM_RE.match?(@rev.to_s) && REV_PARAM_RE.match?(@rev_to.to_s) if @repository.branches.blank? raise InvalidRevisionParam end @@ -341,55 +349,37 @@ class RepositoriesController < ApplicationController end def graph_commits_per_month(repository) - @date_to = User.current.today - @date_from = @date_to << 11 - @date_from = Date.civil(@date_from.year, @date_from.month, 1) + date_to = User.current.today + date_from = date_to << 11 + date_from = Date.civil(date_from.year, date_from.month, 1) commits_by_day = Changeset. - where("repository_id = ? AND commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to). + where("repository_id = ? AND commit_date BETWEEN ? AND ?", repository.id, date_from, date_to). group(:commit_date). count commits_by_month = [0] * 12 - commits_by_day.each {|c| commits_by_month[(@date_to.month - c.first.to_date.month) % 12] += c.last } + commits_by_day.each {|c| commits_by_month[(date_to.month - c.first.to_date.month) % 12] += c.last } changes_by_day = Change. joins(:changeset). - where("#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to). + where("#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, date_from, date_to). group(:commit_date). count changes_by_month = [0] * 12 - changes_by_day.each {|c| changes_by_month[(@date_to.month - c.first.to_date.month) % 12] += c.last } + changes_by_day.each {|c| changes_by_month[(date_to.month - c.first.to_date.month) % 12] += c.last } fields = [] today = User.current.today 12.times {|m| fields << month_name(((today.month - 1 - m) % 12) + 1)} - graph = SVG::Graph::Bar.new( - :height => 300, - :width => 800, - :fields => fields.reverse, - :stack => :side, - :scale_integers => true, - :step_x_labels => 2, - :show_data_values => false, - :graph_title => l(:label_commits_per_month), - :show_graph_title => true - ) - - graph.add_data( - :data => commits_by_month[0..11].reverse, - :title => l(:label_revision_plural) - ) - - graph.add_data( - :data => changes_by_month[0..11].reverse, - :title => l(:label_change_plural) - ) - - graph.burn + data = { + :labels => fields.reverse, + :commits => commits_by_month[0..11].reverse, + :changes => changes_by_month[0..11].reverse + } end def graph_commits_per_author(repository) - #data + # data stats = repository.stats_by_author fields, commits_data, changes_data = [], [], [] stats.each do |name, hsh| @@ -398,7 +388,7 @@ class RepositoriesController < ApplicationController changes_data << hsh[:changes_count] end - #expand to 10 values if needed + # expand to 10 values if needed fields = fields + [""]*(10 - fields.length) if fields.length<10 commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10 changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10 @@ -406,27 +396,11 @@ class RepositoriesController < ApplicationController # Remove email address in usernames fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') } - #prepare graph - graph = SVG::Graph::BarHorizontal.new( - :height => 30 * commits_data.length, - :width => 800, - :fields => fields, - :stack => :side, - :scale_integers => true, - :show_data_values => false, - :rotate_y_labels => false, - :graph_title => l(:label_commits_per_author), - :show_graph_title => true - ) - graph.add_data( - :data => commits_data, - :title => l(:label_revision_plural) - ) - graph.add_data( - :data => changes_data, - :title => l(:label_change_plural) - ) - graph.burn + data = { + :labels => fields.reverse, + :commits => commits_data.reverse, + :changes => changes_data.reverse + } end def disposition(path) diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index b85c51b..0e29e8c 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -101,16 +103,22 @@ class RolesController < ApplicationController end def permissions - @roles = Role.sorted.to_a - @permissions = Redmine::AccessControl.permissions.select { |p| !p.public? } - if request.post? - @roles.each do |role| - role.permissions = params[:permissions][role.id.to_s] - role.save - end - flash[:notice] = l(:notice_successful_update) - redirect_to roles_path + scope = Role.sorted + if params[:ids].present? + scope = scope.where(:id => params[:ids]) end + @roles = scope.to_a + @permissions = Redmine::AccessControl.permissions.select { |p| !p.public? } + end + + def update_permissions + @roles = Role.where(:id => params[:permissions].keys) + @roles.each do |role| + role.permissions = params[:permissions][role.id.to_s] + role.save + end + flash[:notice] = l(:notice_successful_update) + redirect_to roles_path end private diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index ce9e21f..2e81281 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -16,12 +18,11 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class SearchController < ApplicationController - before_action :find_optional_project + before_action :find_optional_project_by_id, :authorize_global accept_api_auth :index def index - @question = params[:q] || "" - @question.strip! + @question = params[:q]&.strip || "" @all_words = params[:all_words] ? params[:all_words].present? : true @titles_only = params[:titles_only] ? params[:titles_only].present? : false @search_attachments = params[:attachments].presence || '0' @@ -68,7 +69,7 @@ class SearchController < ApplicationController fetcher = Redmine::Search::Fetcher.new( @question, User.current, @scope, projects_to_search, :all_words => @all_words, :titles_only => @titles_only, :attachments => @search_attachments, :open_issues => @open_issues, - :cache => params[:page].present?, :params => params + :cache => params[:page].present?, :params => params.to_unsafe_hash ) if fetcher.tokens.present? @@ -87,13 +88,4 @@ class SearchController < ApplicationController format.api { @results ||= []; render :layout => false } end end - -private - def find_optional_project - return true unless params[:id] - @project = Project.find(params[:id]) - check_project_privacy - rescue ActiveRecord::RecordNotFound - render_404 - end end diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index 7b2dceb..4ff333b 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -34,7 +36,7 @@ class SettingsController < ApplicationController def edit @notifiables = Redmine::Notifiable.all if request.post? - errors = Setting.set_all_from_params(params[:settings]) + errors = Setting.set_all_from_params(params[:settings].to_unsafe_hash) if errors.blank? flash[:notice] = l(:notice_successful_update) redirect_to settings_path(:tab => params[:tab]) @@ -46,7 +48,7 @@ class SettingsController < ApplicationController end @options = {} - user_format = User::USER_FORMATS.collect{|key, value| [key, value[:setting_order]]}.sort{|a, b| a[1] <=> b[1]} + user_format = User::USER_FORMATS.collect{|key, value| [key, value[:setting_order]]}.sort_by{|f| f[1]} @options[:user_format] = user_format.collect{|f| [User.current.name(f[0]), f[0].to_s]} @deliveries = ActionMailer::Base.perform_deliveries diff --git a/app/controllers/sys_controller.rb b/app/controllers/sys_controller.rb index bd8238a..f217ee2 100644 --- a/app/controllers/sys_controller.rb +++ b/app/controllers/sys_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -38,7 +40,7 @@ class SysController < ActionController::Base repository.safe_attributes = params[:repository] repository.project = project if repository.save - render :json => {repository.class.name.underscore.gsub('/', '-') => {:id => repository.id, :url => repository.url}}, :status => 201 + render :json => {repository.class.name.underscore.tr('/', '-') => {:id => repository.id, :url => repository.url}}, :status => 201 else head 422 end @@ -50,7 +52,7 @@ class SysController < ActionController::Base scope = Project.active.has_module(:repository) if params[:id] project = nil - if params[:id].to_s =~ /^\d*$/ + if /^\d*$/.match?(params[:id].to_s) project = scope.find(params[:id]) else project = scope.find_by_identifier(params[:id]) diff --git a/app/controllers/timelog_controller.rb b/app/controllers/timelog_controller.rb index df6b618..1d144b9 100644 --- a/app/controllers/timelog_controller.rb +++ b/app/controllers/timelog_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -25,7 +27,6 @@ class TimelogController < ApplicationController before_action :find_optional_issue, :only => [:new, :create] before_action :find_optional_project, :only => [:index, :report] - before_action :authorize_global, :only => [:new, :create, :index, :report] accept_rss_auth :index accept_api_auth :index, :show, :create, :update, :destroy @@ -91,12 +92,12 @@ class TimelogController < ApplicationController end def new - @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today) + @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :author => User.current, :spent_on => User.current.today) @time_entry.safe_attributes = params[:time_entry] end def create - @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today) + @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :author => User.current, :user => User.current, :spent_on => User.current.today) @time_entry.safe_attributes = params[:time_entry] if @time_entry.project && !User.current.allowed_to?(:log_time, @time_entry.project) render_403 @@ -146,7 +147,6 @@ class TimelogController < ApplicationController def update @time_entry.safe_attributes = params[:time_entry] - call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) if @time_entry.save @@ -166,8 +166,18 @@ class TimelogController < ApplicationController end def bulk_edit - @available_activities = @projects.map(&:activities).reduce(:&) + @target_projects = Project.allowed_to(:log_time).to_a @custom_fields = TimeEntry.first.available_custom_fields.select {|field| field.format.bulk_edit_supported} + if params[:time_entry] + @target_project = @target_projects.detect {|p| p.id.to_s == params[:time_entry][:project_id].to_s} + end + if @target_project + @available_activities = @target_project.activities + else + @available_activities = @projects.map(&:activities).reduce(:&) + end + @time_entry_params = params[:time_entry] || {} + @time_entry_params[:custom_field_values] ||= {} end def bulk_update @@ -230,7 +240,8 @@ class TimelogController < ApplicationController end end -private + private + def find_time_entry @time_entry = TimeEntry.find(params[:id]) @project = @time_entry.project @@ -262,25 +273,18 @@ private if params[:issue_id].present? @issue = Issue.find(params[:issue_id]) @project = @issue.project + authorize else find_optional_project end end - def find_optional_project - if params[:project_id].present? - @project = Project.find(params[:project_id]) - end - rescue ActiveRecord::RecordNotFound - render_404 - end - # Returns the TimeEntry scope for index and report actions def time_entry_scope(options={}) @query.results_scope(options) end def retrieve_time_entry_query - retrieve_query(TimeEntryQuery, false) + retrieve_query(TimeEntryQuery, false, :defaults => @default_columns_names) end end diff --git a/app/controllers/trackers_controller.rb b/app/controllers/trackers_controller.rb index caf6b11..e219dea 100644 --- a/app/controllers/trackers_controller.rb +++ b/app/controllers/trackers_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -32,7 +34,7 @@ class TrackersController < ApplicationController end def new - @tracker ||= Tracker.new + @tracker ||= Tracker.new(:default_status => IssueStatus.sorted.first) @tracker.safe_attributes = params[:tracker] @trackers = Tracker.sorted.to_a @projects = Project.all diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 0133f97..ec9ecba 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -28,7 +30,10 @@ class UsersController < ApplicationController include SortHelper helper :custom_fields include CustomFieldsHelper + include UsersHelper helper :principal_memberships + helper :activities + include ActivitiesHelper require_sudo_mode :create, :update, :destroy @@ -59,6 +64,9 @@ class UsersController < ApplicationController @groups = Group.givable.sort render :layout => !request.xhr? } + format.csv { + send_data(users_to_csv(scope.order(sort_clause)), :type => 'text/csv; header=present', :filename => 'users.csv') + } format.api end end @@ -72,6 +80,16 @@ class UsersController < ApplicationController # show projects based on current user visibility @memberships = @user.memberships.preload(:roles, :project).where(Project.visible_condition(User.current)).to_a + @issue_counts = {} + @issue_counts[:assigned] = { + :total => Issue.visible.assigned_to(@user).count, + :open => Issue.visible.open.assigned_to(@user).count + } + @issue_counts[:reported] = { + :total => Issue.visible.where(:author_id => @user.id).count, + :open => Issue.visible.open.where(:author_id => @user.id).count + } + respond_to do |format| format.html { events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10) @@ -95,13 +113,13 @@ class UsersController < ApplicationController @user.pref.safe_attributes = params[:pref] if @user.save - Mailer.account_information(@user, @user.password).deliver if params[:send_information] + Mailer.deliver_account_information(@user, @user.password) if params[:send_information] respond_to do |format| format.html { flash[:notice] = l(:notice_user_successful_create, :id => view_context.link_to(@user.login, user_path(@user))) if params[:continue] - attrs = params[:user].slice(:generate_password) + attrs = {:generate_password => @user.generate_password } redirect_to new_user_path(:user => attrs) else redirect_to edit_user_path(@user) @@ -140,9 +158,9 @@ class UsersController < ApplicationController @user.pref.save if was_activated - Mailer.account_activated(@user).deliver + Mailer.deliver_account_activated(@user) elsif @user.active? && params[:send_information] && @user != User.current - Mailer.account_information(@user, @user.password).deliver + Mailer.deliver_account_information(@user, @user.password) end respond_to do |format| diff --git a/app/controllers/versions_controller.rb b/app/controllers/versions_controller.rb index a536416..15c24a8 100644 --- a/app/controllers/versions_controller.rb +++ b/app/controllers/versions_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -34,7 +36,7 @@ class VersionsController < ApplicationController @trackers = @project.trackers.sorted.to_a retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?}) @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1') - project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id] + project_ids = @with_subprojects ? @project.self_and_descendants.pluck(:id) : [@project.id] @versions = @project.shared_versions.preload(:custom_values) @versions += @project.rolled_up_versions.visible.preload(:custom_values) if @with_subprojects diff --git a/app/controllers/watchers_controller.rb b/app/controllers/watchers_controller.rb index 3f080e9..f0692e3 100644 --- a/app/controllers/watchers_controller.rb +++ b/app/controllers/watchers_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index 341a64d..571e233 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index 134765e..423f94f 100644 --- a/app/controllers/wiki_controller.rb +++ b/app/controllers/wiki_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -42,8 +44,6 @@ class WikiController < ApplicationController helper :watchers include Redmine::Export::PDF - include ActionView::Helpers::SanitizeHelper - # List of pages, sorted alphabetically and by parent (hierarchy) def index load_pages_for_index @@ -72,7 +72,7 @@ class WikiController < ApplicationController @page.title = '' unless editable? @page.validate if @page.errors[:title].blank? - path = project_wiki_page_path(@project, @page.title) + path = project_wiki_page_path(@project, @page.title, :parent => params[:parent]) respond_to do |format| format.html { redirect_to path } format.js { render :js => "window.location = #{path.to_json}" } @@ -109,7 +109,7 @@ class WikiController < ApplicationController send_data(export, :type => 'text/html', :filename => filename_for_content_disposition("#{@page.title}.html")) return elsif params[:format] == 'txt' - send_data(strip_tags(@content.text), :type => 'text/plain', :filename => filename_for_content_disposition("#{@page.title}.txt")) + send_data(@content.text, :type => 'text/plain', :filename => filename_for_content_disposition("#{@page.title}.txt")) return end end @@ -325,7 +325,7 @@ class WikiController < ApplicationController @attachments += page.attachments @previewed = page.content end - @text = params[:content][:text] + @text = params[:content].present? ? params[:content][:text] : params[:text] render :partial => 'common/preview' end @@ -336,7 +336,7 @@ class WikiController < ApplicationController redirect_to :action => 'show', :id => @page.title, :project_id => @project end -private + private def find_wiki @project = Project.find(params[:project_id]) diff --git a/app/controllers/wikis_controller.rb b/app/controllers/wikis_controller.rb index c61c2f9..3c1637e 100644 --- a/app/controllers/wikis_controller.rb +++ b/app/controllers/wikis_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -19,13 +21,6 @@ class WikisController < ApplicationController menu_item :settings before_action :find_project, :authorize - # Create or update a project's wiki - def edit - @wiki = @project.wiki || Wiki.new(:project => @project) - @wiki.safe_attributes = params[:wiki] - @wiki.save if request.post? - end - # Delete a project's wiki def destroy if request.post? && params[:confirm] && @project.wiki diff --git a/app/controllers/workflows_controller.rb b/app/controllers/workflows_controller.rb index c831827..0c29b14 100644 --- a/app/controllers/workflows_controller.rb +++ b/app/controllers/workflows_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -118,7 +120,7 @@ class WorkflowsController < ApplicationController def find_roles ids = Array.wrap(params[:role_id]) if ids == ['all'] - @roles = Role.sorted.to_a + @roles = Role.sorted.select(&:consider_workflow?) elsif ids.present? @roles = Role.where(:id => ids).to_a end diff --git a/app/helpers/account_helper.rb b/app/helpers/account_helper.rb index e4d8222..1e8de67 100644 --- a/app/helpers/account_helper.rb +++ b/app/helpers/account_helper.rb @@ -1,7 +1,7 @@ -# encoding: utf-8 -# +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/helpers/activities_helper.rb b/app/helpers/activities_helper.rb index 54e5580..573e432 100644 --- a/app/helpers/activities_helper.rb +++ b/app/helpers/activities_helper.rb @@ -1,7 +1,7 @@ -# encoding: utf-8 -# +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -21,9 +21,9 @@ module ActivitiesHelper def sort_activity_events(events) events_by_group = events.group_by(&:event_group) sorted_events = [] - events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event| + events.sort_by(&:event_datetime).reverse_each do |event| if group_events = events_by_group.delete(event.event_group) - group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i| + group_events.sort_by(&:event_datetime).reverse.each_with_index do |e, i| sorted_events << [e, i > 0] end end diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb index e972ef0..a06852b 100644 --- a/app/helpers/admin_helper.rb +++ b/app/helpers/admin_helper.rb @@ -1,7 +1,7 @@ -# encoding: utf-8 -# +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 792af98..e8284a0 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,7 +1,7 @@ -# encoding: utf-8 -# +# frozen_string_literal: true + # Redmine - project management software -# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2006-2019 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -23,7 +23,6 @@ require 'cgi' module ApplicationHelper include Redmine::WikiFormatting::Macros::Definitions include Redmine::I18n - include GravatarHelper::PublicMethods include Redmine::Pagination::Helper include Redmine::SudoMode::Helper include Redmine::Themes::Helper @@ -53,7 +52,8 @@ module ApplicationHelper if user.is_a?(User) name = h(user.name(options[:format])) if user.active? || (User.current.admin? && user.logged?) - link_to name, user_path(user), :class => user.css_classes + only_path = options[:only_path].nil? ? true : options[:only_path] + link_to name, user_url(user, :only_path => only_path), :class => user.css_classes else name end @@ -62,6 +62,20 @@ module ApplicationHelper end end + # Displays a link to edit group page if current user is admin + # Otherwise display only the group name + def link_to_group(group, options={}) + if group.is_a?(Group) + name = h(group.name) + if User.current.admin? + only_path = options[:only_path].nil? ? true : options[:only_path] + link_to name, edit_group_path(group, :only_path => only_path) + else + name + end + end + end + # Displays a link to +issue+ with its subject. # Examples: # @@ -97,10 +111,17 @@ module ApplicationHelper # * :download - Force download (default: false) def link_to_attachment(attachment, options={}) text = options.delete(:text) || attachment.filename - route_method = options.delete(:download) ? :download_named_attachment_url : :named_attachment_url - html_options = options.slice!(:only_path) + if options.delete(:download) + route_method = :download_named_attachment_url + options[:filename] = attachment.filename + else + route_method = :attachment_url + # make sure we don't have an extraneous :filename in the options + options.delete(:filename) + end + html_options = options.slice!(:only_path, :filename) options[:only_path] = true unless options.key?(:only_path) - url = send(route_method, attachment, attachment.filename, options) + url = send(route_method, attachment, options) link_to text, url, html_options end @@ -146,8 +167,8 @@ module ApplicationHelper h(project.name) else link_to project.name, - project_url(project, {:only_path => true}.merge(options)), - html_options + project_url(project, {:only_path => true}.merge(options)), + html_options end end @@ -169,6 +190,39 @@ module ApplicationHelper link_to_if version.visible?, format_version_name(version), version_path(version), options end + RECORD_LINK = { + 'CustomValue' => -> (custom_value) { link_to_record(custom_value.customized) }, + 'Document' => -> (document) { link_to(document.title, document_path(document)) }, + 'Group' => -> (group) { link_to(group.name, group_path(group)) }, + 'Issue' => -> (issue) { link_to_issue(issue, :subject => false) }, + 'Message' => -> (message) { link_to_message(message) }, + 'News' => -> (news) { link_to(news.title, news_path(news)) }, + 'Project' => -> (project) { link_to_project(project) }, + 'User' => -> (user) { link_to_user(user) }, + 'Version' => -> (version) { link_to_version(version) }, + 'WikiPage' => -> (wiki_page) { link_to(wiki_page.pretty_title, project_wiki_page_path(wiki_page.project, wiki_page.title)) } + } + + def link_to_record(record) + if link = RECORD_LINK[record.class.name] + self.instance_exec(record, &link) + end + end + + ATTACHMENT_CONTAINER_LINK = { + # Custom list, since project/version attachments are listed in the files + # view and not in the project/milestone view + 'Project' => -> (project) { link_to(l(:project_module_files), project_files_path(project)) }, + 'Version' => -> (version) { link_to(l(:project_module_files), project_files_path(version.project)) }, + } + + def link_to_attachment_container(attachment_container) + if link = ATTACHMENT_CONTAINER_LINK[attachment_container.class.name] || + RECORD_LINK[attachment_container.class.name] + self.instance_exec(attachment_container, &link) + end + end + # Helper that formats object for html or text rendering def format_object(object, html=true, &block) if block_given? @@ -228,22 +282,57 @@ module ApplicationHelper :srcset => "#{thumbnail_path(attachment, :size => thumbnail_size * 2)} 2x", :style => "max-width: #{thumbnail_size}px; max-height: #{thumbnail_size}px;" ), - named_attachment_path( - attachment, - attachment.filename + attachment_path( + attachment ), :title => attachment.filename ) end def toggle_link(name, id, options={}) - onclick = "$('##{id}').toggle(); " + onclick = +"$('##{id}').toggle(); " onclick << (options[:focus] ? "$('##{options[:focus]}').focus(); " : "this.blur(); ") onclick << "$(window).scrollTop($('##{options[:focus]}').position().top); " if options[:scroll] onclick << "return false;" link_to(name, "#", :onclick => onclick) end + def link_to_previous_month(year, month, options={}) + target_year, target_month = if month == 1 + [year - 1, 12] + else + [year, month - 1] + end + + name = if target_month == 12 + "#{month_name(target_month)} #{target_year}" + else + month_name(target_month) + end + + link_to_month(("« " + name), target_year, target_month, options) + end + + def link_to_next_month(year, month, options={}) + target_year, target_month = if month == 12 + [year + 1, 1] + else + [year, month + 1] + end + + name = if target_month == 1 + "#{month_name(target_month)} #{target_year}" + else + month_name(target_month) + end + + link_to_month((name + " »"), target_year, target_month, options) + end + + def link_to_month(link_name, year, month, options={}) + link_to(link_name, {:params => request.query_parameters.merge(:year => year, :month => month)}, options) + end + # Used to format item titles on the activity view def format_activity_title(text) text @@ -281,19 +370,19 @@ module ApplicationHelper # The given collection may be a subset of the whole project tree # (eg. some intermediate nodes are private and can not be seen) def render_project_nested_lists(projects, &block) - s = '' + s = +'' if projects.any? ancestors = [] original_project = @project projects.sort_by(&:lft).each do |project| # set the project environment to please macros. @project = project - if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) + if ancestors.empty? || project.is_descendant_of?(ancestors.last) s << "\n" end @@ -311,12 +400,17 @@ module ApplicationHelper end def render_page_hierarchy(pages, node=nil, options={}) - content = '' + content = +'' if pages[node] content << "