desc "Anonymize your database -- DON'T USE THIS UNLESS YOU REALLY, REALLY KNOW WHAT YOU'RE DOING. NOT KIDDING HERE!" $LOREM = " Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer in mi a mauris ornare sagittis. Suspendisse potenti. Suspendisse dapibus dignissim dolor. Nam sapien tellus, tempus et, tempus ac, tincidunt in, arcu. Duis dictum. Proin magna nulla, pellentesque non, commodo et, iaculis sit amet, mi. Mauris condimentum massa ut metus. Donec viverra, sapien mattis rutrum tristique, lacus eros semper tellus, et molestie nisi sapien eu massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce erat tortor, mollis ut, accumsan ut, lacinia gravida, libero. Curabitur massa felis, accumsan feugiat, convallis sit amet, porta vel, neque. Duis et ligula non elit ultricies rutrum. Suspendisse tempor. Quisque posuere malesuada velit. Sed pellentesque mi a purus. Integer imperdiet, orci a eleifend mollis, velit nulla iaculis arcu, eu rutrum magna quam sed elit. Nullam egestas. Integer interdum purus nec mauris. Vestibulum ac mi in nunc suscipit dapibus. Duis consectetuer, ipsum et pharetra sollicitudin, metus turpis facilisis magna, vitae dictum ligula nulla nec mi. Nunc ante urna, gravida sit amet, congue et, accumsan vitae, magna. Praesent luctus. Nullam in velit. Praesent est. Curabitur turpis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Cras consectetuer, nibh in lacinia ornare, turpis sem tempor massa, sagittis feugiat mauris nibh non tellus. Phasellus mi. Fusce enim. Mauris ultrices, turpis eu adipiscing viverra, justo libero ullamcorper massa, id ultrices velit est quis tortor. Quisque condimentum, lacus volutpat nonummy accumsan, est nunc imperdiet magna, vulputate aliquet nisi risus at est. Aliquam imperdiet gravida tortor. Praesent interdum accumsan ante. Vivamus est ligula, consequat sed, pulvinar eu, consequat vitae, eros. Nulla elit nunc, congue eget, scelerisque a, tempor ac, nisi. Morbi facilisis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst. Suspendisse vel lorem ut ligula tempor consequat. Quisque consectetuer nisl eget elit. Proin quis mauris ac orci accumsan suscipit. Sed ipsum. Sed vel libero nec elit feugiat blandit. Vestibulum purus nulla, accumsan et, volutpat at, pellentesque vel, urna. Suspendisse nonummy. Aliquam pulvinar libero. Donec vulputate, orci ornare bibendum condimentum, lorem elit dignissim sapien, ut aliquam nibh augue in turpis. Phasellus ac eros. Praesent luctus, lorem a mollis lacinia, leo turpis commodo sem, in lacinia mi quam et quam. Curabitur a libero vel tellus mattis imperdiet. In congue, neque ut scelerisque bibendum, libero lacus ullamcorper sapien, quis aliquet massa velit vel orci. Fusce in nulla quis est cursus gravida. In nibh. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer fermentum pretium massa. Morbi feugiat iaculis nunc. Aenean aliquam pretium orci. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus quis tellus vel quam varius bibendum. Fusce est metus, feugiat at, porttitor et, cursus quis, pede. Nam ut augue. Nulla posuere. Phasellus at dolor a enim cursus vestibulum. Duis id nisi. Duis semper tellus ac nulla. Vestibulum scelerisque lobortis dolor. Aenean a felis. Aliquam erat volutpat. Donec a magna vitae pede sagittis lacinia. Cras vestibulum diam ut arcu. Mauris a nunc. Duis sollicitudin erat sit amet turpis. Proin at libero eu diam lobortis fermentum. Nunc lorem turpis, imperdiet id, gravida eget, aliquet sed, purus. Ut vehicula laoreet ante. Mauris eu nunc. Sed sit amet elit nec ipsum aliquam egestas. Donec non nibh. Cras sodales pretium massa. Praesent hendrerit est et risus. Vivamus eget pede. Curabitur tristique scelerisque dui. Nullam ullamcorper. Vivamus venenatis velit eget enim. Nunc eu nunc eget felis malesuada fermentum. Quisque magna. Mauris ligula felis, luctus a, aliquet nec, vulputate eget, magna. Quisque placerat diam sed arcu. Praesent sollicitudin. Aliquam non sapien. Quisque id augue. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Etiam lacus lectus, mollis quis, mattis nec, commodo facilisis, nibh. Sed sodales sapien ac ante. Duis eget lectus in nibh lacinia auctor. Fusce interdum lectus non dui. Integer accumsan. Quisque quam. Curabitur scelerisque imperdiet nisl. Suspendisse potenti. Nam massa leo, iaculis sed, accumsan id, ultrices nec, velit. Suspendisse potenti. Mauris bibendum, turpis ac viverra sollicitudin, metus massa interdum orci, non imperdiet orci ante at ipsum. Etiam eget magna. Mauris at tortor eu lectus tempor tincidunt. Phasellus justo purus, pharetra ut, ultricies nec, consequat vel, nisi. Fusce vitae velit at libero sollicitudin sodales. Aenean mi libero, ultrices id, suscipit vitae, dapibus eu, metus. Aenean vestibulum nibh ac massa. Vivamus vestibulum libero vitae purus. In hac habitasse platea dictumst. Curabitur blandit nunc non arcu. Ut nec nibh. Morbi quis leo vel magna commodo rhoncus. Donec congue leo eu lacus. Pellentesque at erat id mi consequat congue. Praesent a nisl ut diam interdum molestie. Fusce suscipit rhoncus sem. Donec pretium. Aliquam molestie. Vivamus et justo at augue aliquet dapibus. Pellentesque felis. Morbi semper. In venenatis imperdiet neque. Donec auctor molestie augue. Nulla id arcu sit amet dui lacinia convallis. Proin tincidunt. Proin a ante. Nunc imperdiet augue. Nullam sit amet arcu. Quisque laoreet viverra felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In hac habitasse platea dictumst. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nullam nibh sapien, volutpat ut, placerat quis, ornare at, lorem. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Morbi dictum massa id libero. Ut neque. Phasellus tincidunt, nibh ut tincidunt lacinia, lacus nulla aliquam mi, a interdum dui augue non pede. Duis nunc magna, vulputate a, porta at, tincidunt a, nulla. Praesent facilisis. Suspendisse sodales feugiat purus. Cras et justo a mauris mollis imperdiet. Morbi erat mi, ultrices eget, aliquam elementum, iaculis id, velit. In scelerisque enim sit amet turpis. Sed aliquam, odio nonummy ullamcorper mollis, lacus nibh tempor dolor, sit amet varius sem neque ac dui. Nunc et est eu massa eleifend mollis. Mauris aliquet orci quis tellus. Ut mattis. Praesent mollis consectetuer quam. Nulla nulla. Nunc accumsan, nunc sit amet scelerisque porttitor, nibh pede lacinia justo, tristique mattis purus eros non velit. Aenean sagittis commodo erat. Aliquam id lacus. Morbi vulputate vestibulum elit." $LOREM = $LOREM.gsub(/\s+/, ' ') $LOREM = $LOREM.split(/[.]\s*/) def lorem(n) return $LOREM[rand($LOREM.size - 20)..-1].join('. ')[0, n] end $ALPHANUMERICS = [('0'..'9'),('A'..'Z'),('a'..'z')].map {|range| range.to_a}.flatten $RANDOM_CACHE = ((0... 100).map { $ALPHANUMERICS[rand($ALPHANUMERICS.size)] }.join) $PASSWORD = ((0... 8).map { $ALPHANUMERICS[rand($ALPHANUMERICS.size)] }.join) $UNIQUE = [ 'IssuePriority#name', 'ActsAsTaggableOn::Tag#name', 'Version#name', 'IssueStatus#name' ] $UNIQUE = {} def unique(model_attr) v = $UNIQUE[model_attr].to_i + 1 $UNIQUE[model_attr] = v v = "#{model_attr.split('#')[0]}#{v}" v << "@example.com" if model_attr.match(/#mail/) return v end def random_string(model_attr, v) return nil if !v return $PASSWORD if model_attr.match(/#password$/) # these are required to be unique return unique(model_attr) if $UNIQUE.include?(model_attr) || model_attr.match(/#mail$/) return lorem(v.size) if v.match(/ /) nv = nil l = v.size while nv.nil? start = rand($RANDOM_CACHE.size / 3) if $RANDOM_CACHE.size >= start + l nv = $RANDOM_CACHE[start, l] else $RANDOM_CACHE << ((0... (l * 3)).map { $ALPHANUMERICS[rand($ALPHANUMERICS.size)] }.join) end end return nv end namespace :redmine do namespace :backlogs do task :anonymize => :environment do puts "This will anonymize ALL YOUR DATA" puts "ARE YOU VERY, VERY SURE?" puts "If so, type 'Yes!' (case matters!)" answer = STDIN.gets.chomp return if answer != "Yes!" ignore = [ 'AnonymousUser#language', 'Version#status', 'Version#sharing', 'CustomField#regexp', 'CustomField#field_format', 'Principal#language', 'JournalDetail#property', 'JournalDetail#prop_key', 'Query#column_names', 'Query#group_by', 'Query#sort_criteria', 'Query#filters', 'Enumeration#name', 'WikiContent::Version#compression', 'User#language', 'AnonymousUser#login', ] admins = [] ActiveRecord::Base.send(:subclasses).each do |model| attrs = {} model.columns_hash.each_pair { |attrib, column| #next unless model.content_columns.include?(column) next if column.name == 'type' next if attrib.match(/_type$/) next if [:integer, :boolean, :datetime, :date, :float].include?(column.type) next if ignore.include?("#{model.name}##{attrib}") attrib = 'password' if attrib == 'hashed_password' attrs[attrib] = nil } if attrs.size != 0 puts "Anonymizing #{model.name} ..." model.all.each { |obj| save_error = nil 10.times do |attempt| attrs.each_pair {|k, v| attrs[k] = random_string("#{model.name}##{k}", obj.send(k)) } attempt_string = (attempt == 0 ? '' : " (attempt #{attempt + 1}") puts "... #{model.name} #{obj.id}#{attempt_string}" begin obj.update_attributes(attrs) obj.save! save_error = nil break rescue ActiveRecord::RecordInvalid => save_error end end raise "Not able to save #{model.name} #{obj.id}: #{save_error}" if save_error if model.name == 'User' && obj.admin? admins << obj.login end } end end User.find(:all).each { |user| user.password = $PASSWORD user.save! } puts "Your anonymized admins are #{admins.inspect} with password '#{$PASSWORD}'" end end end