[
  {
    "path": ".gitignore",
    "content": ".DS_Store\n*~\ntest/app/*\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: ruby\nrvm:\n- 2.5\n- 2.6\n- jruby\nservices:\n  - mysql\n  - postgresql\nenv:\n  global:\n  - REDMINE_LANG=en\n  - MYSQL_DATABASE=redmine\n  - MYSQL_HOST=127.0.0.1\n  - MYSQL_PORT=3306\n  - MYSQL_USER=root\n  - MYSQL_PASSWORD=\n  - POSTGRES_DATABASE=redmine\n  - POSTGRES_USER=postgres\n  matrix:\n  - REDMINE_VERSION=4.0.5 DATABASE_ADAPTER=mysql\n  - REDMINE_VERSION=4.0.5 DATABASE_ADAPTER=postgresql\nmatrix:\n  allow_failures: # Incomplete ActiveRecord 4.2 support in jruby\n  - rvm: 2.6\n    env: REDMINE_VERSION=4.0.5 DATABASE_ADAPTER=mysql\n  - rvm: 2.6\n    env: REDMINE_VERSION=4.0.5 DATABASE_ADAPTER=postgresql\n  - rvm: jruby\n    env: REDMINE_VERSION=4.0.5 DATABASE_ADAPTER=mysql\n  - rvm: jruby\n    env: REDMINE_VERSION=4.0.5 DATABASE_ADAPTER=postgresql\naddons:\n  code_climate:\n    repo_token:\n      secure: \"SAyz/KNRQQC1T2oGNUxbDceBcoaL/IxvEmeKEIR3iivj3RMJi2Nm8v5B2Su9MhQBegi2mH70ypgkTPmGh69tSONf1sqkkCAxsZnIqihl1Ai+dwM2KlBLGw/k+IG9/xD1+hgQiO06OKZMPO+Kj9X28mMqJ75YVKGE4alr1mfo2NM=\"\nbefore_install:\n  - rake helpdesk:redmine:install\n  - cd test/app\n  - export BUNDLE_GEMFILE=Gemfile\nbefore_script:\n  - echo $(pwd)\n  - sudo service mysql start\n  - echo $(ps -Af | grep mysqld)\n  - export RAILS_ENV=test\n  - mysql -e 'create database redmine;'\n  - psql -c 'create database redmine;' -U postgres\n  - bundle exec rake generate_secret_token\n  - export RAILS_ENV=test\n  - bundle exec rake db:migrate\nscript:\n  - bundle exec rake helpdesk:ci\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "0.0.20\n---\n* Make plugin compatibility with Redmine 5.0.x\n\n0.0.19\n---\n* Italian translation\n* Fix logger and use new setting\n* Do not send on private-notes\n* Fix reopening closed issue error\n* Improve de locale\n* Fix typo in email_was_send_to_supportclient\n* Sets To header optional\n* Remove Gemfile.lock\n* Find and process value of custom field directly\n* Add X-Redmine-Issue-Tracker header to mailerpatch\n\n0.0.18\n---\n* Remove batches as nobody has the time to fix the tests\n* Remove untrue stuff from readme\n* Update mail_handler_patch.rb\n* Fix migration\n* Incorrect issue and project ids usage\n* Add space after the pre\n\n0.0.17\n---\n* Fix issue by sending redmine journals with redmine_helpdesk\n* Store email-details before each note by martincizek from orchitech\n* Make option to reopen closed issues by email work\n* Added support for reply separator by sandratatarevicova from orchitech\n\n0.0.16\n---\n* Make plugin compatibility with Redmine 4.0.x\n* Add option to reopen closed issues by email\n\n0.0.15\n---\n* Added support for tracking email details by martincizek from orchitech\n\n0.0.14\n---\n* Make plugin compatibility with Redmine 3.0.1 by Vilppu Vuorinen\n\n0.0.13\n---\n* Unit and functional tests with travis and code climate support by Vilppu Vuorinen\n* Add customizable email footers by martincizek\n* Test compatibility with Redmine 2.6.2\n\n0.0.12\n---\n* Add support for non-anonymous supportclients by martincizek\n* Add issue matching based on standard MIME header references by martincizek\n* Test compatibility with Redmine 2.5.3\n\n0.0.11\n---\n* Make sure that the notes length is always calculated\n\n0.0.10\n---\n* Fixed bug trying to send an email with empty notes\n\n0.0.9\n---\n* Fixed non-working helpdesk-send-to-owner-default checkbox\n\n0.0.8\n---\n* Add setting for handling send to owner default value by davidef\n\n0.0.7\n---\n* Added reply-to header by barbazul\n\n0.0.6\n---\n* Update code for redmine 2.4.x by Craig Gowing\n* Minor compatibility issues fixed\n\n0.0.5\n---\n* Fix skip validation issue \n\n0.0.4\n---\n* Update code for redmine 2.3.x\n* Send any journal attachments with the email notification to the supportclient\n\n0.0.3\n---\n* The sender email-address is now adjustable on a per project basis\n\n0.0.2\n---\n* A standard first reply message can be send to the supportclient on ticket creation (optional, per project)\n* The email-footer for the email notification to the supportclient can be adjusted (optional, per project)\n\n0.0.1\n---\n* First release"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Issues\n\nPlease note that I cannot provide user support for this open source project. All issues related to user support will be closed without a further comment. Open source does not mean that I have unlimited time to solve problems of others for free!\n\nIf you need professional help please [contact me](http://www.qutic.com/support \"hire a consultant\") directly - I am for hire.\n\nIf you find a bug please create an issue in the tracker, write a patch and send me a pull request :-)\n"
  },
  {
    "path": "Gemfile",
    "content": "gem \"codeclimate-test-reporter\", group: :test, require: nil\nunless (Gem::Specification::find_all_by_name('rake').any?)\n  gem \"rake\", group: :test, require: nil\nend\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2012-2021 qutic development GmbH\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# Redmine Helpdesk\n\nLightweight helpdesk plugin for redmine. Adds the email sender-address of an anonymous supportclient to the custom field 'owner-email' of a ticket which was created by a support email. Answers can be send to the supportclient by checking the support checkbox on a journal.\n\n## Support\n\nYou want to support the development of this plugin? [We provide Redmine hosting including the Helpdesk plugin](https://qutic.com/de/loesungen/redmine-hosting/).\n\n## Features\n\n* No need to create any user accounts for anonymous user\n* Support for sending an email notification to the (anonymous user) supportclient on ticket creation\n* A standard first reply message can be send to the supportclient on ticket creation (optional, per project)\n* The email-footer for the email notification to the supportclient can be adjusted (optional, per project)\n* The email-footer can be customized by using the following placeholders: \n  - Issue parameters\n    - ##issue-id##\n    - ##issue-subject##\n    - ##issue-tracker##\n    - ##issue-status##\n  - Project parameters\n    - ##project-name##\n  - User parameters\n    - ##user-name## \n    - ##user-firstname##\n    - ##user-lastname##\n    - ##user-mail##\n    - ##user-login##\n    - all user custom fields: ##user-cf-[user's custom field name]##, e.g. ##user-cf-position##\n  - Base parameters\n    - ##time-now##\n* The sender email-address can be adjusted (optional, per project)\n* Internal communication is not send to the supportclient\n* The supportclient will get an email notification if the support checkbox on the journal is checked (default value is optional)\n* Journal attachments will be delivered too\n* Cc header is handled if the cc-handling checkbox is checked. (optional, per project)\n* Reopening a closed issue is handled if the reopen-closed-issues-by-email checkbox is checked. (optional, per project)\n\n## Screenshot\n\n![Send mail to supportclient](doc/send-mail-to-supportclient.jpg \"New checkbox 'Send mail to supportclient'\")\n\n## Getting the plugin\n\nA copy of the plugin can be downloaded from [GitHub](https://github.com/jfqd/redmine_helpdesk)\n\n## Installation\n\nTo install the plugin clone the repo from github and migrate the database:\n\n```\ncd /path/to/redmine/\ngit clone git://github.com/jfqd/redmine_helpdesk.git plugins/redmine_helpdesk\nbundle install --without development test rmagick\nbundle exec rake redmine:plugins:migrate RAILS_ENV=production\n```\n\nTo uninstall the plugin migrate the database back and remove the plugin:\n\n```\ncd /path/to/redmine/\nrake redmine:plugins:migrate NAME=redmine_helpdesk VERSION=0 RAILS_ENV=production\nrm -rf plugins/redmine_helpdesk\n```\n\nFurther information about plugin installation can be found at: https://www.redmine.org/wiki/redmine/Plugins\n\n## Usage\n\nTo use the helpdesk functionality you need to\n\n* add the custom field 'owner-email' to a project in the project configuration\n* add a standard first reply message into the custom_field 'helpdesk-first-reply' in the project configuration (optional)\n* add an email-footer into the custom_field 'helpdesk-email-footer' in the project configuration\n* add a sender email address into the custom_field 'helpdesk-sender-email' in the project configuration (optional)\n* make sure 'Issue added' and 'Issue updated' in the general redmine settings for email notifications are checked\n* add the permission 'Treat as supportclient' to all roles you want to be treated as supportclient (the permission is automatically added to the 'Anonymous' role)\n* disable standard notifications for non-anonymous supportclients to prevent their spamming (optional)\n* add a cronjob for creating issues from support emails\n\n![project configuration sample](doc/project-settings.jpg \"Per project configuration sample\")\n\n## Cronjob\n\nCreating tickets from support emails through an IMAP-account is done by a cronjob. If you are not familiar with cron you first should read about the concept. The following syntax is for ubuntu or debian linux:\n\n```\n*/5 * * * * redmineuser /path/to/your/rake -f /path/to/redmine/Rakefile --silent redmine:email:receive_imap RAILS_ENV=\"production\" host=mail.example.com port=993 username=username password=password ssl=true project=project_identifier folder=INBOX move_on_success=processed move_on_failure=failed no_permission_check=1 unknown_user=accept 1 > /dev/null\n```\n\nFurther information about receiving emails with redmine can be found at: [https://www.redmine.org/projects/redmine/wiki/RedmineReceivingEmails](https://www.redmine.org/projects/redmine/wiki/RedmineReceivingEmails#Fetching-emails-from-an-IMAP-server)\n\nPlease note that forwarding emails with **rdm-mailhandler.rb** is currently **not supported** by the plugin.\n\n## Compatibility\n\nThe latest version of this plugin is only compatible with Redmine 5.0, 5.1.\n\n* A version for Redmine 4.2.x is tagged with [v4.2](https://github.com/jfqd/redmine_helpdesk/releases/tag/v4.2 \"plugin version for Redmine 4.2.x\") and available for [download on github](https://github.com/jfqd/redmine_helpdesk/archive/v4.2.zip \"download plugin for Redmine 4.2.x\").\n* A version for Redmine 4.0.x is tagged with [v4.0](https://github.com/jfqd/redmine_helpdesk/releases/tag/v4.0 \"plugin version for Redmine 4.0.x\") and available for [download on github](https://github.com/jfqd/redmine_helpdesk/archive/v4.0.zip \"download plugin for Redmine 4.0.x\").\n* A version for Redmine 3.0.x and 3.1.x is tagged with [v3.1](https://github.com/jfqd/redmine_helpdesk/releases/tag/v3.1 \"plugin version for Redmine 3.0.x and 3.1.x\") and available for [download on github](https://github.com/jfqd/redmine_helpdesk/archive/v3.1.zip \"download plugin for Redmine 3.0.x and 3.1.x\").\n* A version for Redmine 2.4.x and 2.5.x is tagged with [v2.5](https://github.com/jfqd/redmine_helpdesk/releases/tag/v2.5 \"plugin version for Redmine 2.4.x and 2.5.x\") and available for [download on github](https://github.com/jfqd/redmine_helpdesk/archive/v2.5.zip \"download plugin for Redmine 2.4.x and 2.5.x\").\n* A version for Redmine 2.3.x is tagged with [v2.3](https://github.com/jfqd/redmine_helpdesk/tree/v2.3 \"plugin version for Redmine 2.3.x\") and available for [download on github](https://github.com/jfqd/redmine_helpdesk/archive/v2.3.zip \"download plugin for Redmine 2.3.x\").\n* A version for Redmine 1.2.x. up to 1.4.7. is tagged with [v1.4](https://github.com/jfqd/redmine_helpdesk/tree/v1.4 \"plugin version for Redmine 1.2.x up to 1.4.7\") and available for [download on github](https://github.com/jfqd/redmine_helpdesk/archive/v1.4.zip \"download plugin for Redmine 1.2.x up to 1.4.7\").\n\nIf you prefer to run Redmine with JRuby make sure to use Redmine versions prior to 3.0.x!\n\n## Development\n\n### Testing\n\nRake tasks for testing against Redmine are provided. Redmine is installed under `test/app` and tests are run against the local instance.\n\n```bash\nREDMINE_VERSION=3.2 DATABASE_ADAPTER=mysql rake helpdesk:redmine:install\n```\n\nDocker is used to provide local MySQL (`DATABASE_ADAPTER=mysql`) and PostgreSQL (`DATABASE_ADAPTER=postgresql_ext`) instances.\n\n```bash\nexport DATABASE_ADAPTER=mysql\nrake helpdesk:prepare_local\nrake helpdesk:migrate\n```\n\nTest suite can be executed with:\n\n```bash\nDATABASE_ADAPTER=mysql rake helpdesk:ext_ci\n```\n\nThe local database instance has to be stopped with a rake task:\n\n```bash\nrake helpdesk:localdb:stop\n```\n\n## Contributions\n\n* [MatthiasPetermann](https://github.com/MatthiasPetermann) - Update for compatibility with Redmine 5.x / Rails 6.x\n* [rrsach](https://github.com/rrsach) - Redmine 5 Compatibility\n* [gianpaol0](https://github.com/gianpaol0) - italian translation\n* [mgeerdsen](https://github.com/mgeerdsen) - Fix reopening closed issue error\n* [mgeerdsen](https://github.com/mgeerdsen) - Improve de locale\n* [lmorillas](https://github.com/lmorillas) - Fix Error when message hasn't \"To:\" header\n* [promasu](https://github.com/promasu) - Add X-Redmine-Issue-Tracker header to mailerpatch\n* [ANemcov](https://github.com/ANemcov) - incorrect issue and project ids usage\n* [ismaelgc](https://github.com/ismaelgc) - Spanish translation\n* [monaka](https://github.com/monaka) - Japanese translation\n* [avoidik](https://github.com/avoidik) - Add missed Russian translation into roles and access manager\n* [WhereIsPedro](https://github.com/WhereIsPedro) - Polish translation\n* [vilppuvuorinen](https://github.com/vilppuvuorinen) - 3.0.x compatibility\n* [vilppuvuorinen](https://github.com/vilppuvuorinen) - Unit and functional tests with travis and code climate support\n* [ssidelnikov](https://github.com/ssidelnikov) - Make sure that the notes length is always calculated\n* [nifuki](https://github.com/nifuki) - Fixed bug trying to send an email with empty notes\n* [nifuki](https://github.com/nifuki) - Fixed non-working helpdesk-send-to-owner-default checkbox\n* [box789](https://github.com/box789) - Russian translation\n* [seqizz](https://github.com/seqizz) - Turkish translation\n* [benstwa](https://github.com/benstwa) - 'send' should be 'sent'\n* [davidef](https://github.com/davidef) - Add setting for handling sent to owner default value\n* [Craig Gowing](https://github.com/craiggowing) - Redmine 2.4 compatibility\n* [Barbazul](https://github.com/barbazul) - Added reply-to header\n* [Orchitech Solutions](https://github.com/orchitech) - Added issue matching based on standard MIME header references\n* [Orchitech Solutions](https://github.com/orchitech) - Added support for non-anonymous supportclients (sponsored by ISIC Global Office)\n* [Orchitech Solutions](https://github.com/orchitech) - Added support for customizable email footers (sponsored by ISIC Global Office)\n* [Orchitech Solutions](https://github.com/orchitech) - Added support for tracking email details (sponsored by ISIC Global Office)\n* [shackijj](https://github.com/shackijj) - Added Cc header handling\n* [archonwang](https://github.com/archonwang) - Add Simplified Chinese\n* [Niremizov](https://github.com/Niremizov) - Set owner email only if it wasn't set before\n* [ghost](https://github.com/ghost) - Fix attachements truncated in email sent to supportclient\n* [Orchitech Solutions](https://github.com/orchitech) - Added support for reply separator (sponsored by ISIC Global Office)\n\n## License\n\nThis plugin is licensed under the MIT license. See LICENSE-file for details.\n\n## Copyright\n\nCopyright (c) 2012-2022 qutic development GmbH\n"
  },
  {
    "path": "Rakefile",
    "content": "Dir.glob('lib/tasks/*.rake').each { |r| load r}\n"
  },
  {
    "path": "app/views/_issue_edit.erb",
    "content": "<%= check_box_tag('send_to_owner', \"true\", (send_to_owner_default == \"1\")) %> <%=h t('label_support_checkbox') %> (<%=h email %>)\n"
  },
  {
    "path": "app/views/_issue_history.erb",
    "content": "<i style=\"display:block;margin-bottom:10px;\"><%=h t('email_was_send_to_supportclient') %></i>"
  },
  {
    "path": "config/locales/de.yml",
    "content": "de:\n  label_support_checkbox: \"E-Mail an Support-Anfragenden senden\"\n  email_was_send_to_supportclient: \"Diese Antwort wurde an den Support-Anfragenden gesendet.\"\n  permission_treat_user_as_supportclient: \"Nutzer als Support-Anfragenden behandeln\""
  },
  {
    "path": "config/locales/en.yml",
    "content": "en:\n  label_support_checkbox: \"Send mail to supportclient\"\n  email_was_send_to_supportclient: \"This answer was sent to the supportclient.\"\n"
  },
  {
    "path": "config/locales/es.yml",
    "content": "es:\n  label_support_checkbox: \"Enviar correo al usuario de soporte\"\n  email_was_send_to_supportclient: \"Esta respuesta ha sido enviada al usuario de soporte.\"\n"
  },
  {
    "path": "config/locales/it.yml",
    "content": "it:\n  label_support_checkbox: \"Invia email al cliente\"\n  email_was_send_to_supportclient: \"Questa risposta è stata inviata al cliente.\"\n"
  },
  {
    "path": "config/locales/ja.yml",
    "content": "ja:\n  label_support_checkbox: \"サポート顧客へメールを送信\"\n  email_was_send_to_supportclient: \"この回答はサポート顧客へ送信されました。\"\n"
  },
  {
    "path": "config/locales/pl.yml",
    "content": "pl:\n  label_support_checkbox: \"Wyślij wiadomość do klienta\"\n  email_was_send_to_supportclient: \"Wiadomość została wysłana do klienta.\"\n"
  },
  {
    "path": "config/locales/ru.yml",
    "content": "ru:\n  label_support_checkbox: \"Отправить e-mail клиенту поддержки\"\n  email_was_send_to_supportclient: \"Этот ответ был отправлен клиенту поддержки\"\n  permission_treat_user_as_supportclient: \"Определять пользователя как клиента техподдержки\"  \n"
  },
  {
    "path": "config/locales/tr.yml",
    "content": "tr:\n  label_support_checkbox: \"Bu yanıtı destek isteyen müşteriye e-posta ile gönder\"\n  email_was_send_to_supportclient: \"Bu yanıt destek talebi isteyen müşteriye de gönderildi.\"\n\n"
  },
  {
    "path": "config/locales/zh.yml",
    "content": "zh:\n  label_support_checkbox: \"发送反馈Email至客户\"\n  email_was_send_to_supportclient: \"反馈邮件已发送至客户。\"\n  permission_treat_user_as_supportclient: \"将用户作为客户\"  \n"
  },
  {
    "path": "db/migrate/001_create_custom_owner_email_field.rb",
    "content": "class CreateCustomOwnerEmailField < ActiveRecord::Migration[5.2]\n  def self.up\n    # fix PG:DuplicateColumn errors\n    # https://github.com/jfqd/redmine_helpdesk/issues/66\n    unless column_exists? :journals, :send_to_owner\n      add_column :journals, :send_to_owner, :boolean, :default => false\n      c = CustomField.new(\n        :name => 'owner-email',\n        :editable => true,\n        :field_format => 'string')\n      c.type = 'IssueCustomField' # cannot be set by mass assignement!\n      c.save\n      Tracker.all.each do |t|\n        execute \"INSERT INTO custom_fields_trackers (custom_field_id,tracker_id) VALUES (#{c.id},#{t.id})\"\n      end\n    end\n  end\n\n  def self.down\n    c = CustomField.find_by_name('owner-email')\n    execute \"DELETE FROM custom_fields_trackers WHERE custom_field_id=#{c.id}\"\n    c.delete\n    remove_column :journals, :send_to_owner\n  end\nend\n"
  },
  {
    "path": "db/migrate/002_create_custom_fields_for_reply.rb",
    "content": "class CreateCustomFieldsForReply < ActiveRecord::Migration[5.2]\n  def self.up\n    c = CustomField.new(\n      :name => 'helpdesk-first-reply',\n      :editable => true,\n      :visible => false,          # do not show it on the project summary page\n      :field_format => 'text')\n    c.type = 'ProjectCustomField' # cannot be set by mass assignement!\n    c.save\n    d = CustomField.new(\n      :name => 'helpdesk-email-footer',\n      :editable => true,\n      :visible => false,          # do not show it on the project summary page\n      :field_format => 'text')\n    d.type = 'ProjectCustomField' # cannot be set by mass assignement!\n    d.save\n  end\n\n  def self.down\n    CustomField.find_by_name('helpdesk-first-reply').delete\n    CustomField.find_by_name('helpdesk-email-footer').delete\n  end\nend"
  },
  {
    "path": "db/migrate/003_create_custom_field_for_sender_email.rb",
    "content": "class CreateCustomFieldForSenderEmail < ActiveRecord::Migration[5.2]\n  def self.up\n    c = CustomField.new(\n      :name => 'helpdesk-sender-email',\n      :editable => true,\n      :visible => true,\n      :field_format => 'string')\n    c.type = 'ProjectCustomField' # cannot be set by mass assignement!\n    c.save\n  end\n\n  def self.down\n    CustomField.find_by_name('helpdesk-sender-email').delete\n  end\nend"
  },
  {
    "path": "db/migrate/004_create_custom_field_for_send_to_owner_default.rb",
    "content": "class CreateCustomFieldForSendToOwnerDefault < ActiveRecord::Migration[5.2]\n  def self.up\n    c = CustomField.new(\n      :name => 'helpdesk-send-to-owner-default',\n      :editable => true,\n      :visible => false,          # do not show it on the project summary page\n      :field_format => 'bool')\n    c.type = 'ProjectCustomField' # cannot be set by mass assignement!\n    c.save\n  end\n\n  def self.down\n    CustomField.find_by_name('helpdesk-send-to-owner-default').delete\n  end\nend\n"
  },
  {
    "path": "db/migrate/005_add_treat_as_supportclient_to_anonymous.rb",
    "content": "class AddTreatAsSupportclientToAnonymous < ActiveRecord::Migration[5.2]\n  def self.up\n    anon_id = User.where(type: 'AnonymousUser').first.try(:id) ||\n              User.where('lastname LIKE ?', 'Anonymous').first.try(:id) ||\n              4\n    role = Role.where(builtin: anon_id).first\n    role.add_permission!(:treat_user_as_supportclient) unless role.nil?\n  end\n\n  def self.down\n    Role.all.each do |r|\n      r.remove_permission!(:treat_user_as_supportclient)\n    end\n  end\nend\n"
  },
  {
    "path": "db/migrate/006_append_footer_to_first_reply.rb",
    "content": "class AppendFooterToFirstReply < ActiveRecord::Migration[5.2]\n\n  # Appends helpdesk-email-footer to helpdesk-first-reply to ensure backward\n  # compatibility for updaters. See https://github.com/jfqd/redmine_helpdesk/issues/52\n  def self.up\n    first_reply_cf_id = CustomField.find_by_name('helpdesk-first-reply').id\n    footer_cf_id = CustomField.find_by_name('helpdesk-email-footer').id\n\n    CustomValue.where(:custom_field_id => first_reply_cf_id).each do |first_reply_cv|\n      if !first_reply_cv.value.nil?\n        first_reply_with_footer = first_reply_cv.value\n        first_reply_with_footer << \"\\n\\n\"\n        first_reply_with_footer << CustomValue.where(\"custom_field_id=? and customized_id=?\", footer_cf_id, first_reply_cv.customized_id).first.value\n\n        CustomValue.update(first_reply_cv.id, :value => first_reply_with_footer)\n      end\n    end\n  end\n\nend\n"
  },
  {
    "path": "db/migrate/007_create_custom_copy_to_field.rb",
    "content": "class CreateCustomCopyToField < ActiveRecord::Migration[5.2]\n  def self.up\n    c = CustomField.new(\n      :name => 'copy-to',\n      :editable => true,\n      :field_format => 'string')\n    c.type = 'IssueCustomField' # cannot be set by mass assignement!\n    c.save\n    Tracker.all.each do |t|\n      execute \"INSERT INTO custom_fields_trackers (custom_field_id,tracker_id) VALUES (#{c.id},#{t.id})\"\n    end\n  end\n\n  def self.down\n    c = CustomField.find_by_name('copy-to')\n    execute \"DELETE FROM custom_fields_trackers WHERE custom_field_id=#{c.id}\"\n    c.delete\n  end\nend\n"
  },
  {
    "path": "db/migrate/008_create_custom_field_cc_handling.rb",
    "content": "class CreateCustomFieldCcHandling < ActiveRecord::Migration[5.2]\n  def self.up\n    c = CustomField.new(\n      :name => 'cc-handling',\n      :editable => true,\n      :visible => true,\n      :field_format => 'bool')\n    c.type = 'ProjectCustomField' # cannot be set by mass assignement!\n    c.save\n  end\n\n  def self.down\n    CustomField.find_by_name('cc-handling').delete\n  end\nend\n"
  },
  {
    "path": "db/migrate/009_create_custom_field_for_reopen_closed_issues_by_email.rb",
    "content": "class CreateCustomFieldForReopenClosedIssuesByEmail < ActiveRecord::Migration[5.2]\n  def self.up\n    c = CustomField.new(\n      :name => 'reopen-issues-with',\n      :editable => true,\n      :visible => true,\n      :field_format => 'string')\n    c.type = 'ProjectCustomField' # cannot be set by mass assignement!\n    c.save\n  end\n\n  def self.down\n    CustomField.find_by_name('reopen-issues-with').delete\n  end\nend"
  },
  {
    "path": "db/migrate/010_create_custom_field_for_reply_separator.rb",
    "content": "class CreateCustomFieldForReplySeparator < ActiveRecord::Migration[5.2]\n  def self.up\n    begin\n      c = CustomField.new(\n        :name => 'helpdesk-reply-separator',\n        :editable => true,\n        :visible => false,          # do not show it on the project summary page\n        :field_format => 'string',\n        :default_value => '-- Reply above this line --')\n      c.type = 'ProjectCustomField'\n      c.save\n    rescue\n      # rescue a possible migration error caused by renumbering the file\n    end\n  end\n\n  def self.down\n    CustomField.find_by_name('helpdesk-reply-separator').delete\n  end\nend"
  },
  {
    "path": "init.rb",
    "content": "require 'redmine'\n$LOAD_PATH.unshift \"#{File.dirname(__FILE__)}/lib\"\nrequire 'helpdesk_hooks'\nrequire 'helpdesk_mailer'\nrequire 'redmine_helpdesk/journal_patch'\nrequire 'redmine_helpdesk/mail_handler_patch'\nrequire 'redmine_helpdesk/mailer_patch'\n\nRedmine::Plugin.register :redmine_helpdesk do\n  name 'Redmine helpdesk plugin'\n  author 'Stefan Husch'\n  description 'Redmine helpdesk plugin'\n  version '0.0.20'\n  requires_redmine :version_or_higher => '5.0.0'\n  project_module :issue_tracking do\n    permission :treat_user_as_supportclient, {}\n  end\nend\n"
  },
  {
    "path": "lib/helpdesk_hooks.rb",
    "content": "class HelpdeskHooks < Redmine::Hook::Listener\n  \n  # render partial for 'Send mail to supportclient'\n  def view_issues_edit_notes_bottom(context={})\n    i = Issue.find(context[:issue].id)\n    c = CustomField.find_by_name('owner-email')\n    owner_email = i.custom_value_for(c).try(:value)\n    return if owner_email.blank?\n    p = i.project\n    s = CustomField.find_by_name('helpdesk-send-to-owner-default')\n    send_to_owner_default = p.custom_value_for(s).try(:value) if p.present? && s.present?\n    lookup   = ActionView::LookupContext.new(File.dirname(__FILE__) + '/../app/views/')\n    context  = ActionView::Base.with_empty_template_cache.new(lookup, {}, nil)\n    renderer = ActionView::Renderer.new(lookup)\n    renderer.render(\n      context,\n      partial: \"issue_edit\",\n      locals: {\n        email: owner_email,\n        send_to_owner_default: (send_to_owner_default.present? && send_to_owner_default || false)\n      }\n    )\n  end\n  \n  # fetch 'send_to_owner' param and set the value into journal.send_to_owner\n  def controller_issues_edit_before_save(context={})\n    send_to_owner = (context[:params]['send_to_owner'] == \"true\")\n    context[:journal].send_to_owner = send_to_owner\n  end\n  \n  # add a history note on the journal\n  def view_issues_history_journal_bottom(context={})\n    return if (context[:journal].nil? || context[:journal].notes.nil? || context[:journal].notes.length == 0)\n    return unless context[:journal].send_to_owner == true\n    i = Issue.find(context[:journal].journalized_id)\n    c = CustomField.find_by_name('owner-email')\n    owner_email = i.custom_value_for(c).try(:value)\n    return if owner_email.blank?\n    lookup   = ActionView::LookupContext.new(File.dirname(__FILE__) + '/../app/views/')\n    context  = ActionView::Base.with_empty_template_cache.new(lookup, {}, nil)\n    renderer = ActionView::Renderer.new(lookup)\n    renderer.render(\n      context,\n      partial: \"issue_history\",\n      locals: {\n        email: owner_email\n      }\n    )\n  end\n  \nend\n"
  },
  {
    "path": "lib/helpdesk_mailer.rb",
    "content": "#\n# With Rails 3 mail is send with the mail method. Sadly redmine\n# uses this method-name too in their mailer. This is the reason\n# why we need our own Mailer class.\n#\nclass HelpdeskMailer < ActionMailer::Base\n  helper :application\n\n  include Redmine::I18n\n  include MacroExpander\n\n  # set the hostname for url_for helper\n  def self.default_url_options\n    { :host => Setting.host_name, :protocol => Setting.protocol }\n  end\n\n  # Sending email notifications to the supportclient\n  def email_to_supportclient(issue, params)\n    # issue, recipient, journal=nil, text='', copy_to=nil\n\n    recipient = params[:recipient]\n    journal = params[:journal]\n    text = params[:text]\n    carbon_copy = params[:carbon_copy]\n\n    redmine_headers 'Project' => issue.project.identifier,\n                    'Issue-Id' => issue.id,\n                    'Issue-Author' => issue.author.login\n    redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to\n    message_id issue\n    references issue\n\n    subject = \"[#{issue.project.name} - ##{issue.id}] #{issue.subject}\"\n    # Set 'from' email-address to 'helpdesk-sender-email' if available.\n    # Falls back to regular redmine behaviour if 'sender' is empty.\n    p = issue.project\n    s = CustomField.find_by_name('helpdesk-sender-email')\n    sender = p.custom_value_for(s).try(:value) if p.present? && s.present?\n    # If a custom field with text for the first reply is\n    # available then use this one instead of the regular\n    r = CustomField.find_by_name('helpdesk-first-reply')\n    f = CustomField.find_by_name('helpdesk-email-footer')\n    reply  = p.nil? || r.nil? ? '' : p.custom_value_for(r).try(:value)\n    footer = p.nil? || f.nil? ? '' : p.custom_value_for(f).try(:value)\n    # add carbon copy\n    ct = CustomField.find_by_name('copy-to')\n    if carbon_copy.nil?\n      carbon_copy = issue.custom_value_for(ct).try(:value)\n    end\n    # add any attachements\n    if journal.present? && text.present?\n      journal.details.each do |d|\n        if d.property == 'attachment'\n          a = Attachment.find(d.prop_key)\n          begin\n            attachments[a.filename] = File.binread(a.diskfile)\n          rescue\n            # ignore rescue\n          end\n        end\n      end\n    end\n    if @message_id_object\n      headers[:message_id] = \"<#{self.class.message_id_for(@message_id_object)}>\"\n    end\n    if @references_objects\n      headers[:references] = @references_objects.collect {|o| \"<#{self.class.references_for(o)}>\"}.join(' ')\n    end\n    # create mail object to deliver\n    mail = if text.present? || reply.present?\n      # sending out the journal note to the support client\n      # or the first reply message\n      t = text.present? ? \"#{text}\\n\\n#{footer}\" : reply\n      body = expand_macros(t, issue, journal)\n\n      # precess reply-separator\n      f = CustomField.find_by_name('helpdesk-reply-separator')\n      reply_separator = issue.project.custom_value_for(f).try(:value)\n      if !reply_separator.blank?\n        body = reply_separator + \"\\n\\n\" + body\n      end\n\n      mail(\n        :from     => sender.present? && sender || Setting.mail_from,\n        :reply_to => sender.present? && sender || Setting.mail_from,\n        :to       => recipient,\n        :subject  => subject,\n        :body     => body,\n        :date     => Time.zone.now,\n        :cc       => carbon_copy\n      )\n    else\n      # fallback to a regular notifications email with redmine view\n      @issue = issue\n      @journal = journal\n      @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue)\n      mail(\n        :from     => sender.present? && sender || Setting.mail_from,\n        :reply_to => sender.present? && sender || Setting.mail_from,\n        :to       => recipient,\n        :subject  => subject,\n        :date     => Time.zone.now,\n        :template_path => 'mailer',\n        :template_name => 'issue_edit',\n        :cc            => carbon_copy\n      )\n    end\n    # return mail object to deliver it\n    return mail\n  end\n\n  private\n\n  # Appends a Redmine header field (name is prepended with 'X-Redmine-')\n  def redmine_headers(h)\n    h.each { |k,v| headers[\"X-Redmine-#{k}\"] = v.to_s }\n  end\n\n  def self.token_for(object, rand=true)\n    timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)\n    hash = [\n      \"redmine\",\n      \"#{object.class.name.demodulize.underscore}-#{object.id}\",\n      timestamp.strftime(\"%Y%m%d%H%M%S\")\n    ]\n    if rand\n      hash << Redmine::Utils.random_hex(8)\n    end\n    host = Setting.mail_from.to_s.strip.gsub(%r{^.*@|>}, '')\n    host = \"#{::Socket.gethostname}.redmine\" if host.empty?\n    \"#{hash.join('.')}@#{host}\"\n  end\n\n  # Returns a Message-Id for the given object\n  def self.message_id_for(object)\n    token_for(object, true)\n  end\n\n  # Returns a uniq token for a given object referenced by all notifications\n  # related to this object\n  def self.references_for(object)\n    token_for(object, false)\n  end\n\n  def message_id(object)\n    @message_id_object = object\n  end\n\n  def references(object)\n    @references_objects ||= []\n    @references_objects << object\n  end\nend\n"
  },
  {
    "path": "lib/macro_expander.rb",
    "content": "module MacroExpander\n  def expand_macros(string, issue, journal)\n    e = Expander.new(string, issue, journal)\n    e.expand\n  end\n\n  class Expander\n    include Redmine::I18n\n\n    def initialize(string, issue, journal)\n      @string = string\n      @issue = issue\n      @journal = journal\n    end\n\n    def expand\n      unless @issue.nil?\n        expand_issue\n        expand_project\n      end\n      expand_user unless @journal.nil?\n      expand_base\n\n      @string\n    end\n\n    private\n\n    def expand_issue\n      @string.gsub!(\"##issue-id##\", @issue.id.to_s)\n      @string.gsub!(\"##issue-subject##\", @issue.subject)\n      @string.gsub!(\"##issue-tracker##\", @issue.tracker.name)\n      @string.gsub!(\"##issue-status##\", @issue.status.name)\n    end\n\n    def expand_project\n      p = @issue.project\n      @string.gsub!(\"##project-name##\", p.name)\n    end\n\n    def expand_user\n      u = @journal.user\n      @string.gsub!(\"##user-name##\", u.name)\n      @string.gsub!(\"##user-firstname##\", u.firstname)\n      @string.gsub!(\"##user-lastname##\", u.lastname)\n      @string.gsub!(\"##user-mail##\", u.mail)\n      @string.gsub!(\"##user-login##\", u.login)\n      expand_user_cf(u)\n    end\n\n    def expand_user_cf(user)\n      CustomField.where(\n        \"type = 'UserCustomField'\").each do |user_cf|\n        cf_name = user_cf.name.downcase.gsub(' ', '-')\n        user_cf_cv = user.custom_value_for(user_cf).try(:value)\n        @string.gsub!(\"##user-cf-#{cf_name}##\", user_cf_cv) unless user_cf_cv.nil?\n      end\n    end\n\n    def expand_base\n      @string.gsub!(\"##time-now##\", I18n.l(Time.zone.now))\n    end\n  end\nend\n"
  },
  {
    "path": "lib/redmine_helpdesk/journal_patch.rb",
    "content": "module RedmineHelpdesk\n  module JournalPatch\n    def self.included(base) # :nodoc:\n      base.send(:include, InstanceMethods)\n      \n      base.class_eval do\n        alias_method :send_notification_without_helpdesk, :send_notification\n        alias_method :send_notification, :send_notification_with_helpdesk\n      end\n    end\n\n    module InstanceMethods\n      # Overrides the send_notification method which\n      # is only called on journal updates\n      def send_notification_with_helpdesk\n        if notify? && (Setting.notified_events.include?('issue_updated') ||\n            (Setting.notified_events.include?('issue_note_added') && notes.present?) ||\n            (Setting.notified_events.include?('issue_status_updated') && new_status.present?) ||\n            (Setting.notified_events.include?('issue_assigned_to_updated') && detail_for_attribute('assigned_to_id').present?) ||\n            (Setting.notified_events.include?('issue_priority_updated') && new_value_for('priority_id').present?)\n          )\n          Mailer.deliver_issue_edit(self)\n        end\n        # do not send on private-notes\n        if private_notes == true && send_to_owner == true \n          self.send_to_owner = false\n          self.save( validate: false )\n        end\n        # sending email notifications to the supportclient\n        # only if the send_to_owner checkbox was checked\n        if send_to_owner == true && notes.length != 0\n          issue = self.journalized.reload\n          owner_email = issue.custom_value_for( CustomField.find_by_name('owner-email') ).value\n          HelpdeskMailer.email_to_supportclient(\n            issue, {\n              recipient: owner_email,\n              journal:   self,\n              text:      notes\n            }\n          ).deliver unless owner_email.blank?\n        end\n      end\n      \n    end # module InstanceMethods\n  end # module JournalPatch\nend # module RedmineHelpdesk\n\n# Add module to Journal class\nJournal.send(:include, ::RedmineHelpdesk::JournalPatch)\n"
  },
  {
    "path": "lib/redmine_helpdesk/mail_handler_patch.rb",
    "content": "module RedmineHelpdesk\n  module MailHandlerPatch\n    def self.included(base) # :nodoc:\n      base.send(:include, InstanceMethods)\n\n      base.class_eval do\n        alias_method :dispatch_to_default_without_helpdesk, :dispatch_to_default\n        alias_method :dispatch_to_default, :dispatch_to_default_with_helpdesk\n        # needed for reopening a closed issue\n        alias_method :receive_issue_reply_without_helpdesk, :receive_issue_reply\n        alias_method :receive_issue_reply, :receive_issue_reply_with_helpdesk\n      end\n    end\n\n    module InstanceMethods\n      private\n      # Overrides the dispatch_to_default method to\n      # set the owner-email of a new issue created by\n      # an email request\n      def dispatch_to_default_with_helpdesk\n        issue = receive_issue\n        issue.reload # prevent ActiveRecord::StaleObjectError\n        roles = if issue.author.class == AnonymousUser\n          Role.where(builtin: issue.author.id)\n        else\n          issue.author.roles_for_project(issue.project)\n        end\n        # add owner-email only if the author has assigned some role with\n        # permission treat_user_as_supportclient enabled\n        if issue.author.type.eql?(\"AnonymousUser\") || roles.any? {|role| role.allowed_to?(:treat_user_as_supportclient) }\n          sender_email = @email.from.first\n          \n          # any cc handling needed?\n          custom_value = custom_field_value(issue.project,'cc-handling')\n          if (!@email.cc.nil?) && (custom_value.value == '1')\n            carbon_copy = @email[:cc].formatted.join(', ')\n            custom_value = custom_field_value(issue,'copy-to')\n            custom_value.value = carbon_copy\n            custom_value.save( validate: false ) # skip validation!\n          else\n            carbon_copy = nil\n          end\n          \n          issue.description = email_details + issue.description\n          issue.save( validate: false ) # skip validation!\n          \n          custom_value = custom_field_value(issue,'owner-email')\n          if custom_value.value.to_s.strip.empty?\n            custom_value.value = sender_email\n            custom_value.save( validate: false ) # skip validation!\n          else\n            # Email owner field was already set by some preprocess hooks.\n            # So now we need to send message to another recepient.\n            sender_email = custom_value.value.to_s.strip\n          end\n          \n          # regular email sending to known users is done\n          # on the first issue.save. So we need to send\n          # the notification email to the supportclient\n          # on our own.\n          HelpdeskMailer.email_to_supportclient(\n            issue, {\n              recipient:   sender_email,\n              carbon_copy: carbon_copy\n            }\n          ).deliver\n        end\n        after_dispatch_to_default_hook issue\n        return issue\n      end\n\n      # let other plugins the chance to override this\n      # method to hook into dispatch_to_default\n      def after_dispatch_to_default_hook(issue)\n      end\n\n      # Fix an issue with email.has_attachments?\n      def add_attachments(obj)\n         if !email.attachments.nil? && email.attachments.size > 0\n           email.attachments.each do |attachment|\n             obj.attachments << Attachment.create(\n               container:    obj,\n               file:         attachment.decoded,\n               filename:     attachment.filename,\n               author:       user,\n               content_type: attachment.mime_type\n             )\n          end\n        end\n      end\n\n      # Overrides the receive_issue_reply method\n      def receive_issue_reply_with_helpdesk(issue_id, from_journal=nil)\n        issue = Issue.find_by_id(issue_id)\n        return unless issue\n\n        # reopening a closed issues by email\n        custom_value = custom_field_value(issue.project,'reopen-issues-with')\n        if issue.closed? && custom_value.present? && custom_value.value.present?\n          status_id = IssueStatus.where(\"name = ?\", custom_value.value).try(:first).try(:id)\n          unless status_id.nil?\n            issue.status_id = status_id\n            issue.save\n          end\n        end\n\n        # call original method\n        receive_issue_reply_without_helpdesk(issue_id, from_journal)\n\n        # store email-details before each note\n        last_journal = Journal.find(issue.last_journal_id)\n        last_journal.notes = email_details + last_journal.notes\n        last_journal.save\n\n        return last_journal\n      end\n      \n      def custom_field_value(issue,name)\n        custom_field = CustomField.find_by_name(name)\n        CustomValue.where(\n          \"customized_id = ? AND custom_field_id = ?\", issue.id, custom_field.id\n        ).first\n      end\n\n      def email_details\n        details =  \"From: \" + @email[:from].formatted.first + \"\\n\"\n        details << \"To:   \" + @email[:to].formatted.join(', ') + \"\\n\" if !@email.to.nil?\n        details << \"Cc:   \" + @email[:cc].formatted.join(', ') + \"\\n\" if !@email.cc.nil?\n        details << \"Date: \" + @email[:date].to_s + \"\\n\"\n        \"<pre>\\n\" + Mail::Encodings.unquote_and_convert_to(details, 'utf-8') + \"</pre>\\n\\n\"\n      end\n\n    end # module InstanceMethods\n  end # module MailHandlerPatch\nend # module RedmineHelpdesk\n\n# Add module to MailHandler class\nMailHandler.send(:include, ::RedmineHelpdesk::MailHandlerPatch)\n"
  },
  {
    "path": "lib/redmine_helpdesk/mailer_patch.rb",
    "content": "module RedmineHelpdesk\n  module MailerPatch\n    def self.included(base) # :nodoc:\n      base.send(:include, InstanceMethods)\n      \n      base.class_eval do\n        alias_method :issue_edit_without_helpdesk, :issue_edit\n        alias_method :issue_edit, :issue_edit_with_helpdesk\n      end\n    end\n\n    module InstanceMethods\n      # Overrides the issue_edit method which is only\n      # be called on existing tickets. We will add the\n      # owner-email to the recipients only if no email-\n      # footer text is available.\n      def issue_edit_with_helpdesk(user, journal)\n        issue = journal.journalized\n        redmine_headers 'Project' => issue.project.identifier,\n                        'Issue-Id' => issue.id,\n                        'Issue-Author' => issue.author.login,\n                        'Issue-Tracker' => issue.tracker\n        redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to\n        message_id journal\n        references issue\n        @author = journal.user\n\n        # process reply-separator\n        f = CustomField.find_by_name('helpdesk-reply-separator')\n        reply_separator = issue.project.custom_value_for(f).try(:value)\n        if !reply_separator.blank? and !journal.notes.nil?\n          journal.notes = journal.notes.gsub(/#{reply_separator}.*/m, '')\n          journal.save(:validate => false)\n        end\n\n        # add owner-email to the recipients\n        alternative_user = nil\n        begin\n          if journal.send_to_owner == true\n            f = CustomField.find_by_name('helpdesk-email-footer')\n            p = issue.project\n            owner_email = issue.custom_value_for( CustomField.find_by_name('owner-email') ).value\n            if !owner_email.blank? && !f.nil? && !p.nil? && p.custom_value_for(f).try(:value).blank?\n              alternative_user = owner_email\n            end\n          end\n        rescue Exception => e\n          Rails.logger.error \"Error while adding owner-email to recipients of email notification: \\\"#{e.message}\\\".\"\n        end\n\n        # any cc handling needed?\n        cc_users = nil\n        begin\n          # any cc handling needed?\n          if alternative_user.present?\n            custom_field = CustomField.find_by_name('cc-handling')\n            custom_value = CustomValue.where(\n              \"customized_id = ? AND custom_field_id = ?\", issue.project.id, custom_field.id\n            ).first\n            cc_users = custom_value.value.split(',').map(&:strip) if custom_value.value.present?\n          end\n        rescue Exception => e\n          Rails.logger.error \"Error while adding cc-users to recipients of email notification: \\\"#{e.message}\\\".\"\n        end\n\n        s = \"[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] \"\n        s += \"(#{issue.status.name}) \" if journal.new_value_for('status_id') && Setting.show_status_changes_in_mail_subject?\n        s += issue.subject\n        u = (alternative_user.present? ? alternative_user : user)\n        @issue = issue\n        @user = u\n        @journal = journal\n        @journal_details = journal.visible_details\n        @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => \"change-#{journal.id}\")\n        mail(\n          :to => u,\n          :cc => cc_users,\n          :subject => s\n        )\n      end\n      \n    end # module InstanceMethods\n  end # module MailerPatch\nend # module RedmineHelpdesk\n\n# Add module to Mailer class\nMailer.send(:include, ::RedmineHelpdesk::MailerPatch)\n"
  },
  {
    "path": "lib/tasks/local-db.rake",
    "content": "namespace :helpdesk do\n  namespace :localdb do\n    db_label = 'helpdesk-db'\n\n    def get_env ()\n      db_name = 'redmine'\n      db_host = 'localhost'\n      db_user = 'root'\n\n      db_adapter = ENV['DATABASE_ADAPTER']\n      case db_adapter\n      when \"mysql\"\n        env = \"-e MYSQL_DATABASE=#{db_name} \"\\\n              \"-e MYSQL_ALLOW_EMPTY_PASSWORD=yes \"\n      when \"postgresql\"\n        env = \"-e POSTGRES_DB=#{db_name} \"\\\n              \"-e POSTGRES_USER=#{db_user} \"\\\n      when \"postgresql_ext\"\n        env = \"-e POSTGRES_DB=#{db_name} \"\\\n              \"-e POSTGRES_USER=#{db_user}\"\n      else\n        raise StandardError.new \"Cannot start local db\"\n      end\n      env\n    end\n\n    def get_port ()\n      db_adapter = ENV['DATABASE_ADAPTER']\n      case db_adapter\n      when \"mysql\"\n        port = 3306\n      when \"postgresql\"\n        port = 5432\n      when \"postgresql_ext\"\n        port = 5432\n      else\n        raise StandardError.new \"Cannot start local db\"\n      end\n      port\n    end\n\n    def get_image ()\n      db_adapter = ENV['DATABASE_ADAPTER']\n      case db_adapter\n      when \"mysql\"\n        image = \"mysql\"\n      when \"postgresql\"\n        image = \"postgres\"\n      when \"postgresql_ext\"\n        image = \"postgres\"\n      else\n        raise StandardError.new \"Cannot start local db\"\n      end\n      image\n    end\n\n    task :start => :stop do\n      env = get_env()\n      port = get_port()\n      image = get_image()\n      cmd = \"docker run -d --name #{db_label} \"\\\n              \"--net=host \"\\\n              \"#{env} \"\\\n              \"#{image}\"\n      puts cmd\n      system(cmd)\n    end\n\n    task :stop do\n      system(\"docker stop #{db_label}\")\n      system(\"docker rm #{db_label}\")\n    end\n  end\nend\n"
  },
  {
    "path": "lib/tasks/plugin_ci.rake",
    "content": "namespace :helpdesk do\n  plugin_root = File.expand_path('../../../', __FILE__)\n  coverage_dir = \"#{plugin_root}/coverage\"\n\n  desc 'Runs :ci target from plugin scope in test/app'\n  task :ext_ci do\n    cd('test/app') do\n      sh('bundle exec rake helpdesk:ci')\n    end\n  end\n\n  desc 'Prepared and configures DB in Docker container'\n  task :prepare_local => ['helpdesk:localdb:start',\n                          'helpdesk:redmine:configure_db'] do\n    Rake::Task['helpdesk:install'].invoke()\n  end\n\n  desc 'Runs bundle install from plugin scop in test/app'\n  task :install do\n    cd('test/app') do\n      sh('bundle install --without production development rmagick')\n    end\n  end\n\n  desc 'Runs migrate from plugin scope in test/app'\n  task :migrate do\n    cd('test/app') do\n      sh('bundle exec rake generate_secret_token')\n      sh('bundle exec rake db:migrate')\n    end\n  end\n\n  desc 'Prepares and runs the test suite.'\n  task :ci => ['redmine:plugins:migrate',\n               'helpdesk:test']\n\n  desc 'Runs Redmine plugin tests with single CodeClimate TestReporter invocation.'\n  task :test => [ 'helpdesk:test:clear_coverage_data',\n                  'helpdesk:test:run' ]\n\n  namespace :test do\n    task :run do\n      Rake::Task['redmine:plugins:test:units'].invoke\n      Rake::Task['redmine:plugins:test:functionals'].invoke\n\n      # require \"simplecov\"\n      # require \"codeclimate-test-reporter\"\n      # SimpleCov.coverage_dir \"plugins/coverage\"\n      # CodeClimate::TestReporter.configure do |config|\n      #   config.git_dir = \"plugins/#{ENV['GITHUB_PROJECT']}\"\n      # end\n      # CodeClimate::TestReporter::Formatter.new.format(SimpleCov.result)\n    end\n\n    task :clear_coverage_data do\n      rm_rf coverage_dir\n    end\n  end\nend\n"
  },
  {
    "path": "lib/tasks/redmine.rake",
    "content": "require 'fileutils'\n\nnamespace :helpdesk do\n  namespace :redmine do\n    plugin_root = File.expand_path('../../../', __FILE__)\n    redmine_path = \"#{plugin_root}/test/app\"\n    tmp_dir = \"#{plugin_root}/tmp\"\n\n    redmine_source_url = \"http://www.redmine.org/releases\"\n    redmine_version = ENV['REDMINE_VERSION'] || \"3.2.0\"\n    redmine_name = \"redmine-#{redmine_version}\"\n    redmine_package = \"#{redmine_name}.tar.gz\"\n    redmine_url = \"#{redmine_source_url}/#{redmine_package}\"\n\n    version = redmine_version.split(\".\")\n    major = version[0]\n    minor = version[1]\n    patch = version[2]\n\n    task :install => [ :remove,\n                       :print_env,\n                       :download_tarball,\n                       :extract_tarball,\n                       :configure_db,\n                       :link_plugin,\n                       :print_result ]\n\n    task :print_env do\n      if ENV['DATABASE_ADAPTER'].nil?\n        raise StandardError.new \"Database adapter not defined\"\n      end\n\n      puts \"\"\n      puts \"######################\"\n      puts \"REDMINE INSTALLATION SCRIPT\"\n      puts \"\"\n      puts \"REDMINE_VERSION  : #{redmine_version}\"\n      puts \"REDMINE_URL      : #{redmine_url}\"\n      puts \"DATABASE ADAPTER : #{ENV['DATABASE_ADAPTER']}\"\n      puts \"\"\n    end\n\n    task :remove do\n      rm_rf redmine_path\n    end\n\n    task :download_tarball do\n      mkdir_p tmp_dir\n      Dir.chdir(tmp_dir) do\n        puts \"Downloading tarball\"\n        if !system(\"wget #{redmine_url}\")\n          raise StandardError.new \"download failed\"\n        end\n      end\n    end\n\n    task :extract_tarball do\n      Dir.chdir(tmp_dir) do\n        puts \"Extracting tarball\"\n        if !system(\"tar xf #{redmine_package}\")\n          raise StandardError.new \"download failed\"\n        end\n        mv \"#{redmine_name}\", \"#{redmine_path}\", :force => true\n        rm_rf tmp_dir\n      end\n    end\n\n    task :configure_db do\n      puts \"Configuring database\"\n      db_adapter = ENV['DATABASE_ADAPTER']\n      case db_adapter\n      when \"mysql\"\n        a = \"mysql\"\n      when \"postgresql\"\n        a = \"postgres\"\n      when \"postgresql_ext\"\n        a = \"postgres_ext\"\n      when \"sqlite\"\n        a = \"sqlite\"\n      else\n        raise StandardError.new \"Error copying config files\"\n      end\n      cp \"#{plugin_root}/test/confs/database_#{a}.yml\",\n        \"#{redmine_path}/config/database.yml\", :verbose => true\n    end\n\n    task :print_result do\n      puts \"Dummy Redmine dir listing\"\n      Dir[\"#{redmine_path}/*\"].each do |f|\n        puts f.sub(\"#{redmine_path}\", \"\")\n      end\n      puts \"\"\n      puts \"Dummy Redmine plugin dir listing\"\n      Dir[\"#{redmine_path}/plugins/*\"].each do |f|\n        puts f.sub(\"#{redmine_path}/plugins\", \"\")\n      end\n      puts \"\"\n    end\n\n    task :link_plugin do\n      plugin_dir = \"#{redmine_path}/plugins/redmine_helpdesk\"\n      ln_sf plugin_root, plugin_dir\n    end\n  end\nend\n"
  },
  {
    "path": "test/confs/database_mysql.yml",
    "content": "## MySQL configuration example\n## Data come from environment variables so the test suite can be run\n## on Travis or Jenkins (see https://github.com/codevise/jenkins-mysql-job-databases-plugin)\nproduction:\n  adapter: mysql2\n  database: <%= ENV['MYSQL_DATABASE'] || 'redmine' %>\n  host: <%= ENV['MYSQL_HOST'] || '127.0.0.1' %>\n  port: <%= ENV['MYSQL_PORT'] || '3306' %>\n  username: <%= ENV['MYSQL_USER'] || 'root' %>\n  password: <%= ENV['MYSQL_PASSWORD'] %>\n  encoding: utf8\n\ndevelopment:\n  adapter: mysql2\n  database: <%= ENV['MYSQL_DATABASE'] || 'redmine' %>\n  host: <%= ENV['MYSQL_HOST'] || '127.0.0.1' %>\n  port: <%= ENV['MYSQL_PORT'] || '3306' %>\n  username: <%= ENV['MYSQL_USER'] || 'root' %>\n  password: <%= ENV['MYSQL_PASSWORD'] %>\n  encoding: utf8\n\ntest:\n  adapter: mysql2\n  database: <%= ENV['MYSQL_DATABASE'] || 'redmine' %>\n  host: <%= ENV['MYSQL_HOST'] || '127.0.0.1' %>\n  port: <%= ENV['MYSQL_PORT'] || '3306' %>\n  username: <%= ENV['MYSQL_USER'] || 'root' %>\n  password: <%= ENV['MYSQL_PASSWORD'] %>\n  encoding: utf8\n"
  },
  {
    "path": "test/confs/database_postgres.yml",
    "content": "## PostgreSQL configuration example\n## Data come from environment variables so the test suite can be run\n## on Travis or Jenkins (see https://github.com/lmlima/jenkins-postgresql-job-databases-plugin)\nproduction:\n  adapter: postgresql\n  database: <%= ENV['POSTGRES_DATABASE'] || 'redmine' %>\n  username: <%= ENV['POSTGRES_USER'] || 'root' %>\n  encoding: utf8\n\ndevelopment:\n  adapter: postgresql\n  database: <%= ENV['POSTGRES_DATABASE'] || 'redmine' %>\n  username: <%= ENV['POSTGRES_USER'] || 'root' %>\n  encoding: utf8\n\ntest:\n  adapter: postgresql\n  database: <%= ENV['POSTGRES_DATABASE'] || 'redmine' %>\n  username: <%= ENV['POSTGRES_USER'] || 'root' %>\n  encoding: utf8\n"
  },
  {
    "path": "test/confs/database_postgres_ext.yml",
    "content": "## PostgreSQL configuration example\n## Data come from environment variables so the test suite can be run\n## on Travis or Jenkins (see https://github.com/lmlima/jenkins-postgresql-job-databases-plugin)\nproduction:\n  adapter: postgresql\n  database: <%= ENV['POSTGRES_DATABASE'] || 'redmine' %>\n  host: <%= ENV['POSTGRES_HOST'] || 'localhost' %>\n  username: <%= ENV['POSTGRES_USER'] || 'root' %>\n  encoding: utf8\n\ndevelopment:\n  adapter: postgresql\n  database: <%= ENV['POSTGRES_DATABASE'] || 'redmine' %>\n  host: <%= ENV['POSTGRES_HOST'] || 'localhost' %>\n  username: <%= ENV['POSTGRES_USER'] || 'root' %>\n  encoding: utf8\n\ntest:\n  adapter: postgresql\n  database: <%= ENV['POSTGRES_DATABASE'] || 'redmine' %>\n  host: <%= ENV['POSTGRES_HOST'] || 'localhost' %>\n  username: <%= ENV['POSTGRES_USER'] || 'root' %>\n  encoding: utf8\n"
  },
  {
    "path": "test/confs/database_sqlite.yml",
    "content": "## SQLite3 configuration example\nproduction:\n  adapter: sqlite3\n  database: db/redmine.sqlite3\ndevelopment:\n  adapter: sqlite3\n  database: db/redmine.dev.sqlite3\ntest:\n  adapter: sqlite3\n  database: db/redmine.test.sqlite3\n"
  },
  {
    "path": "test/fixtures/2.6/attachments.yml",
    "content": "---\nattachments_001:\n  created_on: 2006-07-19 21:07:27 +02:00\n  container_type: Issue\n  container_id: 1\n  downloads: 0\n  disk_filename: 060719210727_source.rb\n  disk_directory: \"2006/07\"\n  digest: b91e08d0cf966d5c6ff411bd8c4cc3a2\n  id: 1\n  filesize: 153\n  filename: source.rb\n  author_id: 1\n  description: This is a Ruby source file\n  content_type: application/x-ruby\n"
  },
  {
    "path": "test/fixtures/2.6/custom_fields.yml",
    "content": "---\ncustom_fields_001:\n  name: owner-email\n  regexp: \"\"\n  type: IssueCustomField\n  possible_values: \"\"\n  id: 1\n  is_required: false\n  field_format: string\n  default_value: \"\"\n  editable: true\n  visible: true\n  position: 1\ncustom_fields_002:\n  name: helpdesk-first-reply\n  min_length: 1\n  regexp: \"\"\n  visible: false\n  type: ProjectCustomField\n  max_length: 100\n  possible_values: \"\"\n  id: 2\n  is_required: false\n  field_format: text\n  default_value: \"\"\n  editable: true\n  position: 1\ncustom_fields_003:\n  name: helpdesk-email-footer\n  min_length: 1\n  regexp: \"\"\n  visible: false\n  type: ProjectCustomField\n  max_length: 100\n  possible_values: \"\"\n  id: 3\n  is_required: false\n  field_format: text\n  default_value: \"\"\n  editable: true\n  position: 1\ncustom_fields_004:\n  name: helpdesk-sender-email\n  regexp: \"\"\n  type: ProjectCustomField\n  possible_values: \"\"\n  id: 4\n  is_required: false\n  field_format: string\n  default_value: false\n  editable: true\n  visible: true\n  position: 1\ncustom_fields_005:\n  name: helpdesk-send-to-owner-default\n  regexp: \"\"\n  type: ProjectCustomField\n  possible_values: \"\"\n  id: 5\n  is_required: false\n  field_format: bool\n  default_value: false\n  editable: true\n  visible: false\n  position: 1\ncustom_fields_006:\n  name: helpdesk-subject\n  min_length: 1\n  regexp: \"\"\n  visible: false\n  type: ProjectCustomField\n  max_length: 100\n  possible_values: \"\"\n  id: 6\n  is_required: false\n  field_format: text\n  default_value: \"\"\n  editable: true\n  position: 1\ncustom_fields_007:\n  name: helpdesk-send-first-reply\n  visible: false\n  type: ProjectCustomField\n  id: 7\n  is_required: false\n  field_format: boolean\n  default_value: true\n  editable: true\n  position: 1\ncustom_fields_008:\n  name: title\n  regexp: \"\"\n  is_for_all: false\n  type: UserCustomField\n  possible_values: \"\"\n  id: 8\n  is_required: false\n  field_format: string\n  default_value: \"\"\n  editable: true\n  position: 1\ncustom_fields_009:\n  name: motto\n  regexp: \"\"\n  is_for_all: false\n  type: UserCustomField\n  possible_values: \"\"\n  id: 9\n  is_required: false\n  field_format: string\n  default_value: \"\"\n  editable: true\n  position: 2\ncustom_fields_010:\n  name: copy-to\n  regexp: \"\"\n  type: IssueCustomField\n  possible_values: \"\"\n  id: 10\n  is_required: false\n  field_format: string\n  default_value: \"\"\n  editable: true\n  visible: true\n  position: 1\ncustom_fields_011:\n  name: cc-handling\n  visible: false\n  type: ProjectCustomField\n  id: 11\n  is_required: false\n  field_format: bool\n  default_value: false\n  editable: true\n  position: 1\n"
  },
  {
    "path": "test/fixtures/2.6/custom_fields_projects.yml",
    "content": "---\ncustom_fields_projects_001:\n  custom_field_id: 1\n  project_id: 1\ncustom_fields_projects_002:\n  custom_field_id: 1\n  project_id: 2\ncustom_fields_projects_003:\n  custom_field_id: 10\n  project_id: 1\ncustom_fields_projects_004:\n  custom_field_id: 10\n  project_id: 2\ncustom_fields_projects_005:\n  custom_field_id: 1\n  project_id: 4\ncustom_fields_projects_006:\n  custom_field_id: 10\n  project_id: 4\n"
  },
  {
    "path": "test/fixtures/2.6/custom_fields_trackers.yml",
    "content": "---\ncustom_fields_trackers_001:\n  custom_field_id: 1\n  tracker_id: 1\ncustom_fields_trackers_002:\n  custom_field_id: 1\n  tracker_id: 2\ncustom_fields_trackers_003:\n  custom_field_id: 1\n  tracker_id: 3\ncustom_fields_trackers_004:\n  custom_field_id: 1\n  tracker_id: 4\ncustom_fields_trackers_005:\n  custom_field_id: 10\n  tracker_id: 1\ncustom_fields_trackers_006:\n  custom_field_id: 10\n  tracker_id: 2\ncustom_fields_trackers_007:\n  custom_field_id: 10\n  tracker_id: 3\ncustom_fields_trackers_008:\n  custom_field_id: 10\n  tracker_id: 4\n"
  },
  {
    "path": "test/fixtures/2.6/custom_values.yml",
    "content": "---\ncustom_values_001:\n  customized_type: Project\n  custom_field_id: 2\n  customized_id: 1\n  id: 1\n  value: \"first reply\"\ncustom_values_002:\n  customized_type: Project\n  custom_field_id: 3\n  customized_id: 1\n  id: 2\n  value: \"email footer\"\ncustom_values_003:\n  customized_type: Project\n  custom_field_id: 4\n  customized_id: 1\n  id: 3\n  value: reply@example.com\ncustom_values_004:\n  customized_type: Project\n  custom_field_id: 5\n  customized_id: 1\n  id: 4\n  value: 0\ncustom_values_005:\n  customized_type: Project\n  custom_field_id: 11\n  customized_id: 1\n  id: 5\n  value: 1\ncustom_values_006:\n  customized_type: Project\n  custom_field_id: 2\n  customized_id: 2\n  id: 6\n  value: first reply\ncustom_values_007:\n  customized_type: Project\n  custom_field_id: 3\n  customized_id: 2\n  id: 7\n  value: email footer\ncustom_values_008:\n  customized_type: Project\n  custom_field_id: 4\n  customized_id: 2\n  id: 8\n  value: reply@example.com\ncustom_values_009:\n  customized_type: Project\n  custom_field_id: 5\n  customized_id: 2\n  id: 9\n  value: 0\ncustom_values_010:\n  customized_type: Project\n  custom_field_id: 11\n  customized_id: 2\n  id: 10\n  value: 1\ncustom_values_011:\n  customized_type: Issue\n  custom_field_id: 1\n  customized_id: 1\n  id: 11\n  value: owner@example.com\ncustom_values_012:\n  customized_type: Project\n  custom_field_id: 2\n  customized_id: 4\n  id: 12\n  value: first reply\ncustom_values_013:\n  customized_type: Project\n  custom_field_id: 3\n  customized_id: 4\n  id: 13\n  value: email footer\ncustom_values_014:\n  customized_type: Project\n  custom_field_id: 4\n  customized_id: 4\n  id: 14\n  value: reply@example.com\ncustom_values_015:\n  customized_type: Project\n  custom_field_id: 5\n  customized_id: 4\n  id: 15\n  value: 0\ncustom_values_016:\n  customized_type: Project\n  custom_field_id: 11\n  customized_id: 4\n  id: 16\n  value: 0\n"
  },
  {
    "path": "test/fixtures/2.6/enabled_modules.yml",
    "content": "---\nenabled_modules_001:\n  name: issue_tracking\n  project_id: 1\n  id: 1\nenabled_modules_002:\n  name: time_tracking\n  project_id: 1\n  id: 2\nenabled_modules_003:\n  name: files\n  project_id: 1\n  id: 3\nenabled_modules_004:\n  name: issue_tracking\n  project_id: 2\n  id: 4\nenabled_modules_005:\n  name: time_tracking\n  project_id: 2\n  id: 5\nenabled_modules_006:\n  name: files\n  project_id: 2\n  id: 6\nenabled_modules_007:\n  name: issue_tracking\n  project_id: 4\n  id: 7\nenabled_modules_008:\n  name: time_tracking\n  project_id: 4\n  id: 8\nenabled_modules_009:\n  name: files\n  project_id: 4\n  id: 9\n"
  },
  {
    "path": "test/fixtures/2.6/enumerations.yml",
    "content": "---\nenumerations_001:\n  name: Low\n  id: 1\n  type: IssuePriority\n  active: true\n  position: 1\n  position_name: lowest\nenumerations_002:\n  name: Normal\n  id: 2\n  type: IssuePriority\n  is_default: true\n  active: true\n  position: 2\n  position_name: default\nenumerations_003:\n  name: High\n  id: 3\n  type: IssuePriority\n  active: true\n  position: 3\n  position_name: high3\nenumerations_004:\n  name: Urgent\n  id: 4\n  type: IssuePriority\n  active: true\n  position: 4\n  position_name: high2\nenumerations_005:\n  name: Immediate\n  id: 5\n  type: IssuePriority\n  active: true\n  position: 5\n  position_name: highest\n"
  },
  {
    "path": "test/fixtures/2.6/issue_statuses.yml",
    "content": "--- \nissue_statuses_001: \n  id: 1\n  name: New\n  is_default: true\n  is_closed: false\n  position: 1\nissue_statuses_002: \n  id: 2\n  name: Assigned\n  is_default: false\n  is_closed: false\n  position: 2\nissue_statuses_003: \n  id: 3\n  name: Resolved\n  is_default: false\n  is_closed: false\n  position: 3\nissue_statuses_004: \n  name: Feedback\n  id: 4\n  is_default: false\n  is_closed: false\n  position: 4\nissue_statuses_005: \n  id: 5\n  name: Closed\n  is_default: false\n  is_closed: true\n  position: 5\nissue_statuses_006: \n  id: 6\n  name: Rejected\n  is_default: false\n  is_closed: true\n  position: 6\n"
  },
  {
    "path": "test/fixtures/2.6/issues.yml",
    "content": "---\nissues_001:\n  created_on: 2015-03-05 21:41:21 +02:00\n  project_id: 1\n  updated_on: 2015-03-05 22:05:50 +02:00\n  priority_id: 2\n  subject: Can't print recipes\n  id: 1\n  fixed_version_id:\n  category_id: 1\n  description: Unable to print recipes\n  tracker_id: 1\n  assigned_to_id: 1\n  author_id: 1\n  status_id: 1\n  start_date:\n  due_date:\n  root_id: 1\n  lft: 1\n  rgt: 2\n  lock_version: 3\nissues_002:\n  created_on: 2006-07-19 21:04:21 +02:00\n  project_id: 2\n  updated_on: 2006-07-19 21:09:50 +02:00\n  priority_id: 2\n  subject: Add ingredients categories\n  id: 2\n  fixed_version_id:\n  category_id:\n  description: Ingredients of the recipe should be classified by categories\n  tracker_id: 2\n  assigned_to_id:\n  author_id: 1\n  status_id: 2\n  start_date:\n  due_date:\n  root_id: 2\n  lft: 1\n  rgt: 2\n  lock_version: 3\n"
  },
  {
    "path": "test/fixtures/2.6/journal_details.yml",
    "content": "---\njournal_details_001:\n  old_value:\n  property: attachment\n  id: 1\n  value: 060719210727_source.rb\n  prop_key: 1\n  journal_id: 3\n"
  },
  {
    "path": "test/fixtures/2.6/journals.yml",
    "content": "---\njournals_001:\n  created_on: <%= 2.days.ago.to_date.to_s(:db) %>\n  notes: \"Journal notes\"\n  id: 1\n  journalized_type: Issue\n  user_id: 1\n  journalized_id: 1\njournals_002:\n  created_on: <%= 1.days.ago.to_date.to_s(:db) %>\n  notes: \"Some notes.\"\n  id: 2\n  journalized_type: Issue\n  user_id: 1\n  journalized_id: 1\njournals_003:\n  created_on: <%= 1.days.ago.to_date.to_s(:db) %>\n  notes: \"Some notes with an attachment.\"\n  id: 3\n  journalized_type: Issue\n  user_id: 1\n  journalized_id: 1\njournals_004:\n  id: 4\n  created_on: <%= 1.days.ago.to_date.to_s(:db) %>\n  notes: \"A comment on an issue.\"\n  user_id: 1\n  journalized_type: Issue\n  journalized_id: 2\n"
  },
  {
    "path": "test/fixtures/2.6/member_roles.yml",
    "content": "---\nmember_roles_001:\n  id: 1\n  role_id: 1\n  member_id: 1\nmember_roles_002:\n  id: 2\n  role_id: 1\n  member_id: 2\nmember_roles_003:\n  id: 3\n  role_id: 1\n  member_id: 3\nmember_roles_004:\n  id: 4\n  role_id: 6\n  member_id: 4\n"
  },
  {
    "path": "test/fixtures/2.6/members.yml",
    "content": "---\nmembers_001:\n  created_on: 2006-07-19 19:35:33 +02:00\n  project_id: 1\n  id: 1\n  user_id: 1\n  mail_notification: true\nmembers_002:\n  created_on: 2006-07-19 19:35:36 +02:00\n  project_id: 2\n  id: 2\n  user_id: 1\n  mail_notification: true\nmembers_003:\n  created_on: 2006-07-19 19:35:36 +02:00\n  project_id: 3\n  id: 3\n  user_id: 1\n  mail_notification: true\nmembers_004:\n  created_on: 2006-07-19 19:35:36 +02:00\n  project_id: 2\n  id: 4\n  user_id: 2\n  mail_notification: false\nmembers_005:\n  created_on: 2006-07-19 19:35:36 +02:00\n  project_id: 4\n  id: 5\n  user_id: 1\n  mail_notification: true\n"
  },
  {
    "path": "test/fixtures/2.6/projects.yml",
    "content": "---\nprojects_001:\n  created_on: 2015-03-05 19:13:59 +02:00\n  name: Helpdesk Project 1\n  updated_on: 2015-03-05 22:53:01 +02:00\n  id: 1\n  description: First helpdesk project\n  homepage: \"\"\n  is_public: true\n  identifier: helpdesk_project_1\n  parent_id:\n  lft: 1\n  rgt: 2\nprojects_002:\n  created_on: 2015-03-05 19:14:19 +02:00\n  name: Helpdesk Project 2\n  updated_on: 2015-03-05 19:14:19 +02:00\n  id: 2\n  description: Second helpdesk project\n  homepage: \"\"\n  is_public: false\n  identifier: helpdesk_project_2\n  parent_id:\n  lft: 3\n  rgt: 4\nprojects_003:\n  created_on: 2015-03-05 19:15:21 +02:00\n  name: Irrelevant Project\n  updated_on: 2015-03-05 19:18:12 +02:00\n  id: 3\n  description: Project that has no helpdesk features\n  homepage: \"\"\n  is_public: true\n  identifier: irrelevant_project\n  parent_id:\n  lft: 5\n  rgt: 6\nprojects_004:\n  created_on: 2015-03-05 19:14:19 +02:00\n  name: Helpdesk Project 4\n  updated_on: 2015-03-05 19:14:19 +02:00\n  id: 4\n  description: Disabled copy-to helpdesk project\n  homepage: \"\"\n  is_public: true\n  identifier: helpdesk_project_4\n  parent_id:\n  lft: 6\n  rgt: 7\n\n"
  },
  {
    "path": "test/fixtures/2.6/projects_trackers.yml",
    "content": "---\nprojects_trackers_001:\n  project_id: 1\n  tracker_id: 1\nprojects_trackers_002:\n  project_id: 1\n  tracker_id: 2\nprojects_trackers_003:\n  project_id: 1\n  tracker_id: 3\nprojects_trackers_004:\n  project_id: 2\n  tracker_id: 1\nprojects_trackers_005:\n  project_id: 2\n  tracker_id: 2\nprojects_trackers_006:\n  project_id: 2\n  tracker_id: 3\nprojects_trackers_007:\n  project_id: 3\n  tracker_id: 1\nprojects_trackers_008:\n  project_id: 3\n  tracker_id: 2\nprojects_trackers_009:\n  project_id: 3\n  tracker_id: 3\nprojects_trackers_010:\n  project_id: 4\n  tracker_id: 1\nprojects_trackers_011:\n  project_id: 4\n  tracker_id: 2\nprojects_trackers_012:\n  project_id: 4\n  tracker_id: 3\n"
  },
  {
    "path": "test/fixtures/2.6/roles.yml",
    "content": "---\nroles_001:\n  name: Manager\n  id: 1\n  builtin: 0\n  issues_visibility: all\n  permissions: |\n    ---\n    - :add_project\n    - :edit_project\n    - :close_project\n    - :select_project_modules\n    - :manage_members\n    - :manage_versions\n    - :manage_categories\n    - :view_issues\n    - :add_issues\n    - :edit_issues\n    - :manage_issue_relations\n    - :manage_subtasks\n    - :add_issue_notes\n    - :move_issues\n    - :delete_issues\n    - :view_issue_watchers\n    - :add_issue_watchers\n    - :set_issues_private\n    - :set_notes_private\n    - :view_private_notes\n    - :delete_issue_watchers\n    - :manage_public_queries\n    - :save_queries\n    - :view_gantt\n    - :view_calendar\n    - :log_time\n    - :view_time_entries\n    - :edit_time_entries\n    - :delete_time_entries\n    - :manage_news\n    - :comment_news\n    - :view_documents\n    - :add_documents\n    - :edit_documents\n    - :delete_documents\n    - :view_wiki_pages\n    - :export_wiki_pages\n    - :view_wiki_edits\n    - :edit_wiki_pages\n    - :delete_wiki_pages_attachments\n    - :protect_wiki_pages\n    - :delete_wiki_pages\n    - :rename_wiki_pages\n    - :add_messages\n    - :edit_messages\n    - :delete_messages\n    - :manage_boards\n    - :view_files\n    - :manage_files\n    - :browse_repository\n    - :manage_repository\n    - :view_changesets\n    - :manage_related_issues\n    - :manage_project_activities\n\n  position: 1\nroles_002:\n  name: Developer\n  id: 2\n  builtin: 0\n  issues_visibility: default\n  permissions: |\n    ---\n    - :edit_project\n    - :manage_members\n    - :manage_versions\n    - :manage_categories\n    - :view_issues\n    - :add_issues\n    - :edit_issues\n    - :manage_issue_relations\n    - :manage_subtasks\n    - :add_issue_notes\n    - :move_issues\n    - :delete_issues\n    - :view_issue_watchers\n    - :save_queries\n    - :view_gantt\n    - :view_calendar\n    - :log_time\n    - :view_time_entries\n    - :edit_own_time_entries\n    - :manage_news\n    - :comment_news\n    - :view_documents\n    - :add_documents\n    - :edit_documents\n    - :delete_documents\n    - :view_wiki_pages\n    - :view_wiki_edits\n    - :edit_wiki_pages\n    - :protect_wiki_pages\n    - :delete_wiki_pages\n    - :add_messages\n    - :edit_own_messages\n    - :delete_own_messages\n    - :manage_boards\n    - :view_files\n    - :manage_files\n    - :browse_repository\n    - :view_changesets\n\n  position: 2\nroles_003:\n  name: Reporter\n  id: 3\n  builtin: 0\n  issues_visibility: default\n  permissions: |\n    ---\n    - :edit_project\n    - :manage_members\n    - :manage_versions\n    - :manage_categories\n    - :view_issues\n    - :add_issues\n    - :edit_issues\n    - :manage_issue_relations\n    - :add_issue_notes\n    - :move_issues\n    - :view_issue_watchers\n    - :save_queries\n    - :view_gantt\n    - :view_calendar\n    - :log_time\n    - :view_time_entries\n    - :manage_news\n    - :comment_news\n    - :view_documents\n    - :add_documents\n    - :edit_documents\n    - :delete_documents\n    - :view_wiki_pages\n    - :view_wiki_edits\n    - :edit_wiki_pages\n    - :delete_wiki_pages\n    - :add_messages\n    - :manage_boards\n    - :view_files\n    - :manage_files\n    - :browse_repository\n    - :view_changesets\n\n  position: 3\nroles_004:\n  name: Non member\n  id: 4\n  builtin: 1\n  issues_visibility: default\n  permissions: |\n    ---\n    - :view_issues\n    - :add_issues\n    - :edit_issues\n    - :manage_issue_relations\n    - :add_issue_notes\n    - :save_queries\n    - :view_gantt\n    - :view_calendar\n    - :log_time\n    - :view_time_entries\n    - :comment_news\n    - :view_documents\n    - :view_wiki_pages\n    - :view_wiki_edits\n    - :edit_wiki_pages\n    - :add_messages\n    - :view_files\n    - :manage_files\n    - :browse_repository\n    - :view_changesets\n\n  position: 4\nroles_005:\n  name: Anonymous\n  id: 5\n  builtin: 2\n  issues_visibility: default\n  permissions: |\n    ---\n    - :treat_user_as_supportclient\n    - :view_issues\n    - :add_issue_notes\n    - :view_gantt\n    - :view_calendar\n    - :view_time_entries\n    - :view_documents\n    - :view_wiki_pages\n    - :view_wiki_edits\n    - :view_files\n    - :browse_repository\n    - :view_changesets\n\n  position: 5\nroles_006:\n  name: SupportClient\n  id: 6\n  builtin: 0\n  issues_visibility: default\n  permissions: |\n    ---\n    - :treat_user_as_supportclient\n    - :add_issues\n    - :add_issue_notes\n  position: 6\n"
  },
  {
    "path": "test/fixtures/2.6/trackers.yml",
    "content": "--- \ntrackers_001: \n  name: Bug\n  id: 1\n  is_in_chlog: true\n  position: 1\ntrackers_002: \n  name: Feature request\n  id: 2\n  is_in_chlog: true\n  position: 2\ntrackers_003: \n  name: Support request\n  id: 3\n  is_in_chlog: false\n  position: 3\n"
  },
  {
    "path": "test/fixtures/2.6/users.yml",
    "content": "---\nusers_001:\n  created_on: 2015-03-05 19:34:07 +02:00\n  status: 1\n  last_login_on:\n  language: en\n  # password = foo\n  salt: 3126f764c3c5ac61cbfc103f25f934cf\n  hashed_password: 9e4dd7eeb172c12a0691a6d9d3a269f7e9fe671b\n  updated_on: 2015-03-05 19:34:07 +02:00\n  admin: true\n  mail: rhill@somenet.foo\n  lastname: Hill\n  firstname: Robert\n  id: 1\n  auth_source_id:\n  mail_notification: all\n  login: normaluser\n  type: User\nusers_002:\n  created_on: 2015-03-05 19:33:19 +02:00\n  status: 1\n  last_login_on:\n  language: en\n  # password = foo\n  salt: 7599f9963ec07b5a3b55b354407120c0\n  hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed\n  updated_on: 2015-03-05 19:33:19 +02:00\n  admin: false\n  mail: dlopper@somenet.foo\n  lastname: Lopper\n  firstname: Dave\n  id: 2\n  auth_source_id:\n  mail_notification: all\n  login: supportclient\n  type: User\nusers_003:\n  id: 3\n  created_on: 2006-07-19 19:33:19 +02:00\n  status: 0\n  last_login_on:\n  language: ''\n  hashed_password: 1\n  updated_on: 2006-07-19 19:33:19 +02:00\n  admin: false\n  lastname: Anonymous\n  firstname: ''\n  auth_source_id:\n  mail_notification: only_my_events\n  login: ''\n  type: AnonymousUser\n"
  },
  {
    "path": "test/fixtures/3.0/attachments.yml",
    "content": "---\nattachments_001:\n  created_on: 2006-07-19 21:07:27 +02:00\n  container_type: Issue\n  container_id: 1\n  downloads: 0\n  disk_filename: 060719210727_source.rb\n  disk_directory: \"2006/07\"\n  digest: b91e08d0cf966d5c6ff411bd8c4cc3a2\n  id: 1\n  filesize: 153\n  filename: source.rb\n  author_id: 1\n  description: This is a Ruby source file\n  content_type: application/x-ruby\n"
  },
  {
    "path": "test/fixtures/3.0/custom_fields.yml",
    "content": "---\ncustom_fields_001:\n  name: owner-email\n  regexp: \"\"\n  type: IssueCustomField\n  possible_values: \"\"\n  id: 1\n  is_required: false\n  field_format: string\n  default_value: \"\"\n  editable: true\n  visible: true\n  position: 1\ncustom_fields_002:\n  name: helpdesk-first-reply\n  min_length: 1\n  regexp: \"\"\n  visible: false\n  type: ProjectCustomField\n  max_length: 100\n  possible_values: \"\"\n  id: 2\n  is_required: false\n  field_format: text\n  default_value: \"\"\n  editable: true\n  position: 1\ncustom_fields_003:\n  name: helpdesk-email-footer\n  min_length: 1\n  regexp: \"\"\n  visible: false\n  type: ProjectCustomField\n  max_length: 100\n  possible_values: \"\"\n  id: 3\n  is_required: false\n  field_format: text\n  default_value: \"\"\n  editable: true\n  position: 1\ncustom_fields_004:\n  name: helpdesk-sender-email\n  regexp: \"\"\n  type: ProjectCustomField\n  possible_values: \"\"\n  id: 4\n  is_required: false\n  field_format: string\n  default_value: false\n  editable: true\n  visible: true\n  position: 1\ncustom_fields_005:\n  name: helpdesk-send-to-owner-default\n  regexp: \"\"\n  type: ProjectCustomField\n  possible_values: \"\"\n  id: 5\n  is_required: false\n  field_format: bool\n  default_value: false\n  editable: true\n  visible: false\n  position: 1\ncustom_fields_006:\n  name: helpdesk-subject\n  min_length: 1\n  regexp: \"\"\n  visible: false\n  type: ProjectCustomField\n  max_length: 100\n  possible_values: \"\"\n  id: 6\n  is_required: false\n  field_format: text\n  default_value: \"\"\n  editable: true\n  position: 1\ncustom_fields_007:\n  name: helpdesk-send-first-reply\n  visible: false\n  type: ProjectCustomField\n  id: 7\n  is_required: false\n  field_format: boolean\n  default_value: true\n  editable: true\n  position: 1\ncustom_fields_008:\n  name: title\n  regexp: \"\"\n  is_for_all: false\n  type: UserCustomField\n  possible_values: \"\"\n  id: 8\n  is_required: false\n  field_format: string\n  default_value: \"\"\n  editable: true\n  position: 1\ncustom_fields_009:\n  name: motto\n  regexp: \"\"\n  is_for_all: false\n  type: UserCustomField\n  possible_values: \"\"\n  id: 9\n  is_required: false\n  field_format: string\n  default_value: \"\"\n  editable: true\n  position: 2\ncustom_fields_010:\n  name: copy-to\n  regexp: \"\"\n  type: IssueCustomField\n  possible_values: \"\"\n  id: 10\n  is_required: false\n  field_format: string\n  default_value: \"\"\n  editable: true\n  visible: true\n  position: 1\ncustom_fields_011:\n  name: cc-handling\n  visible: false\n  type: ProjectCustomField\n  id: 11\n  is_required: false\n  field_format: bool\n  default_value: false\n  editable: true\n  position: 1\n"
  },
  {
    "path": "test/fixtures/3.0/custom_fields_projects.yml",
    "content": "---\ncustom_fields_projects_001:\n  custom_field_id: 1\n  project_id: 1\ncustom_fields_projects_002:\n  custom_field_id: 1\n  project_id: 2\ncustom_fields_projects_003:\n  custom_field_id: 10\n  project_id: 1\ncustom_fields_projects_004:\n  custom_field_id: 10\n  project_id: 2\ncustom_fields_projects_005:\n  custom_field_id: 1\n  project_id: 4\ncustom_fields_projects_006:\n  custom_field_id: 10\n  project_id: 4\n"
  },
  {
    "path": "test/fixtures/3.0/custom_fields_trackers.yml",
    "content": "---\ncustom_fields_trackers_001:\n  custom_field_id: 1\n  tracker_id: 1\ncustom_fields_trackers_002:\n  custom_field_id: 1\n  tracker_id: 2\ncustom_fields_trackers_003:\n  custom_field_id: 1\n  tracker_id: 3\ncustom_fields_trackers_004:\n  custom_field_id: 1\n  tracker_id: 4\ncustom_fields_trackers_005:\n  custom_field_id: 10\n  tracker_id: 1\ncustom_fields_trackers_006:\n  custom_field_id: 10\n  tracker_id: 2\ncustom_fields_trackers_007:\n  custom_field_id: 10\n  tracker_id: 3\ncustom_fields_trackers_008:\n  custom_field_id: 10\n  tracker_id: 4\n"
  },
  {
    "path": "test/fixtures/3.0/custom_values.yml",
    "content": "---\ncustom_values_001:\n  customized_type: Project\n  custom_field_id: 2\n  customized_id: 1\n  id: 1\n  value: \"first reply\"\ncustom_values_002:\n  customized_type: Project\n  custom_field_id: 3\n  customized_id: 1\n  id: 2\n  value: \"email footer\"\ncustom_values_003:\n  customized_type: Project\n  custom_field_id: 4\n  customized_id: 1\n  id: 3\n  value: reply@example.com\ncustom_values_004:\n  customized_type: Project\n  custom_field_id: 5\n  customized_id: 1\n  id: 4\n  value: 0\ncustom_values_005:\n  customized_type: Project\n  custom_field_id: 11\n  customized_id: 1\n  id: 5\n  value: 1\ncustom_values_006:\n  customized_type: Project\n  custom_field_id: 2\n  customized_id: 2\n  id: 6\n  value: first reply\ncustom_values_007:\n  customized_type: Project\n  custom_field_id: 3\n  customized_id: 2\n  id: 7\n  value: email footer\ncustom_values_008:\n  customized_type: Project\n  custom_field_id: 4\n  customized_id: 2\n  id: 8\n  value: reply@example.com\ncustom_values_009:\n  customized_type: Project\n  custom_field_id: 5\n  customized_id: 2\n  id: 9\n  value: 0\ncustom_values_010:\n  customized_type: Project\n  custom_field_id: 11\n  customized_id: 2\n  id: 10\n  value: 1\ncustom_values_011:\n  customized_type: Issue\n  custom_field_id: 1\n  customized_id: 1\n  id: 11\n  value: owner@example.com\ncustom_values_012:\n  customized_type: Project\n  custom_field_id: 2\n  customized_id: 4\n  id: 12\n  value: first reply\ncustom_values_013:\n  customized_type: Project\n  custom_field_id: 3\n  customized_id: 4\n  id: 13\n  value: email footer\ncustom_values_014:\n  customized_type: Project\n  custom_field_id: 4\n  customized_id: 4\n  id: 14\n  value: reply@example.com\ncustom_values_015:\n  customized_type: Project\n  custom_field_id: 5\n  customized_id: 4\n  id: 15\n  value: 0\ncustom_values_016:\n  customized_type: Project\n  custom_field_id: 11\n  customized_id: 4\n  id: 16\n  value: 0\n"
  },
  {
    "path": "test/fixtures/3.0/email_addresses.yml",
    "content": "---\nemail_address_001:\n  id: 1\n  user_id: 1\n  address: rhill@somenet.foo\n  is_default: true\n  created_on: 2006-07-19 19:34:07 +02:00\n  updated_on: 2006-07-19 19:34:07 +02:00\nemail_address_002:\n  id: 2\n  user_id: 2\n  address: dlopper@somenet.foo\n  is_default: true\n  created_on: 2006-07-19 19:34:07 +02:00\n  updated_on: 2006-07-19 19:34:07 +02:00\n"
  },
  {
    "path": "test/fixtures/3.0/enabled_modules.yml",
    "content": "---\nenabled_modules_001:\n  name: issue_tracking\n  project_id: 1\n  id: 1\nenabled_modules_002:\n  name: time_tracking\n  project_id: 1\n  id: 2\nenabled_modules_003:\n  name: files\n  project_id: 1\n  id: 3\nenabled_modules_004:\n  name: issue_tracking\n  project_id: 2\n  id: 4\nenabled_modules_005:\n  name: time_tracking\n  project_id: 2\n  id: 5\nenabled_modules_006:\n  name: files\n  project_id: 2\n  id: 6\nenabled_modules_007:\n  name: issue_tracking\n  project_id: 4\n  id: 7\nenabled_modules_008:\n  name: time_tracking\n  project_id: 4\n  id: 8\nenabled_modules_009:\n  name: files\n  project_id: 4\n  id: 9\n"
  },
  {
    "path": "test/fixtures/3.0/enumerations.yml",
    "content": "---\nenumerations_001:\n  name: Low\n  id: 1\n  type: IssuePriority\n  active: true\n  position: 1\n  position_name: lowest\nenumerations_002:\n  name: Normal\n  id: 2\n  type: IssuePriority\n  is_default: true\n  active: true\n  position: 2\n  position_name: default\nenumerations_003:\n  name: High\n  id: 3\n  type: IssuePriority\n  active: true\n  position: 3\n  position_name: high3\nenumerations_004:\n  name: Urgent\n  id: 4\n  type: IssuePriority\n  active: true\n  position: 4\n  position_name: high2\nenumerations_005:\n  name: Immediate\n  id: 5\n  type: IssuePriority\n  active: true\n  position: 5\n  position_name: highest\n"
  },
  {
    "path": "test/fixtures/3.0/issue_statuses.yml",
    "content": "---\nissue_statuses_001:\n  id: 1\n  name: New\n  is_closed: false\n  position: 1\nissue_statuses_002:\n  id: 2\n  name: Assigned\n  is_closed: false\n  position: 2\nissue_statuses_003:\n  id: 3\n  name: Resolved\n  is_closed: false\n  position: 3\nissue_statuses_004:\n  name: Feedback\n  id: 4\n  is_closed: false\n  position: 4\nissue_statuses_005:\n  id: 5\n  name: Closed\n  is_closed: true\n  position: 5\nissue_statuses_006:\n  id: 6\n  name: Rejected\n  is_closed: true\n  position: 6\n"
  },
  {
    "path": "test/fixtures/3.0/issues.yml",
    "content": "---\nissues_001:\n  created_on: 2015-03-05 21:41:21 +02:00\n  project_id: 1\n  updated_on: 2015-03-05 22:05:50 +02:00\n  priority_id: 2\n  subject: Can't print recipes\n  id: 1\n  fixed_version_id:\n  category_id: 1\n  description: Unable to print recipes\n  tracker_id: 1\n  assigned_to_id: 1\n  author_id: 1\n  status_id: 1\n  start_date:\n  due_date:\n  root_id: 1\n  lft: 1\n  rgt: 2\n  lock_version: 3\nissues_002:\n  created_on: 2006-07-19 21:04:21 +02:00\n  project_id: 2\n  updated_on: 2006-07-19 21:09:50 +02:00\n  priority_id: 2\n  subject: Add ingredients categories\n  id: 2\n  fixed_version_id:\n  category_id:\n  description: Ingredients of the recipe should be classified by categories\n  tracker_id: 2\n  assigned_to_id:\n  author_id: 1\n  status_id: 2\n  start_date:\n  due_date:\n  root_id: 2\n  lft: 1\n  rgt: 2\n  lock_version: 3\n"
  },
  {
    "path": "test/fixtures/3.0/journal_details.yml",
    "content": "---\njournal_details_001:\n  old_value:\n  property: attachment\n  id: 1\n  value: 060719210727_source.rb\n  prop_key: 1\n  journal_id: 3\n"
  },
  {
    "path": "test/fixtures/3.0/journals.yml",
    "content": "---\njournals_001:\n  created_on: <%= 2.days.ago.to_date.to_s(:db) %>\n  notes: \"Journal notes\"\n  id: 1\n  journalized_type: Issue\n  user_id: 1\n  journalized_id: 1\njournals_002:\n  created_on: <%= 1.days.ago.to_date.to_s(:db) %>\n  notes: \"Some notes.\"\n  id: 2\n  journalized_type: Issue\n  user_id: 1\n  journalized_id: 1\njournals_003:\n  created_on: <%= 1.days.ago.to_date.to_s(:db) %>\n  notes: \"Some notes with an attachment.\"\n  id: 3\n  journalized_type: Issue\n  user_id: 1\n  journalized_id: 1\njournals_004:\n  id: 4\n  created_on: <%= 1.days.ago.to_date.to_s(:db) %>\n  notes: \"A comment on an issue.\"\n  user_id: 1\n  journalized_type: Issue\n  journalized_id: 2\n"
  },
  {
    "path": "test/fixtures/3.0/member_roles.yml",
    "content": "---\nmember_roles_001:\n  id: 1\n  role_id: 1\n  member_id: 1\nmember_roles_002:\n  id: 2\n  role_id: 1\n  member_id: 2\nmember_roles_003:\n  id: 3\n  role_id: 1\n  member_id: 3\nmember_roles_004:\n  id: 4\n  role_id: 6\n  member_id: 4\n"
  },
  {
    "path": "test/fixtures/3.0/members.yml",
    "content": "---\nmembers_001:\n  created_on: 2006-07-19 19:35:33 +02:00\n  project_id: 1\n  id: 1\n  user_id: 1\n  mail_notification: true\nmembers_002:\n  created_on: 2006-07-19 19:35:36 +02:00\n  project_id: 2\n  id: 2\n  user_id: 1\n  mail_notification: true\nmembers_003:\n  created_on: 2006-07-19 19:35:36 +02:00\n  project_id: 3\n  id: 3\n  user_id: 1\n  mail_notification: true\nmembers_004:\n  created_on: 2006-07-19 19:35:36 +02:00\n  project_id: 2\n  id: 4\n  user_id: 2\n  mail_notification: false\nmembers_005:\n  created_on: 2006-07-19 19:35:36 +02:00\n  project_id: 4\n  id: 5\n  user_id: 1\n  mail_notification: true\n"
  },
  {
    "path": "test/fixtures/3.0/projects.yml",
    "content": "---\nprojects_001:\n  created_on: 2015-03-05 19:13:59 +02:00\n  name: Helpdesk Project 1\n  updated_on: 2015-03-05 22:53:01 +02:00\n  id: 1\n  description: First helpdesk project\n  homepage: \"\"\n  is_public: true\n  identifier: helpdesk_project_1\n  parent_id:\n  lft: 1\n  rgt: 2\nprojects_002:\n  created_on: 2015-03-05 19:14:19 +02:00\n  name: Helpdesk Project 2\n  updated_on: 2015-03-05 19:14:19 +02:00\n  id: 2\n  description: Second helpdesk project\n  homepage: \"\"\n  is_public: false\n  identifier: helpdesk_project_2\n  parent_id:\n  lft: 3\n  rgt: 4\nprojects_003:\n  created_on: 2015-03-05 19:15:21 +02:00\n  name: Irrelevant Project\n  updated_on: 2015-03-05 19:18:12 +02:00\n  id: 3\n  description: Project that has no helpdesk features\n  homepage: \"\"\n  is_public: true\n  identifier: irrelevant_project\n  parent_id:\n  lft: 5\n  rgt: 6\nprojects_004:\n  created_on: 2015-03-05 19:14:19 +02:00\n  name: Helpdesk Project 4\n  updated_on: 2015-03-05 19:14:19 +02:00\n  id: 4\n  description: Disabled copy-to helpdesk project\n  homepage: \"\"\n  is_public: true\n  identifier: helpdesk_project_4\n  parent_id:\n  lft: 6\n  rgt: 7\n\n"
  },
  {
    "path": "test/fixtures/3.0/projects_trackers.yml",
    "content": "---\nprojects_trackers_001:\n  project_id: 1\n  tracker_id: 1\nprojects_trackers_002:\n  project_id: 1\n  tracker_id: 2\nprojects_trackers_003:\n  project_id: 1\n  tracker_id: 3\nprojects_trackers_004:\n  project_id: 2\n  tracker_id: 1\nprojects_trackers_005:\n  project_id: 2\n  tracker_id: 2\nprojects_trackers_006:\n  project_id: 2\n  tracker_id: 3\nprojects_trackers_007:\n  project_id: 3\n  tracker_id: 1\nprojects_trackers_008:\n  project_id: 3\n  tracker_id: 2\nprojects_trackers_009:\n  project_id: 3\n  tracker_id: 3\nprojects_trackers_010:\n  project_id: 4\n  tracker_id: 1\nprojects_trackers_011:\n  project_id: 4\n  tracker_id: 2\nprojects_trackers_012:\n  project_id: 4\n  tracker_id: 3\n"
  },
  {
    "path": "test/fixtures/3.0/roles.yml",
    "content": "---\nroles_001:\n  name: Manager\n  id: 1\n  builtin: 0\n  issues_visibility: all\n  permissions: |\n    ---\n    - :add_project\n    - :edit_project\n    - :close_project\n    - :select_project_modules\n    - :manage_members\n    - :manage_versions\n    - :manage_categories\n    - :view_issues\n    - :add_issues\n    - :edit_issues\n    - :manage_issue_relations\n    - :manage_subtasks\n    - :add_issue_notes\n    - :move_issues\n    - :delete_issues\n    - :view_issue_watchers\n    - :add_issue_watchers\n    - :set_issues_private\n    - :set_notes_private\n    - :view_private_notes\n    - :delete_issue_watchers\n    - :manage_public_queries\n    - :save_queries\n    - :view_gantt\n    - :view_calendar\n    - :log_time\n    - :view_time_entries\n    - :edit_time_entries\n    - :delete_time_entries\n    - :manage_news\n    - :comment_news\n    - :view_documents\n    - :add_documents\n    - :edit_documents\n    - :delete_documents\n    - :view_wiki_pages\n    - :export_wiki_pages\n    - :view_wiki_edits\n    - :edit_wiki_pages\n    - :delete_wiki_pages_attachments\n    - :protect_wiki_pages\n    - :delete_wiki_pages\n    - :rename_wiki_pages\n    - :add_messages\n    - :edit_messages\n    - :delete_messages\n    - :manage_boards\n    - :view_files\n    - :manage_files\n    - :browse_repository\n    - :manage_repository\n    - :view_changesets\n    - :manage_related_issues\n    - :manage_project_activities\n\n  position: 1\nroles_002:\n  name: Developer\n  id: 2\n  builtin: 0\n  issues_visibility: default\n  permissions: |\n    ---\n    - :edit_project\n    - :manage_members\n    - :manage_versions\n    - :manage_categories\n    - :view_issues\n    - :add_issues\n    - :edit_issues\n    - :manage_issue_relations\n    - :manage_subtasks\n    - :add_issue_notes\n    - :move_issues\n    - :delete_issues\n    - :view_issue_watchers\n    - :save_queries\n    - :view_gantt\n    - :view_calendar\n    - :log_time\n    - :view_time_entries\n    - :edit_own_time_entries\n    - :manage_news\n    - :comment_news\n    - :view_documents\n    - :add_documents\n    - :edit_documents\n    - :delete_documents\n    - :view_wiki_pages\n    - :view_wiki_edits\n    - :edit_wiki_pages\n    - :protect_wiki_pages\n    - :delete_wiki_pages\n    - :add_messages\n    - :edit_own_messages\n    - :delete_own_messages\n    - :manage_boards\n    - :view_files\n    - :manage_files\n    - :browse_repository\n    - :view_changesets\n\n  position: 2\nroles_003:\n  name: Reporter\n  id: 3\n  builtin: 0\n  issues_visibility: default\n  permissions: |\n    ---\n    - :edit_project\n    - :manage_members\n    - :manage_versions\n    - :manage_categories\n    - :view_issues\n    - :add_issues\n    - :edit_issues\n    - :manage_issue_relations\n    - :add_issue_notes\n    - :move_issues\n    - :view_issue_watchers\n    - :save_queries\n    - :view_gantt\n    - :view_calendar\n    - :log_time\n    - :view_time_entries\n    - :manage_news\n    - :comment_news\n    - :view_documents\n    - :add_documents\n    - :edit_documents\n    - :delete_documents\n    - :view_wiki_pages\n    - :view_wiki_edits\n    - :edit_wiki_pages\n    - :delete_wiki_pages\n    - :add_messages\n    - :manage_boards\n    - :view_files\n    - :manage_files\n    - :browse_repository\n    - :view_changesets\n\n  position: 3\nroles_004:\n  name: Non member\n  id: 4\n  builtin: 1\n  issues_visibility: default\n  permissions: |\n    ---\n    - :view_issues\n    - :add_issues\n    - :edit_issues\n    - :manage_issue_relations\n    - :add_issue_notes\n    - :save_queries\n    - :view_gantt\n    - :view_calendar\n    - :log_time\n    - :view_time_entries\n    - :comment_news\n    - :view_documents\n    - :view_wiki_pages\n    - :view_wiki_edits\n    - :edit_wiki_pages\n    - :add_messages\n    - :view_files\n    - :manage_files\n    - :browse_repository\n    - :view_changesets\n\n  position: 4\nroles_005:\n  name: Anonymous\n  id: 5\n  builtin: 2\n  issues_visibility: default\n  permissions: |\n    ---\n    - :treat_user_as_supportclient\n    - :view_issues\n    - :add_issue_notes\n    - :view_gantt\n    - :view_calendar\n    - :view_time_entries\n    - :view_documents\n    - :view_wiki_pages\n    - :view_wiki_edits\n    - :view_files\n    - :browse_repository\n    - :view_changesets\n\n  position: 5\nroles_006:\n  name: SupportClient\n  id: 6\n  builtin: 0\n  issues_visibility: default\n  permissions: |\n    ---\n    - :treat_user_as_supportclient\n    - :add_issues\n    - :add_issue_notes\n  position: 6\n"
  },
  {
    "path": "test/fixtures/3.0/trackers.yml",
    "content": "---\ntrackers_001:\n  name: Bug\n  id: 1\n  is_in_chlog: true\n  position: 1\n  default_status_id: 1\ntrackers_002:\n  name: Feature request\n  id: 2\n  is_in_chlog: true\n  position: 2\n  default_status_id: 1\ntrackers_003:\n  name: Support request\n  id: 3\n  is_in_chlog: false\n  position: 3\n  default_status_id: 1\n"
  },
  {
    "path": "test/fixtures/3.0/users.yml",
    "content": "---\nusers_001:\n  created_on: 2015-03-05 19:34:07 +02:00\n  status: 1\n  last_login_on:\n  language: en\n  # password = foo\n  salt: 3126f764c3c5ac61cbfc103f25f934cf\n  hashed_password: 9e4dd7eeb172c12a0691a6d9d3a269f7e9fe671b\n  updated_on: 2015-03-05 19:34:07 +02:00\n  admin: true\n  lastname: Hill\n  firstname: Robert\n  id: 1\n  auth_source_id:\n  mail_notification: all\n  login: normaluser\n  type: User\nusers_002:\n  created_on: 2015-03-05 19:33:19 +02:00\n  status: 1\n  last_login_on:\n  language: en\n  # password = foo\n  salt: 7599f9963ec07b5a3b55b354407120c0\n  hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed\n  updated_on: 2015-03-05 19:33:19 +02:00\n  admin: false\n  lastname: Lopper\n  firstname: Dave\n  id: 2\n  auth_source_id:\n  mail_notification: all\n  login: supportclient\n  type: User\nusers_003:\n  id: 3\n  created_on: 2006-07-19 19:33:19 +02:00\n  status: 0\n  last_login_on:\n  language: ''\n  hashed_password: 1\n  updated_on: 2006-07-19 19:33:19 +02:00\n  admin: false\n  lastname: Anonymous\n  firstname: ''\n  auth_source_id:\n  mail_notification: only_my_events\n  login: ''\n  type: AnonymousUser\n"
  },
  {
    "path": "test/fixtures/files/2006/07/060719210727_source.rb",
    "content": "# The Greeter class\nclass Greeter\n  def initialize(name)\n    @name = name.capitalize\n  end\n\n  def salute\n    puts \"Hello #{@name}!\" \n  end\nend\n"
  },
  {
    "path": "test/fixtures/mail_handler/ticket_by_unknown_user.eml",
    "content": "Return-Path: <john.doe@somenet.foo>\nReceived: from osiris ([127.0.0.1])\n\tby OSIRIS\n\twith hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200\nMessage-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>\nFrom: \"John Doe\" <john.doe@somenet.foo>\nTo: <redmine@somenet.foo>\nSubject: Ticket by unknown user\nDate: Sun, 22 Jun 2008 12:28:07 +0200\nMIME-Version: 1.0\nContent-Type: text/plain;\n\tformat=flowed;\n\tcharset=\"iso-8859-1\";\n\treply-type=original\nContent-Transfer-Encoding: 7bit\n\nThis is a ticket submitted by an unknown user.\n\n"
  },
  {
    "path": "test/fixtures/mail_handler/ticket_by_unknown_user_with_cc.eml",
    "content": "Return-Path: <john.doe@somenet.foo>\nReceived: from osiris ([127.0.0.1])\n\tby OSIRIS\n\twith hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200\nMessage-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>\nFrom: \"John Doe\" <john.doe@somenet.foo>\nTo: <redmine@somenet.foo>\nCc: \"Ada\" <ada@test.lindsaar.net>, My Group: <mikel@test.lindsaar.net>, Bob <bob@test.lindsaar.net>;\nSubject: Ticket by unknown user\nDate: Sun, 22 Jun 2008 12:28:07 +0200\nMIME-Version: 1.0\nContent-Type: text/plain;\n\tformat=flowed;\n\tcharset=\"iso-8859-1\";\n\treply-type=original\nContent-Transfer-Encoding: 7bit\n\nThis is a ticket submitted by an unknown user with cc.\n\n"
  },
  {
    "path": "test/fixtures/mail_handler/ticket_by_user_1.eml",
    "content": "Return-Path: <rhill@somenet.foo>\nReceived: from osiris ([127.0.0.1])\n\tby OSIRIS\n\twith hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200\nMessage-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>\nFrom: \"John Doe\" <rhill@somenet.foo>\nTo: <redmine@somenet.foo>\nSubject: Ticket by unknown user\nDate: Sun, 22 Jun 2008 12:28:07 +0200\nMIME-Version: 1.0\nContent-Type: text/plain;\n\tformat=flowed;\n\tcharset=\"iso-8859-1\";\n\treply-type=original\nContent-Transfer-Encoding: 7bit\n\nThis is a ticket submitted by an unknown user.\n\n"
  },
  {
    "path": "test/fixtures/mail_handler/ticket_by_user_2.eml",
    "content": "Return-Path: <dlopper@somenet.foo>\nReceived: from osiris ([127.0.0.1])\n\tby OSIRIS\n\twith hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200\nMessage-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>\nFrom: \"John Doe\" <dlopper@somenet.foo>\nTo: <redmine@somenet.foo>\nSubject: Ticket by unknown user\nDate: Sun, 22 Jun 2008 12:28:07 +0200\nMIME-Version: 1.0\nContent-Type: text/plain;\n\tformat=flowed;\n\tcharset=\"iso-8859-1\";\n\treply-type=original\nContent-Transfer-Encoding: 7bit\n\nThis is a ticket submitted by an unknown user.\n\n"
  },
  {
    "path": "test/fixtures/mail_handler/ticket_reply.eml",
    "content": "Return-Path: <jsmith@somenet.foo>\nReceived: from osiris ([127.0.0.1])\n\tby OSIRIS\n\twith hMailServer ; Sat, 21 Jun 2008 18:41:39 +0200\nMessage-ID: <006a01c8d3bd$ad9baec0$0a00a8c0@osiris>\nIn-Reply-To: <redmine.issue-2.20060719210421@osiris>\nFrom: \"John Smith\" <jsmith@somenet.foo>\nTo: <redmine@somenet.foo>\nReferences: <485d0ad366c88_d7014663a025f@osiris.tmail>\nSubject: Re: Add ingredients categories\nDate: Sat, 21 Jun 2008 18:41:39 +0200\nMIME-Version: 1.0\nContent-Type: multipart/alternative;\n\tboundary=\"----=_NextPart_000_0067_01C8D3CE.711F9CC0\"\nX-Priority: 3\nX-MSMail-Priority: Normal\nX-Mailer: Microsoft Outlook Express 6.00.2900.2869\nX-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869\n\nThis is a multi-part message in MIME format.\n\n------=_NextPart_000_0067_01C8D3CE.711F9CC0\nContent-Type: text/plain;\n\tcharset=\"utf-8\"\nContent-Transfer-Encoding: quoted-printable\n\nThis is reply\n------=_NextPart_000_0067_01C8D3CE.711F9CC0\nContent-Type: text/html;\n\tcharset=\"utf-8\"\nContent-Transfer-Encoding: quoted-printable\n\n=EF=BB=BF<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n<HTML><HEAD>\n<META http-equiv=3DContent-Type content=3D\"text/html; charset=3Dutf-8\">\n<STYLE>BODY {\n\tFONT-SIZE: 0.8em; COLOR: #484848; FONT-FAMILY: Verdana, sans-serif\n}\nBODY H1 {\n\tFONT-SIZE: 1.2em; MARGIN: 0px; FONT-FAMILY: \"Trebuchet MS\", Verdana, =\nsans-serif\n}\nA {\n\tCOLOR: #2a5685\n}\nA:link {\n\tCOLOR: #2a5685\n}\nA:visited {\n\tCOLOR: #2a5685\n}\nA:hover {\n\tCOLOR: #c61a1a\n}\nA:active {\n\tCOLOR: #c61a1a\n}\nHR {\n\tBORDER-RIGHT: 0px; BORDER-TOP: 0px; BACKGROUND: #ccc; BORDER-LEFT: 0px; =\nWIDTH: 100%; BORDER-BOTTOM: 0px; HEIGHT: 1px\n}\n.footer {\n\tFONT-SIZE: 0.8em; FONT-STYLE: italic\n}\n</STYLE>\n\n<META content=3D\"MSHTML 6.00.2900.2883\" name=3DGENERATOR></HEAD>\n<BODY bgColor=3D#ffffff>\n<DIV><SPAN class=3Dfooter><FONT face=3DArial color=3D#000000 =\nsize=3D2>This is=20\nreply</FONT></DIV></SPAN></BODY></HTML>\n\n------=_NextPart_000_0067_01C8D3CE.711F9CC0--\n\n"
  },
  {
    "path": "test/fixtures/mail_handler/ticket_with_attachment.eml",
    "content": "Return-Path: <jsmith@somenet.foo>\nReceived: from osiris ([127.0.0.1])\n\tby OSIRIS\n\twith hMailServer ; Sat, 21 Jun 2008 15:53:25 +0200\nMessage-ID: <002301c8d3a6$2cdf6950$0a00a8c0@osiris>\nFrom: \"John Smith\" <jsmith@somenet.foo>\nTo: <redmine@somenet.foo>\nSubject: Ticket created by email with attachment\nDate: Sat, 21 Jun 2008 15:53:25 +0200\nMIME-Version: 1.0\nContent-Type: multipart/mixed;\n\tboundary=\"----=_NextPart_000_001F_01C8D3B6.F05C5270\"\nX-Priority: 3\nX-MSMail-Priority: Normal\nX-Mailer: Microsoft Outlook Express 6.00.2900.2869\nX-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869\n\nThis is a multi-part message in MIME format.\n\n------=_NextPart_000_001F_01C8D3B6.F05C5270\nContent-Type: multipart/alternative;\n\tboundary=\"----=_NextPart_001_0020_01C8D3B6.F05C5270\"\n\n\n------=_NextPart_001_0020_01C8D3B6.F05C5270\nContent-Type: text/plain;\n\tcharset=\"iso-8859-1\"\nContent-Transfer-Encoding: quoted-printable\n\nThis is  a new ticket with attachments\n------=_NextPart_001_0020_01C8D3B6.F05C5270\nContent-Type: text/html;\n\tcharset=\"iso-8859-1\"\nContent-Transfer-Encoding: quoted-printable\n\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n<HTML><HEAD>\n<META http-equiv=3DContent-Type content=3D\"text/html; =\ncharset=3Diso-8859-1\">\n<META content=3D\"MSHTML 6.00.2900.2883\" name=3DGENERATOR>\n<STYLE></STYLE>\n</HEAD>\n<BODY bgColor=3D#ffffff>\n<DIV><FONT face=3DArial size=3D2>This is&nbsp; a new ticket with=20\nattachments</FONT></DIV></BODY></HTML>\n\n------=_NextPart_001_0020_01C8D3B6.F05C5270--\n\n------=_NextPart_000_001F_01C8D3B6.F05C5270\nContent-Type: image/jpeg;\n\tname=\"Paella.jpg\"\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment;\n\tfilename=\"Paella.jpg\"\n\n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\ncbis+/WpUqUcMZKdF44n/9k=\n\n------=_NextPart_000_001F_01C8D3B6.F05C5270--\n\n"
  },
  {
    "path": "test/fixtures/mail_handler/ticket_with_attributes.eml",
    "content": "Return-Path: <jsmith@somenet.foo>\nReceived: from osiris ([127.0.0.1])\n\tby OSIRIS\n\twith hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200\nMessage-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>\nFrom: \"John Smith\" <jsmith@somenet.foo>\nTo: <redmine@somenet.foo>\nSubject: New ticket on a given project\nDate: Sun, 22 Jun 2008 12:28:07 +0200\nMIME-Version: 1.0\nContent-Type: text/plain;\n\tformat=flowed;\n\tcharset=\"iso-8859-1\";\n\treply-type=original\nContent-Transfer-Encoding: 7bit\nX-Priority: 3\nX-MSMail-Priority: Normal\nX-Mailer: Microsoft Outlook Express 6.00.2900.2869\nX-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869\n\nLorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet \nturpis et odio. Integer eget pede vel dolor euismod varius. Phasellus \nblandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti \nsociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In \nin urna sed tellus aliquet lobortis. Morbi scelerisque tortor in dolor. Cras \nsagittis odio eu lacus. Aliquam sem tortor, consequat sit amet, vestibulum \nid, iaculis at, lectus. Fusce tortor libero, congue ut, euismod nec, luctus \neget, eros. Pellentesque tortor enim, feugiat in, dignissim eget, tristique \nsed, mauris. Pellentesque habitant morbi tristique senectus et netus et \nmalesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse \nplatea dictumst.\n\nNulla et nunc. Duis pede. Donec et ipsum. Nam ut dui tincidunt neque \nsollicitudin iaculis. Duis vitae dolor. Vestibulum eget massa. Sed lorem. \nNullam volutpat cursus erat. Cras felis dolor, lacinia quis, rutrum et, \ndictum et, ligula. Sed erat nibh, gravida in, accumsan non, placerat sed, \nmassa. Sed sodales, ante fermentum ultricies sollicitudin, massa leo \npulvinar dui, a gravida orci mi eget odio. Nunc a lacus.\n\nProject: onlinestore\nTracker: Feature Request\ncategory: stock management\npriority: URGENT\n"
  },
  {
    "path": "test/functional/issues_controller_with_helpdesk_test.rb",
    "content": "require File.dirname(__FILE__) + '/../test_helper'\n\nclass IssuesControllerWithHelpdeskTest < ActionController::TestCase\n  include Redmine::I18n\n\n  fixtures :all\n\n  def setup\n    User.current = nil\n    @controller = IssuesController.new\n  end\n\n  def test_render_send_to_owner_checkbox\n    issue = Issue.find(1)\n    @request.session[:user_id] = 1\n    get :edit, :id => 1\n    assert_response :success\n    assert_select \"#send_to_owner\", 1\n  end\n\n  test \"send_to_owner not renderer without owner-email\" do\n    issue = Issue.find(1)\n    owner_field = CustomField.find_by_name('owner-email')\n    owner_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.id, owner_field.id).\n      first\n    owner_value.value = \"\"\n    owner_value.save!\n\n    @request.session[:user_id] = 1\n    get :edit, :id => 1\n    assert_response :success\n    assert_select \"#send_to_owner\", 0\n  end\n\n  test \"send_to_owner checked if send-to-owner-default is set to yes\" do\n    issue = Issue.find(1)\n    default_field = CustomField.find_by_name('helpdesk-send-to-owner-default')\n    default_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, default_field.id).\n      first\n    default_value.value = \"1\"\n    default_value.save!\n\n    @request.session[:user_id] = 1\n    get :edit, :id => 1\n    assert_response :success\n    assert_select \"#send_to_owner\", 1\n    assert_equal \"checked\", css_select(\"#send_to_owner\").first[\"checked\"]\n  end\n\n  test \"send_to_owner checked if send-to-owner-default is set to no\" do\n    issue = Issue.find(1)\n    default_field = CustomField.find_by_name('helpdesk-send-to-owner-default')\n    default_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, default_field.id).\n      first\n    default_value.value = \"2\"\n    default_value.save!\n\n    @request.session[:user_id] = 1\n    get :edit, :id => 1\n    assert_response :success\n    assert_select \"#send_to_owner\", 1\n    assert_not_equal \"checked\", css_select(\"#send_to_owner\").first[\"checked\"]\n  end\n\n  test \"history note added to journal if note has been sent to owner\" do\n    issue = Issue.find(1)\n    journal = issue.journals.first\n    journal.send_to_owner = true\n    journal.save\n\n    @request.session[:user_id] = 1\n    get :show, :id => 1\n    assert_response :success\n\n    assert_select \"#history>i\", 1\n    assert_select \"#history>i\", \"This answer was sent to the supportclient.\"\n  end\n\n  test \"history note not added to journal if note has not been sent to owner\" do\n    issue = Issue.find(1)\n    journal = issue.journals.first\n    journal.send_to_owner = false\n    journal.save\n\n    @request.session[:user_id] = 1\n    get :show, :id => 1\n    assert_response :success\n\n    assert_select \"#history>i\", 0\n  end\n\n  test \"send_to_owner checked\" do\n    ActionMailer::Base.delivery_method = :test\n    ActionMailer::Base.deliveries.clear\n    @request.session[:user_id] = 1\n    assert_difference('Journal.count') do\n      put :update, :id => 1,\n                   :issue => {:assigned_to_id => 1,\n                              :notes => 'Assigned'},\n                   :send_to_owner => \"true\"\n    end\n    assert_redirected_to :action => 'show', :id => '1'\n\n    assert Issue.find(1).journals.last.send_to_owner\n    mail = ActionMailer::Base.deliveries.last\n    assert_equal \"owner@example.com\",  mail.to.first\n    assert_equal \"Assigned\\n\\nemail footer\", mail.body.to_s\n  end\n\n  test \"send_to_owner not checked\" do\n    ActionMailer::Base.delivery_method = :test\n    ActionMailer::Base.deliveries.clear\n    @request.session[:user_id] = 1\n    assert_difference('Journal.count') do\n      put :update, :id => 1,\n                   :issue => {:assigned_to_id => 1,\n                              :notes => 'Assigned'},\n                   :send_to_owner => \"false\"\n    end\n    assert_redirected_to :action => 'show', :id => '1'\n\n    assert !Issue.find(1).journals.last.send_to_owner\n    ActionMailer::Base.deliveries.each do |mail|\n      assert !mail.to.include?(\"owner@example.com\")\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_helper.rb",
    "content": "require \"simplecov\"\nrequire \"codeclimate-test-reporter\"\n\nSimpleCov.use_merging true\nSimpleCov.merge_timeout 3600\nSimpleCov.add_filter '/test/'\nSimpleCov.add_filter 'init.rb'\nSimpleCov.formatters = []\nSimpleCov.start(CodeClimate::TestReporter.configuration.profile) do\n  root File.expand_path(File.dirname(__FILE__) + '/../../')\nend\n\n# Load the normal Rails helper\nrequire File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper')\n\nclass TestHelper\n  def self.files_path\n    File.dirname(__FILE__) + '/fixtures/'\n  end\n  def self.fixture_path\n    if Redmine::VERSION::MAJOR >= 3\n      File.dirname(__FILE__) + '/fixtures/3.0'\n    else\n      File.dirname(__FILE__) + '/fixtures/2.6'\n    end\n  end\nend\n\nclass ActiveSupport::TestCase\n  self.fixture_path = TestHelper.fixture_path\nend\n"
  },
  {
    "path": "test/unit/helpdesk_mailer_test.rb",
    "content": "require File.dirname(__FILE__) + '/../test_helper'\n\nclass HelpdeskMailerTest < ActionMailer::TestCase\n  include Redmine::I18n\n\n  self.use_transactional_tests = true\n\n  fixtures :all\n\n  def setup\n    ActionMailer::Base.deliveries.clear\n    Setting.host_name = 'mydomain.foo'\n    Setting.protocol = 'http'\n    Setting.plain_text_mail = '0'\n    Setting.default_language = 'en'\n    User.current = nil\n  end\n\n  def teardown\n    Setting.clear_cache\n  end\n\n  def test_default_url_options\n    default_url_object = HelpdeskMailer.default_url_options\n    assert_equal \"mydomain.foo\", default_url_object[:host]\n    assert_equal \"http\", default_url_object[:protocol]\n  end\n\n  def test_email_headers\n    issue = Issue.find(1)\n    email = HelpdeskMailer.\n        email_to_supportclient(issue, {:recipient => \"owner@example.com\"}).\n        deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert_not_nil email\n    assert_equal issue.project.identifier, email.header['X-Redmine-Project'].to_s\n    assert_equal issue.id, email.header['X-Redmine-Issue-Id'].to_s.to_i\n    assert_equal issue.author.login, email.header['X-Redmine-Issue-Author'].to_s\n    assert_equal issue.assigned_to.login, email.header['X-Redmine-Issue-Assignee'].to_s\n    assert_equal issue.tracker, email.header['X-Redmine-Issue-Tracker'].to_s\n\n    #assert_equal 'OOF', mail.header['X-Auto-Response-Suppress'].to_s\n    #assert_equal 'auto-generated', mail.header['Auto-Submitted'].to_s\n    #assert_equal '<redmine.example.net>', mail.header['List-Id'].to_s\n  end\n\n  def test_email_default_sender\n    issue = Issue.find(1)\n    s = CustomField.find_by_name('helpdesk-sender-email')\n    custom_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, s.id).\n      first\n    custom_value.destroy\n\n    email = HelpdeskMailer.\n        email_to_supportclient(issue, {:recipient => \"owner@example.com\"}).\n        deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert_equal Setting.mail_from, email.header['From'].to_s\n  end\n\n  def test_email_helpdesk_sender\n    issue = Issue.find(1)\n    email = HelpdeskMailer.\n        email_to_supportclient(issue, {:recipient => \"owner@example.com\"}).\n        deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert_equal \"reply@example.com\", email.header['From'].to_s\n  end\n\n  def test_email_helpdesk_sender_with_phrase\n    issue = Issue.find(1)\n    s = CustomField.find_by_name('helpdesk-sender-email')\n    custom_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, s.id).\n      first\n    custom_value.value = \"Redmine helpdesk <reply@example.com>\"\n    custom_value.save\n\n    email = HelpdeskMailer.\n        email_to_supportclient(issue, {:recipient => \"owner@example.com\"}).deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert_equal \"Redmine helpdesk <reply@example.com>\", email.header['From'].to_s\n  end\n\n  def test_first_reply\n    issue = Issue.find(1)\n    email = HelpdeskMailer.\n        email_to_supportclient(issue, {:recipient => \"owner@example.com\"}).\n        deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert_match /^redmine\\.issue-1\\.\\d+\\.[a-f0-9]+@example\\.net/, email.message_id\n    assert_match /redmine\\.issue-1\\.\\d+@example\\.net/, email.references\n\n    assert_equal \"first reply\",\n        email.body.to_s\n  end\n\n  def test_edit\n    issue = Issue.find(1)\n    email = HelpdeskMailer.\n        email_to_supportclient(\n            issue,\n            {:recipient => \"owner@example.com\",\n             :journal   => Journal.find(1),\n             :text     => 'text'\n            }).\n        deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert_match /^redmine\\.issue-1\\.\\d+\\.[a-f0-9]+@example\\.net/, email.message_id\n    assert_match /redmine\\.issue-1\\.\\d+@example\\.net/, email.references\n\n    assert_equal \"text\\n\\nemail footer\",\n        email.body.to_s\n  end\n\n  def test_fallback_message_id\n    issue = Issue.find(2)\n    s = CustomField.find_by_name('helpdesk-first-reply')\n    custom_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, s.id).\n      first\n    custom_value.destroy\n\n    email = HelpdeskMailer.\n        email_to_supportclient(\n            issue,\n            {:recipient => \"owner@example.com\",\n             :journal   => Journal.find(1),\n             :text      => 'text'\n            }).\n        deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert_match /^redmine\\.issue-2\\.\\d+\\.[a-f0-9]+@example\\.net/, email.message_id\n    assert_match /redmine\\.issue-2\\.\\d+@example\\.net/, email.references\n  end\n\n  def test_subject\n    issue = Issue.find(1)\n    email = HelpdeskMailer.\n        email_to_supportclient(issue, {:recipient => \"owner_email\"}).\n        deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert_equal \"[#{issue.project.name} - ##{issue.id}] #{issue.subject}\", email.subject.to_s\n  end\n\n  # Test with single attachment and verify against fixture file\n  def test_attachments_added\n    Attachment.storage_path = TestHelper.files_path + '/files'\n    issue = Issue.find(1)\n    email = HelpdeskMailer.\n        email_to_supportclient(\n            issue,\n            {:recipient => \"owner@example.com\",\n             :journal   => Journal.find(3),\n             :text      => 'text'\n            }).deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    mail = ActionMailer::Base.deliveries.last\n    assert_not_nil mail\n    attachments_length = mail.attachments.length\n    assert_equal 1, attachments_length\n    filename = mail.attachments[0].filename\n    assert_equal \"source.rb\", filename\n    content = mail.attachments[0].body.to_s\n    original_content = File.open(\n        Attachment.find(\n            Journal.find(3).details.first.prop_key).diskfile).read\n    assert_equal original_content, content\n  end\nend\n"
  },
  {
    "path": "test/unit/journal_patch_test.rb",
    "content": "require File.dirname(__FILE__) + '/../test_helper'\n\nclass JournalPatchTest < ActiveSupport::TestCase\n  include Redmine::I18n\n\n  self.use_transactional_tests = true\n\n  fixtures :all\n\n  def setup\n    User.current = User.find(1)\n  end\n\n  def teardown\n    Setting.clear_cache\n  end\n\n  def test_notification_not_sent_when_send_to_owner_false\n    HelpdeskMailer.any_instance.expects(:email_to_supportclient).never\n    Mailer.any_instance.stubs(:deliver_issue_edit).returns(true)\n\n    issue = Issue.find(1)\n    journal = issue.journals.first\n    journal.send_to_owner = false\n    journal.save!\n\n    journal.send(:send_notification)\n  end\n\n  def test_notification_not_sent_when_notes_length_zero\n    HelpdeskMailer.any_instance.expects(:email_to_supportclient).never\n    Mailer.any_instance.stubs(:deliver_issue_edit).returns(true)\n\n    issue = Issue.find(1)\n    journal = issue.journals.first\n    journal.notes = \"\"\n    journal.send_to_owner = true\n    journal.save!\n\n    journal.send(:send_notification)\n  end\n\n  def test_notification_note_sent_when_owner_email_blank\n    HelpdeskMailer.any_instance.expects(:email_to_supportclient).never\n    Mailer.any_instance.stubs(:deliver_issue_edit).returns(true)\n\n    issue = Issue.find(1)\n    journal = issue.journals.first\n    owner_field = CustomField.find_by_name('owner-email')\n    owner_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.id, owner_field.id).\n      first\n    owner_value.value = \"\"\n    owner_value.save!\n    journal.send_to_owner = true\n    journal.save!\n\n    journal.send(:send_notification)\n  end\n\n  def test_notification_sent\n    Mailer.any_instance.stubs(:deliver_issue_edit).returns(true)\n\n    issue = Issue.find(1)\n    journal = issue.journals.first\n    journal.send_to_owner = true\n    journal.save!\n\n    HelpdeskMailer.any_instance.expects(:email_to_supportclient).with(issue, \n        {:recipient => \"owner@example.com\", \n         :journal   => journal, \n         :text      => journal.notes\n        }).once\n    journal.send(:send_notification)\n  end\nend\n"
  },
  {
    "path": "test/unit/macro_expander_test.rb",
    "content": "require File.dirname(__FILE__) + '/../test_helper'\n\nclass MacroExpanderTest < ActionMailer::TestCase\n  include Redmine::I18n\n\n  self.use_transactional_tests = true\n\n  fixtures :all\n\n  def setup\n    ActionMailer::Base.deliveries.clear\n    Setting.host_name = 'mydomain.foo'\n    Setting.protocol = 'http'\n    Setting.plain_text_mail = '0'\n    Setting.default_language = 'en'\n    User.current = nil\n  end\n\n  def teardown\n    Setting.clear_cache\n  end\n\n  def test_expand_issue\n    issue = Issue.find(1)\n    s = CustomField.find_by_name('helpdesk-email-footer')\n    custom_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, s.id).\n      first\n    custom_value.value = \"##issue-id##, ##issue-subject##, ##issue-tracker##, ##issue-status##\"\n    custom_value.save\n    email = HelpdeskMailer.\n        email_to_supportclient(\n            issue,\n            {\n                :recipient => \"owner@example.com\",\n                :journal   => Journal.find(1),\n                :text      => 'text'\n            }).deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert \"text\\n\\n#{issue.id}, #{issue.subject}, #{issue.tracker}, #{issue.status}\", email.body.to_s\n  end\n\n  def test_expand_project\n    issue = Issue.find(1)\n    s = CustomField.find_by_name('helpdesk-email-footer')\n    custom_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, s.id).\n      first\n    custom_value.value = \"##project-name##\"\n    custom_value.save\n    email = HelpdeskMailer.\n        email_to_supportclient(\n            issue,\n            { \n                :recipient => \"owner@example.com\",\n                :journal   => Journal.find(1),\n                :text      =>'text'\n            }).deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert \"text\\n\\n#{issue.project.name}\", email.body.to_s\n  end\n\n  def test_expand_user\n    issue = Issue.find(1)\n    s = CustomField.find_by_name('helpdesk-email-footer')\n    custom_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, s.id).\n      first\n    custom_value.value = \"##user-name##, ##user-firstname##, ##user-lastname##, ##user-mail##, ##user-login##\"\n    custom_value.save\n    email = HelpdeskMailer.\n        email_to_supportclient(\n            issue,\n            {\n                :recipient => \"owner@example.com\",\n                :journal   => Journal.find(1),\n                :text      => 'text'\n            }).deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    user = Journal.find(1).user\n    assert \"text\\n\\n#{user.name}, #{user.firstname}, #{user.lastname}, #{user.mail}, #{user.login}\", email.body.to_s\n  end\n\n  def test_expand_user_cfs_w_not_existing\n    issue = Issue.find(1)\n    user = Journal.find(1).user\n    s = CustomField.find_by_name('helpdesk-email-footer')\n    custom_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, s.id).\n      first\n    custom_value.value = \"##user-cf-title##, ##user-cf-motto##, ##user-cf-invalid##.\"\n    custom_value.save\n\n    title = CustomField.find_by_name('title')\n    custom_value = CustomValue.new(\n      :customized_id => user.id,\n      :custom_field_id => title.id,\n      :value => \"junior senior\"\n    )\n    custom_value.save\n    motto = CustomField.find_by_name('motto')\n    custom_value = CustomValue.new(\n      :customized_id => user.id,\n      :custom_field_id => motto.id,\n      :value => \"epic motto\"\n    )\n    custom_value.save\n\n    email = HelpdeskMailer.\n        email_to_supportclient(\n            issue,\n            {:recipient => \"owner@example.com\",\n             :journal   => Journal.find(1),\n             :text      =>'text'\n            }).deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert \"text\\n\\njunior senior, epic motto, .\", email.body.to_s\n  end\n\n  def test_expand_user_no_cfs\n    issue = Issue.find(1)\n    user = Journal.find(1).user\n    s = CustomField.find_by_name('helpdesk-email-footer')\n    custom_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, s.id).\n      first\n    custom_value.value = \"##user-cf-title##, ##user-cf-motto##, ##user-cf-invalid##.\"\n    custom_value.save\n\n    email = HelpdeskMailer.\n        email_to_supportclient(\n            issue,\n            {\n                :recipient => \"owner@example.com\",\n                :journal   => Journal.find(1),\n                :text      => 'text'\n            }).deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert \"text\\n\\n, , .\", email.body.to_s\n  end\n\n  def test_expand_base\n    issue = Issue.find(1)\n    s = CustomField.find_by_name('helpdesk-email-footer')\n    custom_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.project.id, s.id).\n      first\n    custom_value.value = \"##time-now##\"\n    custom_value.save\n\n    t1 = I18n.l(Time.zone.now)\n    email = HelpdeskMailer.\n        email_to_supportclient(\n            issue,\n            {\n                :recipient => \"owner@example.com\",\n                :journal   => Journal.find(1),\n                :text      => 'text'\n            }).deliver\n    assert !ActionMailer::Base.deliveries.empty?\n    assert \"text\\n\\n#{t1}\", email.body.to_s\n  end\nend\n"
  },
  {
    "path": "test/unit/mail_handler_patch_test.rb",
    "content": "require File.dirname(__FILE__) + '/../test_helper'\n\nclass MailHandlerPatchTest < ActiveSupport::TestCase\n  include Redmine::I18n\n\n  self.use_transactional_tests = true\n\n  fixtures :all\n\n  def setup\n    ActionMailer::Base.deliveries.clear\n    Setting.notified_events = Redmine::Notifiable.all.collect(&:name)\n  end\n\n  def teardown\n    Setting.clear_cache\n  end\n\n  def test_helpdesk_dispatch_not_supportclient\n    HelpdeskMailer.any_instance.expects(:email_to_supportclient).never\n    issue = submit_email('ticket_by_user_1.eml',\n                         :issue => {:project => 'helpdesk_project_1'},\n                         :unknown_user => 'accept',\n                         :no_permission_check => 1)\n    assert_issue_created issue\n\n    owner_field = CustomField.find_by_name('owner-email')\n    owner_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.id, owner_field.id).\n      first\n    assert owner_value.value.blank?\n    assert User.find(1).login, issue.author.login\n  end\n\n  def test_helpdesk_dispatch_disabled_copy_to\n    assert_no_difference 'User.count' do\n      HelpdeskMailer.any_instance.expects(:email_to_supportclient).with(\n        kind_of(Issue),  {:recipient =>\"john.doe@somenet.foo\", \n                          :carbon_copy => nil}\n      ).once\n      issue = submit_email('ticket_by_unknown_user_with_cc.eml',\n                       :issue => {:project => 'helpdesk_project_4'},\n                       :unknown_user => 'accept',\n                       :no_permission_check => 1)\n      assert_issue_created issue\n\n      owner_field = CustomField.find_by_name('owner-email')\n      owner_value = CustomValue.where(\n          \"customized_id = ? AND custom_field_id = ?\", issue.id, owner_field.id).\n          first\n      assert_equal \"john.doe@somenet.foo\", owner_value.value\n      assert issue.author.anonymous?\n    end\n  end\n\n  def test_helpdesk_dispatch_anonymous_as_supportclient\n    assert_no_difference 'User.count' do\n      HelpdeskMailer.any_instance.expects(:email_to_supportclient).with(\n        kind_of(Issue), {:recipient =>\"john.doe@somenet.foo\", :carbon_copy => nil}).once\n      issue = submit_email('ticket_by_unknown_user.eml',\n                       :issue => {:project => 'helpdesk_project_1'},\n                       :unknown_user => 'accept',\n                       :no_permission_check => 1)\n      assert_issue_created issue\n\n      owner_field = CustomField.find_by_name('owner-email')\n      owner_value = CustomValue.where(\n          \"customized_id = ? AND custom_field_id = ?\", issue.id, owner_field.id).\n          first\n      assert_equal \"john.doe@somenet.foo\", owner_value.value\n      assert issue.author.anonymous?\n    end\n  end\n\n  def test_helpdesk_dispatch_anonymous_as_supportclient_with_cc\n    assert_no_difference 'User.count' do\n      HelpdeskMailer.any_instance.expects(:email_to_supportclient).with(\n        kind_of(Issue),  {:recipient =>\"john.doe@somenet.foo\", \n                          :carbon_copy => \"Ada <ada@test.lindsaar.net>, mikel@test.lindsaar.net, Bob <bob@test.lindsaar.net>\"}\n      ).once\n      issue = submit_email('ticket_by_unknown_user_with_cc.eml',\n                       :issue => {:project => 'helpdesk_project_1'},\n                       :unknown_user => 'accept',\n                       :no_permission_check => 1)\n      assert_issue_created issue\n\n      owner_field = CustomField.find_by_name('owner-email')\n      owner_value = CustomValue.where(\n          \"customized_id = ? AND custom_field_id = ?\", issue.id, owner_field.id).\n          first\n      copy_to_field = CustomField.find_by_name('copy-to')\n      copy_to_value = CustomValue.where(\n          \"customized_id = ? AND custom_field_id = ?\", issue.id, copy_to_field.id).\n          first\n      assert_equal \"john.doe@somenet.foo\", owner_value.value\n      assert issue.author.anonymous?\n      assert_equal \"Ada <ada@test.lindsaar.net>, mikel@test.lindsaar.net, Bob <bob@test.lindsaar.net>\",\n          copy_to_value.value\n    end\n  end\n\n  def test_helpdesk_dispatch_supportclient\n    HelpdeskMailer.any_instance.expects(:email_to_supportclient).with(kind_of(Issue), \n        {:recipient => User.find(2).mail, :carbon_copy => nil})\n    issue = submit_email('ticket_by_user_2.eml',\n                         :issue => {:project => 'helpdesk_project_2'},\n                         :unknown_user => 'accept',\n                         :no_permission_check => 1)\n    assert_issue_created issue\n\n    owner_field = CustomField.find_by_name('owner-email')\n    owner_value = CustomValue.where(\n      \"customized_id = ? AND custom_field_id = ?\", issue.id, owner_field.id).\n      first\n    assert_equal User.find(2).mail, owner_value.value\n    assert User.find(2).login, issue.author.login\n  end\n\n  # TODO: Attachments\n\n  def submit_email(filename, options={})\n    raw = IO.read(File.join(TestHelper.files_path, 'mail_handler', filename))\n    yield raw if block_given?\n    MailHandler.receive(raw, options)\n  end\n\n  def assert_issue_created(issue)\n    assert issue.is_a?(Issue)\n    assert !issue.new_record?\n    issue.reload\n  end\nend\n"
  }
]