mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
25fc7cd02b
* Prepare basic recurring meeting setup
* Add proof of concept to create schedules
* Add feature flag
* Rework menu
* Pass request to meetings menu
This doesn't help, as the requested url is the turbo frame
* Add filter menu for recurring meetings
* Start primerized create form
* Add recurring meetings to dropdown and dialog
* Add schedule
* Add frequency/iterations form
* Add services
* Recurring meetings menu entry
* Fix setting project
* Template
* add bi-weekly
* Add template sideinfo
* Skip mails when adding participants
* exclude templated meetings
* Add header for templates
* Prevent deletion of meeting template
* Fix breadcrumb
* WIP Add show table and initialization
* Change icon for calendar
* remove unused template
* add template has_one
* meeting form
* Fix creation of recurring
* working edit
* specify end time
* Add header actions
* Add initial recurring meeting frequency label
* Add index page
* Add soft delete and restore for occurrences
* Refine implementation of scheduled meetings using skeletons
* Add template link
* Paginate
* Move init of meeting to recurring
* Add schedule in words
* Add show series action item
* Implement changed show page of occurrence
* Add interval, fewer frequencies
* Add interval to schedule
* Try to add non working days
* Update meetings index to display recurring occurrences correctly
* Update schedule in words
* Fix exception rule
* Fix occurrence for working days
* Hide interval when selecting working_days
* Document show-when-value-selected
* Set interval to 1 when changing to working_days
* Fix dialog
* Adapt to mobile table
* Update type filter
* Rename TypeFilter -> RecurringFilter
* Start date group
* Combined Filter component
* Updated menu
* Update label created by me
* Add validation on end_date > start_date
* Implement sorting through query
* Render all meeting series in the sidebar
* Select my meetings only when href passed
* WIP Add initial specs
* Fix date validation
* Use the correct date formatter in the subtitle
* Add spec for date validation
* Change label to View template
* Add edit series button
* Fix deletion of recurring meetings
* Correctly hide form for end_after options
* Update copy behaviour to never allow recurring copies
* Fix location value in form
* Fix meeting details form
* Add scheduled meetings table
* Replace destroy/restore with actual destroy
* Uniqueness
* Delete with schedule
* Switch to start_time
* Use start_time in schedule
Otherwise, we get time mismatches
* Add helper for time formatting to the current user
* fixup! Delete with schedule
* Move update_start_time to concern
* Delete cancelled meetings when changing schedule
* Allow passing dates directly
* Remove cancelled occurrences when changing schedules
* Limit count_rule until end_date
* Show changed start times for occurrences
* Indent case
* Fix destroy path to include project
* Fix past meetings
* Schedule first occurrence on creation
* Linting
* fixup! Linting
* Autoschedule job
* Add more schedule tests
* Fix project-based destroy
* Redirect to template, not show
* Don't cache user time zone in request store
* Fix forgotten invited where
* fixup! Linting
* Remove default meeting order
* Fix meetings index spec with new ordering
* Fix path
* Convert meeting tab to cuprite
* Fix expectation for meeting tab
* More robust selector on meeting tab
* Change global menu spec
* Add more CRUD specs
* Fix dates and times
* Allow cancellation of scheduled meetings
* Lint
* Reschedule init job when updating schedule
* Fix end date in the form
* Test cancellation
* Extract create spec
* Fix specs
* Add spec when lacking permissions
* Fix cancellation of scheduled meetings
* Render meetings with correct project link
* Remove unused disable
* Remove useless cop disable
* Add contract specs
* Add delete contract spec
* Revert "Add delete contract spec"
This reverts commit 27a517d773.
* Add delete contract spec for meetings itself
* Fix spec
* Hide past cancelled occurrences
* Show different delete labels and messages
* Move to request spec
---------
Co-authored-by: Mir Bhatia <m.bhatia@openproject.com>
200 lines
6.6 KiB
Bash
Executable File
200 lines
6.6 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -e
|
|
|
|
|
|
|
|
DUMPFILE="${1:?Pass the dump file to anonymize as first argument}"
|
|
if [ -f "$HOME/openproject/dev/Gemfile" ]; then
|
|
OPENPROJECT_DEV_DIR="$HOME/openproject/dev"
|
|
elif [ -f "$HOME/openproject/Gemfile" ]; then
|
|
OPENPROJECT_DEV_DIR="$HOME/openproject"
|
|
elif [ -f "$HOME/code/opf/openproject/Gemfile" ]; then
|
|
OPENPROJECT_DEV_DIR="$HOME/code/opf/openproject"
|
|
else
|
|
OPENPROJECT_DEV_DIR="${2:?Pass the openproject dev directory as second argument (needed to create the admin user)}"
|
|
[ -f "$OPENPROJECT_DEV_DIR/Gemfile" ] || { echo "OpenProject dev directory $OPENPROJECT_DEV_DIR is not an OpenProject repository"; exit 1; }
|
|
fi
|
|
echo "Using non-anonymized dump file $DUMPFILE"
|
|
echo "Using OpenProject dev directory $OPENPROJECT_DEV_DIR"
|
|
|
|
|
|
|
|
echo_header() {
|
|
echo "--"
|
|
echo "-- $*"
|
|
echo "--"
|
|
}
|
|
|
|
|
|
|
|
echo_header "CHECKING THAT WE ARE ON THE EC2 BASTION HOST"
|
|
VPN_IP_ADDRESS="52.29.160.234"
|
|
if [[ $(hostname) != *.compute.internal ]] || [[ $(curl --silent ip.me) == "$VPN_IP_ADDRESS" ]]; then
|
|
cat <<EOT
|
|
It looks like you're not on an EC2 instance.
|
|
This script is meant to be run in the cloud so that customer data never reaches a dev machine.
|
|
|
|
Please run it on the bastion host which is a EC2 instance dedicated to that kind of task.
|
|
There are bastion hosts for production and edge environments.
|
|
|
|
Ask help to ops team for the right bastion hosts.
|
|
EOT
|
|
exit 1
|
|
fi
|
|
|
|
|
|
|
|
echo_header "IMPORTING DUMP FILE $DUMPFILE"
|
|
|
|
dropdb --if-exists tmp
|
|
createdb tmp
|
|
psql --quiet --dbname tmp --command "DROP SCHEMA public;"
|
|
psql --quiet --dbname tmp --command "CREATE EXTENSION IF NOT EXISTS btree_gist WITH SCHEMA pg_catalog;"
|
|
psql --quiet --dbname tmp --command "CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA pg_catalog;"
|
|
psql --quiet --dbname tmp < $DUMPFILE
|
|
|
|
|
|
|
|
SCHEMA=$(psql --tuples-only --quiet --dbname tmp --command "select schema_name from information_schema.schemata WHERE schema_owner != 'postgres';" | tr -d '[:space:]')
|
|
echo_header "RENAMING SCHEMA $SCHEMA to public"
|
|
|
|
psql --quiet --dbname tmp --command "ALTER SCHEMA \"$SCHEMA\" RENAME TO \"public\";"
|
|
psql --quiet --dbname tmp --command "UPDATE settings SET value = 'localhost:3000' WHERE name = 'host_name'"
|
|
|
|
|
|
|
|
echo_header "ANONYMIZING DATA"
|
|
cleanup_sql_file=$(mktemp /tmp/cleanup.sql.XXXXXX)
|
|
|
|
cat <<SQL > "$cleanup_sql_file"
|
|
DELETE FROM sessions;
|
|
DELETE FROM user_passwords;
|
|
DELETE FROM two_factor_authentication_devices;
|
|
DELETE FROM tokens;
|
|
DELETE FROM enterprise_tokens;
|
|
DELETE FROM recaptcha_entries;
|
|
DELETE FROM job_statuses;
|
|
DELETE FROM good_jobs;
|
|
DELETE FROM good_job_batches;
|
|
DELETE FROM good_job_executions;
|
|
DELETE FROM good_job_processes;
|
|
DELETE FROM good_job_settings;
|
|
DELETE FROM deploy_targets;
|
|
DELETE FROM deploy_status_checks;
|
|
DELETE FROM storages;
|
|
DELETE FROM storages_file_links_journals;
|
|
DELETE FROM project_storages;
|
|
DELETE FROM last_project_folders;
|
|
DELETE FROM remote_identities;
|
|
DELETE FROM file_links;
|
|
DELETE FROM oauth_access_tokens;
|
|
DELETE FROM oauth_access_grants;
|
|
DELETE FROM oauth_applications;
|
|
DELETE FROM oauth_client_tokens;
|
|
DELETE FROM oauth_clients;
|
|
DELETE FROM oidc_user_session_links;
|
|
DELETE FROM webhooks_events;
|
|
DELETE FROM webhooks_logs;
|
|
DELETE FROM webhooks_webhooks;
|
|
DELETE FROM paper_trail_audits;
|
|
DELETE FROM settings WHERE name = 'welcome_text';
|
|
DELETE FROM settings WHERE name = 'welcome_title';
|
|
DELETE FROM settings WHERE name = 'app_title';
|
|
DELETE FROM settings WHERE name = 'mail_from';
|
|
DELETE FROM settings WHERE name = 'consent_info';
|
|
|
|
UPDATE attachments SET file_tsv = NULL, fulltext = NULL, fulltext_tsv = NULL;
|
|
|
|
DO \$\$
|
|
DECLARE table_name TEXT;
|
|
DECLARE column_name TEXT;
|
|
BEGIN
|
|
SET client_min_messages TO INFO;
|
|
FOR table_name, column_name IN (
|
|
SELECT DISTINCT information_schema.columns.table_name, information_schema.columns.column_name
|
|
FROM information_schema.columns
|
|
WHERE information_schema.columns.table_schema = 'public'
|
|
AND data_type IN ('character varying', 'text')
|
|
AND information_schema.columns.table_name NOT IN
|
|
(
|
|
'ar_internal_metadata',
|
|
'audits',
|
|
'schema_migrations',
|
|
'colors',
|
|
'changes',
|
|
'delayed_jobs',
|
|
'github_check_runs',
|
|
'github_pull_requests',
|
|
'grid_widgets',
|
|
'paper_trail_audits',
|
|
'custom_values',
|
|
'customizable_values',
|
|
'custom_fields',
|
|
'roles',
|
|
'enumerations',
|
|
'queries',
|
|
'statuses',
|
|
'settings',
|
|
'role_permissions',
|
|
'enabled_modules',
|
|
'two_factor_authentication_devices',
|
|
'tokens',
|
|
'job_statuses'
|
|
)
|
|
AND information_schema.columns.column_name NOT LIKE '%type%'
|
|
AND NOT (information_schema.columns.table_name = 'grids' AND information_schema.columns.column_name = 'options')
|
|
AND NOT (information_schema.columns.table_name = 'users' AND information_schema.columns.column_name = 'language')
|
|
AND NOT (information_schema.columns.table_name = 'types' AND information_schema.columns.column_name = 'attribute_groups')
|
|
)
|
|
LOOP
|
|
RAISE INFO '%', CONCAT('UPDATE ', table_name, ' SET ', column_name, '=MD5(', column_name, ') WHERE NOT ', column_name, ' = '''';');
|
|
EXECUTE CONCAT('UPDATE ', table_name, ' SET ', column_name, '=MD5(', column_name, ') WHERE NOT ', column_name, ' = '''';');
|
|
|
|
END LOOP;
|
|
END \$\$;
|
|
|
|
UPDATE roles SET name = MD5(name)::varchar(30);
|
|
UPDATE enumerations SET name = MD5(name)::varchar(30);
|
|
UPDATE custom_fields SET name = MD5(name)::varchar(30);
|
|
UPDATE statuses SET name = MD5(name)::varchar(30);
|
|
UPDATE queries SET name = MD5(name)::varchar(30);
|
|
UPDATE custom_values SET value = MD5(value) WHERE custom_field_id in (SELECT id from custom_fields where field_format IN ('text', 'string'));
|
|
UPDATE customizable_journals SET value = MD5(value) WHERE custom_field_id in (SELECT id from custom_fields where field_format IN ('text', 'string'));
|
|
UPDATE grid_widgets SET options = '---\n:name: Custom title\n:text: Custom text\n' WHERE identifier = 'custom_text';
|
|
SQL
|
|
|
|
cat "$cleanup_sql_file" | psql --quiet --dbname tmp
|
|
rm "$cleanup_sql_file"
|
|
|
|
|
|
|
|
echo_header "CREATING ADMIN USER"
|
|
|
|
create_admin_rb_file=$(mktemp /tmp/create_admin_rb.XXXXXX)
|
|
|
|
cat <<RUBY > "$create_admin_rb_file"
|
|
admin_user = AdminUserSeeder.new.new_admin
|
|
admin_user.save!(validate: false)
|
|
RUBY
|
|
|
|
cd "$OPENPROJECT_DEV_DIR"
|
|
export DATABASE_URL=postgres:///tmp
|
|
bundle exec rails runner "$create_admin_rb_file"
|
|
cd -
|
|
rm "$create_admin_rb_file"
|
|
|
|
|
|
|
|
echo_header "DUMPING ANONYMIZED DATA TO $(pwd)/tmp.dump.sql"
|
|
pg_dump --no-owner --format=plain tmp > tmp.dump.sql
|
|
|
|
|
|
|
|
echo_header "DONE"
|
|
echo "Anonymized database dump saved to $(pwd)/tmp.dump.sql"
|
|
echo "Copy it to your machine and load it like this:"
|
|
echo " dropdb --if-exists --force openproject_debug_me"
|
|
echo " createdb --owner=openproject openproject_debug_me"
|
|
echo " psql --username=openproject openproject_debug_me < tmp.dump.sql"
|