An unofficial, mostly Bitwarden-compatible API server written in Ruby (Sinatra and ActiveRecord)
1# see https://github.com/jcs/rubywarden/blob/master/AR-MIGRATE.md
2
3require "fileutils"
4require "getoptlong"
5require "tempfile"
6require "yaml_db"
7
8def usage
9 puts "usage: #{$PROGRAM_NAME} -e development"
10 exit 1
11end
12
13environment = nil
14begin
15 GetoptLong.new(
16 ['--environment', '-e', GetoptLong::REQUIRED_ARGUMENT]
17 ).each do |opt, arg|
18 case opt
19 when '--environment'
20 environment = arg
21 end
22 end
23rescue GetoptLong::InvalidOption
24 usage
25end
26
27usage unless environment
28
29require File.realpath(File.dirname(__FILE__) + "/../lib/rubywarden.rb")
30
31ActiveRecord::Base.remove_connection
32
33dbconfig = YAML.load(File.read(File.realpath(__dir__ + "/../db/config.yml")))
34
35# if a file exists at the new path, some kind of migration has already been
36# done so bail out
37newdb = dbconfig[environment]["database"]
38if File.exists?(newdb)
39 raise "a file already exists at #{newdb}, has a migration already taken place?"
40end
41
42olddb = File.realpath(__dir__ + "/../db/production.sqlite3")
43if !olddb || !File.exists?(olddb)
44 raise "no file at #{olddb} to migrate"
45end
46
47# point a temporary config at the old db path so we can dump it
48tmpconfig = dbconfig[environment].dup
49tmpconfig["database"] = olddb
50ActiveRecord::Base.establish_connection tmpconfig
51
52# select only tables for defined models
53class YamlDb::SerializationHelper::Dump
54 def self.tables
55 ObjectSpace.each_object(Class).select{|k| k < DBModel}.map{|k| k.table_name }
56 end
57end
58
59dump_file = Tempfile.new("rubywarden-migrate")
60
61puts "dumping old database to #{dump_file.path}"
62YamlDb::SerializationHelper::Base.new(YamlDb::Helper).dump(dump_file.path)
63ActiveRecord::Base.remove_connection
64
65puts "creating new database at #{dbconfig[environment]["database"]}"
66system("rake", "db:migrate", "RUBYWARDEN_ENV=#{environment}")
67
68puts "importing old database dump"
69ActiveRecord::Base.establish_connection dbconfig[environment]
70YamlDb::SerializationHelper::Base.new(YamlDb::Helper).load(dump_file.path)
71
72puts "deleting dump file"
73dump_file.unlink
74
75# reset created_at / updated_at from seconds since epoch to actual datetime for ar magic
76DBModel.record_timestamps = false
77ObjectSpace.each_object(Class).select {|k| k < DBModel}.each do |k|
78 k.all.each do |i|
79 i.update created_at: Time.at(i.created_at), updated_at: Time.at(i.updated_at)
80 end
81end
82DBModel.record_timestamps = true
83
84newdb = File.realpath(__dir__ + "/../" + dbconfig[environment]["database"])
85puts "you may wish to delete the old database at #{newdb}"
86
87puts "you may also wish to create a new, unprivileged user to run the"
88puts "rubywarden server and own the db/production/ directory"