Commit 291adf17 authored by mh's avatar mh
Browse files

Merge branch 'drop-migrations-update-schema' into 'master'

db maintenance - update schema & drop migrations + script to update schema from tests db

See merge request !48
parents a17c2c4c 63e5458d
Pipeline #8502 passed with stage
in 2 minutes and 47 seconds
#!/bin/env ruby
require 'active_record'
require 'active_record/schema_dumper'
require_relative '../lib/iapi/conf'
main_dir = File.expand_path(File.join(File.dirname(__FILE__),'..'))
ENV['IAPI_CONFIG'] = File.join(main_dir,'conf/test_conf.yaml')
db_conf = IApiConf.user_db
ActiveRecord::Base.establish_connection(db_conf)
filename = File.join(main_dir,'db/schema.rb')
puts "We expect you to have run all migrations successfully, we'll dump the schema to #{filename}. Press Enter to continue - Abort with Ctrl-c"
gets
File.open(filename, "w:utf-8") do |file|
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
end
# pg specific functions to sqlite statements
`sed -i -e 's/now()/CURRENT_TIMESTAMP/' -e 's/-> { "(0)::smallint" }/0/' -e 's/-> { "(1)::smallint" }/1/' -e 's/id: :serial, //' #{filename}`
class AddDelayJob < ActiveRecord::Migration[5.2]
def change
create_table :delayed_jobs, force: true do |table|
table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue
table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually.
table.text :handler, null: false # YAML-encoded string of the object that will do work
table.text :last_error # reason for last failure (See Note below)
table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
table.datetime :locked_at # Set when a client is working on this object
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
table.string :locked_by # Who is working on this object (if locked)
table.string :queue # The name of the queue this job is in
table.string :cron # Cron entry
table.timestamps null: true
end
add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority"
add_index :delayed_jobs, [:queue], :name => 'delayed_jobs_queue'
end
end
class DomainsInviteTokensRelation < ActiveRecord::Migration[5.2]
def change
create_table :email_domains_invite_tokens, id: false do |t|
t.belongs_to :email_domain, index: true
t.belongs_to :invite_token, index: true
end
end
end
class InviteTokensAddExpire < ActiveRecord::Migration[5.2]
def change
add_column :invite_tokens, :expire, :date
end
end
class RenameTreesMailCrypt < ActiveRecord::Migration[5.2]
def change
remove_column :email_users, :trees_public_key
remove_column :email_users, :trees_secret_box
remove_column :email_users, :trees_recovery_token
remove_column :email_users, :trees_extra_secret_boxes
add_column :email_users, "mail_crypt_public_key", :string, limit: 400
add_column :email_users, "mail_crypt_secret_box", :string, limit: 600
add_column :email_users, "mail_crypt_recovery_token", :string, limit: 400
add_column :email_users, "mail_crypt_extra_secret_boxes", :text
end
end
class EmailUsersAddAdminLocked < ActiveRecord::Migration[5.2]
def change
add_column :email_users, :admin_locked, :string, limit: 255
end
end
class ExtraSecretBoxes < ActiveRecord::Migration[5.2]
class MailCryptExtraBox < ActiveRecord::Base
belongs_to :email_user
end
def up
create_table :mail_crypt_extra_boxes do |t|
t.belongs_to :email_user, index: true
t.string "secret_box", limit: 500, null: false
t.text "name", null: false
t.datetime "expire"
t.integer "system", default: -> { "0" }, null: false
t.string "lastlogin", limit: 6
end
EmailUser.all.each do |u|
if u.mail_crypt_extra_secret_boxes.present?
b = YAML.load(u.mail_crypt_extra_secret_boxes)
b.each do |name, box|
MailCryptExtraBox.create!({
email_user: u,
secret_box: box[:box],
name: name,
expire: box[:expire],
})
end
end
end
remove_column :email_users, :mail_crypt_extra_secret_boxes
end
end
class Otps < ActiveRecord::Migration[5.2]
def change
create_table :otps, force: true do |table|
table.belongs_to :email_user, index: true
table.string :kind
table.string :totp
table.integer :totp_last
end
end
end
class MultiOtps < ActiveRecord::Migration[5.2]
def change
rename_table :otps, :totps
add_column :totps, :name, :string, limit: 255, null: false, default: 'default'
remove_column :totps, :kind
add_index :totps, [:email_user_id, :name], unique: true
end
end
class InviteTokensAddAdmin < ActiveRecord::Migration[5.2]
def change
add_column :invite_tokens, :allow_admin_account, :boolean, default: false
end
end
class UsersDropMigrate < ActiveRecord::Migration[5.2]
def change
remove_column :email_users, :migrate_to
remove_column :email_users, :migration_started_at
end
end
class JabberTables < ActiveRecord::Migration[5.2]
def up
create_table :jabber_domains do |t|
t.belongs_to :email_domain, index: true
t.string "name", null: false, index: true, unique: true
t.string "host", null: false, index: true
t.boolean "ispublic", null: false, default: false
end
create_table :jabber_ids do |t|
t.belongs_to :jabber_domain, index: true, null: false
t.belongs_to :email_user, index: true, null: false
t.text "name", index: true, null: false
t.text "password", null: false
t.string "lastlogin", limit: 6
t.timestamp "created_at", default: -> { "CURRENT_TIMESTAMP" }, null: false
t.timestamp "deleted_at"
end
add_index :jabber_ids, [:jabber_domain_id, :name], unique: true
add_index :jabber_ids, [:jabber_domain_id, :name, :email_user_id], unique: true, :name => 'jabber_ids_on_jabber_domain_id_and_name_and_email_user_id'
end
end
class UsersAddRatelimit < ActiveRecord::Migration[5.2]
def change
add_column :email_users, :ratelimit, :integer, default: nil
end
end
class EmailUsersAddRoles < ActiveRecord::Migration[5.2]
def up
create_table :acl_services do |t|
t.string "name", limit: 255, null: false, unique: true
t.string "service", limit: 510, null: false, unique: true
t.boolean "allow_by_default", default: false
end
create_table :acl_groups do |t|
t.string "name", limit: 510, null: false, unique: true
t.boolean "access_to_admin_api", default: false
end
create_table :acl_groups_to_services do |t|
t.belongs_to :acl_service, index: true
t.belongs_to :acl_group, index: true
t.index [:acl_service_id, :acl_group_id], :unique => true, :name => 'acl_groups_to_services_is_unique'
end
create_table :acl_memberships do |t|
t.belongs_to :email_user, index: true
t.belongs_to :acl_group, index: true
t.index [:email_user_id, :acl_group_id], :unique => true, :name => 'acl_memberships_is_unique'
end
end
end
class AddWebauthn < ActiveRecord::Migration[5.2]
def up
create_table "web_authn_credentials", force: :cascade do |t|
t.string "external_id"
t.string "public_key"
t.belongs_to :email_user, foreign_key: true
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
t.index ["email_user_id"], name: "index_credentials_on_email_user_id"
t.index [:email_user_id, :name], unique: true
t.index [:email_user_id, :public_key], unique: true
end
end
end
class RemoveAcl < ActiveRecord::Migration[5.2]
def up
drop_table :acl_services
drop_table :acl_groups
drop_table :acl_groups_to_services
drop_table :acl_memberships
end
end
class AddResources < ActiveRecord::Migration[5.2]
def up
create_table "resource_ownerships" do |t|
t.belongs_to :email_user, index: true
t.string "resource_uid", null: false
t.index [:email_user_id, :resource_uid], unique: true
end
create_table "deleted_resources" do |t|
t.string "resource_type", null: false
t.string "resource_uid", null: false
t.text "resource_backup"
t.date "deleted_at", default: -> { "CURRENT_TIMESTAMP" }, null: false
t.index :resource_uid, unique: true
end
create_table "reserved_emails" do |t|
t.string "email", null: false
t.date "deleted_at", default: -> { "CURRENT_TIMESTAMP" }, null: false
t.index :email, unique: true
end
end
end
class ReservedEmail < ActiveRecord::Base
end
class SplitEmailUsers < ActiveRecord::Migration[5.2]
def up
create_table "email_iaddresses" do |t|
t.string "local_part"
t.datetime "deleted_at"
t.belongs_to :email_domain, index: true
t.bigint :email_object_id
t.string :email_object_type
t.index [:email_object_type, :email_object_id],
name: 'email_iaddresses_email_object'
t.index [:local_part, :email_domain_id], unique: true
end
create_table "email_forwards" do |t|
t.belongs_to "email_iaddress"
t.string "target"
t.index [:email_iaddress_id, :target], unique: true
end
create_table "email_aliases" do |t|
t.belongs_to "email_user"
end
# needs to happen first, since there are clashing forwards
EmailSchleuder.all.each do |l|
d = EmailDomain.where(domain: l['domain']).first
EmailIaddress.create!(local_part: l.name, email_domain: d, email_object: l)
end
remove_column :email_schleuder, :name
remove_column :email_schleuder, :domain
EmailMailman.all.each do |l|
d = EmailDomain.where(domain: l.listendomain).first
EmailIaddress.create!(local_part: l.listenname, email_domain: d, email_object: l)
end
remove_column :email_mailman, :listenname
remove_column :email_mailman, :listendomain
EmailUser.all.each do |e|
a = e.alias
d = EmailDomain.where(domain: e['domain']).first
unless d
d = EmailDomain.create!(domain: e['domain'], iscatchall: 0, isdomainalias: 0, ispublic: 0)
puts "WARN: domain #{d} was missing"
end
n = EmailIaddress.where(local_part: a, email_domain: d).first
if n
if e['deleted_at']
unless n['email_object_id'].present?
n.deleted_at = e.deleted_at
n.save!
end
end
else
begin
n = EmailIaddress.create!(local_part: a, email_domain: d, deleted_at: e.deleted_at)
rescue ActiveRecord::RecordInvalid => err
if !e.ismailbox?
puts "WARN: purging invalid forward #{a}@#{d} #{err}"
e.delete
next
elsif e['deleted_at']
puts "WARN: purging invalid deleted mailbox #{a}@#{d} #{err}"
e.delete
next
else
puts "WARN: force saving invalid email #{a}@#{d} #{err}"
n = EmailIaddress.create(local_part: a, email_domain: d)
n.save(validate: false)
end
end
end
if e.ismailbox?
unless n['email_object_id'].present?
n.email_object = e
n.save!
end
end
unless e['deleted_at'] || !e.isforward?
fwds = (e.forward||'').split(",")
fwds.each do |f|
f = f.gsub(/[() ]/,"")
(f_l, f_dom) = f.split('@', 2)
u = EmailUser.where(alias: f_l, domain: f_dom).first
if fwds.size == 1 && !e.ismailbox? &&
!u.nil? && u.ismailbox? && !u['deleted_at'] &&
n.email_domain.domain != 'security-scan.immerda.ch'
a = EmailAlias.create!(email_iaddress: n, email_user: u)
n.email_object = a
n.save!
else
if EmailForward.where(email_iaddress: n, target: f).first
puts "WARN: #{n.email} has #{f} twice as target"
else
created = EmailForward.create(email_iaddress: n, target: f)
created.save(validate: false)
end
end
end
end
end
EmailUser.where(ismailbox: 0).delete_all
EmailUser.all.each do |u|
unless u.email_iaddress
puts "WARN: purging deleted mailbox #{u['alias']} since it collides with another mail_object"
u.delete
end
end
remove_column :email_users, :forward
remove_column :email_users, :ismailbox
remove_column :email_users, :isforward
remove_column :email_users, :alias
remove_column :email_users, :domain
remove_column :email_users, :deleted_at
ReservedEmail.all.each do |l|
local_part, domain = l['email'].split('@', 2)
d = EmailDomain.where(domain: domain).first
EmailIaddress.create!(local_part: local_part, email_domain: d, deleted_at: l['deleted_at'])
end
drop_table :reserved_emails
end
end
class CleanupEmailForward < ActiveRecord::Migration[5.2]
def up
# Needs to happen after all potential targets are added to the database
EmailForward.all.each do |f|
unless f.valid?
puts "WARN: prune invalid fwd #{f.email_iaddress.email} to #{f.target}"
f.delete
e = f.email_iaddress
if !e.email_object && e.email_forwards.empty?
e.destroy!
end
end
end
EmailAlias.all.each do |a|
uid = "mail_alias:#{a.email}@#{a.email_user.email}"
ResourceManager.by_uid(uid).add_owner(a.email_user)
end
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment