diff --git a/Gemfile b/Gemfile index 4e8b65d551c76c0192648df98be9f5bb12e0c957..d71163d15932ca9ff2bcee3a681a8066db64ddf2 100644 --- a/Gemfile +++ b/Gemfile @@ -31,7 +31,6 @@ gem 'http_accept_language', :git => 'git://github.com/iain/http_accept_language. #Standards gem 'pubsubhubbub' -gem 'redfinger', :git => 'git://github.com/rsofaer/redfinger.git' #EventMachine gem 'em-http-request',:ref => 'bf62d67fc72d6e701be5', :git => 'git://github.com/igrigorik/em-http-request.git', :require => 'em-http' diff --git a/Gemfile.lock b/Gemfile.lock index 5c6398084f09a4e8a3bd19ab3f84c627df0944f2..8f731c8616de6798ce8eb11d676e09f88e226eb4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -55,15 +55,6 @@ GIT carrierwave (0.5.0) activesupport (~> 3.0) -GIT - remote: git://github.com/rsofaer/redfinger.git - revision: 07721f46d02b9d3aa04880788fecb0b4c1b284d7 - specs: - redfinger (0.0.6) - hashie - nokogiri (>= 1.4.0) - rest-client (>= 1.5.0) - GIT remote: git://github.com/rsofaer/sprinkle.git revision: 7c744ed158dda1f99a015e6a29d086e80bd8c635 @@ -115,6 +106,7 @@ GEM activesupport (= 3.0.1) activesupport (3.0.1) addressable (2.2.2) + archive-tar-minitar (0.5.2) arel (1.0.1) activesupport (~> 3.0.0) aws (2.3.24) @@ -140,7 +132,6 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) selenium-webdriver (>= 0.0.3) - cgi_multipart_eof_fix (2.5.0) chef (0.9.12) bunny (>= 0.6.0) erubis @@ -192,10 +183,8 @@ GEM addressable (~> 2.2.2) multipart-post (~> 1.0.1) rack (>= 1.1.0, < 2) - fastthread (1.0.7) ffi (0.6.3) rake (>= 0.8.7) - gem_plugin (0.2.3) gherkin (2.2.9) json (~> 1.4.6) term-ansicolor (~> 1.0.5) @@ -211,7 +200,8 @@ GEM launchy (0.3.7) configuration (>= 0.0.5) rake (>= 0.8.1) - linecache (0.43) + linecache19 (0.5.11) + ruby_core_source (>= 0.1.4) mail (2.2.9) activesupport (>= 2.3.6) i18n (~> 0.4.1) @@ -233,11 +223,6 @@ GEM moneta (0.6.0) mongo (1.1) bson (>= 1.0.5) - mongrel (1.1.5) - cgi_multipart_eof_fix (>= 2.4) - daemons (>= 1.0.3) - fastthread (>= 1.0.1) - gem_plugin (>= 0.2.3) multi_json (0.0.4) multipart-post (1.0.1) net-ldap (0.1.1) @@ -332,14 +317,19 @@ GEM rspec-expectations (~> 2.0.1) rspec-rails (2.0.1) rspec (~> 2.0.0) - ruby-debug (0.10.3) - columnize (>= 0.1) - ruby-debug-base (~> 0.10.3.0) - ruby-debug-base (0.10.3) - linecache (>= 0.3) + ruby-debug-base19 (0.11.24) + columnize (>= 0.3.1) + linecache19 (>= 0.5.11) + ruby_core_source (>= 0.1.4) + ruby-debug19 (0.11.6) + columnize (>= 0.3.1) + linecache19 (>= 0.5.11) + ruby-debug-base19 (>= 0.11.19) ruby-openid (2.1.8) ruby-openid-apps-discovery (1.2.0) ruby-openid (>= 2.1.7) + ruby_core_source (0.1.4) + archive-tar-minitar (>= 0.5.2) rubyntlm (0.1.1) rubyzip (0.9.4) selenium-client (1.2.18) @@ -405,15 +395,13 @@ DEPENDENCIES mini_magick mocha mongo_mapper! - mongrel omniauth pubsubhubbub rails (>= 3.0.0) - redfinger! roxml! rspec (>= 2.0.0) rspec-rails (>= 2.0.0) - ruby-debug + ruby-debug19 sprinkle! thin twitter diff --git a/app/controllers/albums_controller.rb b/app/controllers/albums_controller.rb index a74143363115c1c03a4cb1039ad70153eb94a4da..1474b5c0f56f83ba4a72503d98818d8a514a3659 100644 --- a/app/controllers/albums_controller.rb +++ b/app/controllers/albums_controller.rb @@ -17,8 +17,13 @@ class AlbumsController < ApplicationController aspect = params[:album][:to] @album = current_user.post(:album, params[:album]) - flash[:notice] = I18n.t 'albums.create.success', :name => @album.name - redirect_to :action => :show, :id => @album.id, :aspect => aspect + if @album.persisted? + flash[:notice] = I18n.t 'albums.create.success', :name => @album.name + redirect_to :action => :show, :id => @album.id, :aspect => aspect + else + flash[:error] = I18n.t 'albums.create.failure' + redirect_to albums_path(:aspect => aspect) + end end def new diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index ea56ed81b4f6ba571c370c631d6e8174505b9935..9280e2d3eeecce2e682dd323e8a72afa3a945b5c 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -56,6 +56,7 @@ class PeopleController < ApplicationController end # upload and set new profile photo + params[:person][:profile] ||= {} if params[:person][:profile][:image].present? raw_image = params[:person][:profile].delete(:image) params[:profile_image_hash] = { :user_file => raw_image, :to => "all" } diff --git a/app/controllers/publics_controller.rb b/app/controllers/publics_controller.rb index ae00cc7df6b7b400d6deebfe11df6076826280e6..a5dd347e5d1ddbb8fd507fdbe398c22c4e9d7ecc 100644 --- a/app/controllers/publics_controller.rb +++ b/app/controllers/publics_controller.rb @@ -11,7 +11,7 @@ class PublicsController < ApplicationController def hcard @person = Person.find_by_id params[:id] unless @person.nil? || @person.owner.nil? - render 'hcard' + render 'publics/hcard' else render :nothing => true, :status => 404 end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index b5e11f86a34a05b4774354010526858e74f5b140..a96438dc21b2fefbdf97cfb6bfbb11ef71da5c3a 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -5,11 +5,9 @@ class UsersController < ApplicationController require File.join(Rails.root, 'lib/diaspora/ostatus_builder') require File.join(Rails.root, 'lib/diaspora/exporter') - require File.join(Rails.root, 'lib/diaspora/importer') require File.join(Rails.root, 'lib/collect_user_photos') - - before_filter :authenticate_user!, :except => [:new, :create, :public, :import] + before_filter :authenticate_user!, :except => [:new, :create, :public] respond_to :html @@ -101,23 +99,4 @@ class UsersController < ApplicationController User.invite!(:email => params[:email]) end - - def import - xml = params[:upload][:file].read - - begin - importer = Diaspora::Importer.new(Diaspora::Parsers::XML) - importer.execute(xml, params[:user]) - flash[:notice] = "hang on a sec, try logging in!" - - rescue Exception => e - flash[:error] = "Something went wrong: #{e.message}" - end - - redirect_to new_user_registration_path - #redirect_to user_session_path - end - - - end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 0060f015606103adc0a9f10fdfe242710cd35416..ba0a57a950f44600f7b255bc2a8f963fcc8a62e2 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -3,6 +3,8 @@ # the COPYRIGHT file. module ApplicationHelper + @@youtube_title_cache = Hash.new("no-title") + def current_aspect?(aspect) !@aspect.is_a?(Symbol) && @aspect.id == aspect.id end @@ -85,4 +87,86 @@ module ApplicationHelper "#{photos_path}?person_id=#{person_id}" end + + def markdownify(message, options = {}) + message = h(message).html_safe + + [:autolinks, :youtube, :emphasis, :links].each do |k| + if !options.has_key?(k) + options[k] = true + end + end + + if options[:links] + message.gsub!(/\[([^\[]+)\]\(([^ ]+) \"(([^&]|(&[^q])|(&q[^u])|(&qu[^o])|(&quo[^t])|("[^;]))+)\"\)/) do |m| + escape = (options[:emphasis]) ? "\\" : "" + res = "<a target=\"#{escape}_blank\" href=\"#{$2}\" title=\"#{$3}\">#{$1}</a>" + res + end + message.gsub!(/\[([^\[]+)\]\(([^ ]+)\)/) do |m| + escape = (options[:emphasis]) ? "\\" : "" + res = "<a target=\"#{escape}_blank\" href=\"#{$2}\">#{$1}</a>" + res + end + end + + if options[:youtube] + message.gsub!(/( |^)(http:\/\/)?www\.youtube\.com\/watch[^ ]*v=([A-Za-z0-9_]+)(&[^ ]*|)/) do |m| + res = "#{$1}youtube.com::#{$3}" + res.gsub!(/(\*|_)/) { |m| "\\#{$1}" } if options[:emphasis] + res + end + end + + if options[:autolinks] + message.gsub!(/( |^)(www\.[^ ]+\.[^ ])/, '\1http://\2') + message.gsub!(/(<a target="\\?_blank" href=")?(https|http|ftp):\/\/([^ ]+)/) do |m| + if !$1.nil? + m + else + res = %{<a target="_blank" href="#{$2}://#{$3}">#{$3}</a>} + res.gsub!(/(\*|_)/) { |m| "\\#{$1}" } if options[:emphasis] + res + end + end + end + + if options[:emphasis] + message.gsub!(/([^\\]|^)\*\*(([^*]|([^*]\*[^*]))*[^*\\])\*\*/, '\1<strong>\2</strong>') + message.gsub!(/([^\\]|^)__(([^_]|([^_]_[^_]))*[^_\\])__/, '\1<strong>\2</strong>') + message.gsub!(/([^\\]|^)\*([^*]*[^\\])\*/, '\1<em>\2</em>') + message.gsub!(/([^\\]|^)_([^_]*[^\\])_/, '\1<em>\2</em>') + message.gsub!(/([^\\]|^)\*/, '\1') + message.gsub!(/([^\\]|^)_/, '\1') + message.gsub!("\\*", "*") + message.gsub!("\\_", "_") + end + + if options[:youtube] + while youtube = message.match(/youtube\.com::([A-Za-z0-9_\\]+)/) + videoid = youtube[1] + message.gsub!('youtube.com::'+videoid, '<a onclick="openVideo(\'youtube.com\', \'' + videoid + '\', this)" href="#video">Youtube: ' + youtube_title(videoid) + '</a>') + end + end + + return message + end + + def youtube_title(id) + unless @@youtube_title_cache[id] == 'no-title' + return @@youtube_title_cache[id] + end + + ret = 'Unknown Video Title' #TODO add translation + http = Net::HTTP.new('gdata.youtube.com', 80) + path = '/feeds/api/videos/'+id+'?v=2' + resp, data = http.get(path, nil) + title = data.match(/<title>(.*)<\/title>/) + unless title.nil? + ret = title.to_s[7..-9] + end + + @@youtube_title_cache[id] = ret; + return ret + end end diff --git a/app/helpers/status_messages_helper.rb b/app/helpers/status_messages_helper.rb index 2e010715aaf99ce410f6b860128bfee95b57eb99..2dfbd31cccebfd08c4da3d55f9ba55c480fca28f 100644 --- a/app/helpers/status_messages_helper.rb +++ b/app/helpers/status_messages_helper.rb @@ -3,8 +3,6 @@ # the COPYRIGHT file. module StatusMessagesHelper - @@youtube_title_cache = Hash.new("no-title") - def my_latest_message unless @latest_status_message.nil? return @latest_status_message.message @@ -12,39 +10,4 @@ module StatusMessagesHelper return I18n.t('status_messages.helper.no_message_to_display') end end - - def make_links(message) - # If there should be some kind of bb-style markup, email/diaspora highlighting, it could go here. - - # next line is important due to XSS! (h is rail's make_html_safe-function) - message = h(message).html_safe - message.gsub!(/( |^)(www\.[^ ]+\.[^ ])/, '\1http://\2') - message.gsub!(/( |^)http:\/\/www\.youtube\.com\/watch[^ ]*v=([A-Za-z0-9_]+)(&[^ ]*|)/, '\1youtube.com::\2') - message.gsub!(/(https|http|ftp):\/\/([^ ]+)/, '<a target="_blank" href="\1://\2">\2</a>') - - while youtube = message.match(/youtube\.com::([A-Za-z0-9_]+)/) - videoid = youtube[1] - message.gsub!('youtube.com::'+videoid, '<a onclick="openVideo(\'youtube.com\', \'' + videoid + '\', this)" href="#video">Youtube: ' + youtube_title(videoid) + '</a>') - end - return message - end - - def youtube_title(id) - unless @@youtube_title_cache[id] == 'no-title' - return @@youtube_title_cache[id] - end - - ret = 'Unknown Video Title' #TODO add translation - http = Net::HTTP.new('gdata.youtube.com', 80) - path = '/feeds/api/videos/'+id+'?v=2' - resp, data = http.get(path, nil) - title = data.match(/<title>(.*)<\/title>/) - unless title.nil? - ret = title.to_s[7..-9] - end - - @@youtube_title_cache[id] = ret; - return ret - end - end diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb index c0626f387cbab6c94e0142da2ad0451cf1b4b414..36047d0593277c4b173bbe0b31aba645f44dabd3 100644 --- a/app/mailers/notifier.rb +++ b/app/mailers/notifier.rb @@ -2,12 +2,12 @@ class Notifier < ActionMailer::Base include Magent::Async default :from => "no-reply@joindiaspora.com" - ATTACHMENT = File.read("#{Rails.root}/public/images/diaspora_caps.png") + ATTACHMENT = File.read("#{Rails.root}/public/images/diaspora_white_on_grey.png") def new_request(recipient, sender) @receiver = recipient @sender = sender - attachments["diaspora_white.png"] = ATTACHMENT + attachments.inline['diaspora_white_on_grey.png'] = ATTACHMENT mail(:to => "#{recipient.real_name} <#{recipient.email}>", :subject => "new Diaspora* friend request from #{@sender.real_name}", :host => APP_CONFIG[:terse_pod_url]) @@ -17,7 +17,8 @@ class Notifier < ActionMailer::Base @receiver = recipient @sender = sender @aspect = aspect - attachments["diaspora_white.png"] = ATTACHMENT + attachments.inline['diaspora_white_on_grey.png'] = ATTACHMENT + mail(:to => "#{recipient.real_name} <#{recipient.email}>", :subject => "#{@sender.real_name} has accepted your friend request on Diaspora*", :host => APP_CONFIG[:terse_pod_url]) end diff --git a/app/models/album.rb b/app/models/album.rb index fbc64b2cf33673056097bf7ab89b1f66a2e4bb1b..9be93701ca0d707de643c5ded7db0b6973dc7ffd 100644 --- a/app/models/album.rb +++ b/app/models/album.rb @@ -32,6 +32,10 @@ class Album < Post p_photo ? p_photo : self.photos.sort(:created_at.desc).last end + def mutable? + true + end + protected def destroy_photos self.photos.each{|p| p.destroy} diff --git a/app/models/contact.rb b/app/models/contact.rb index 9ae22357933f7b50f21c4c5463b4e42345fd7950..5aef552926cb836b40b660d2b1139e7f82bb140e 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -4,8 +4,7 @@ class Contact include MongoMapper::Document - attr_accessor :aspect_names #this is only used in the importer - + belongs_to :user validates_presence_of :user diff --git a/app/models/person.rb b/app/models/person.rb index 53f9b3afefa59c3faa3fd7b8a6cc722d6f232db3..f99908eacae2c8885cfdc561f7d4c0f30f905a57 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -43,8 +43,10 @@ class Person ensure_index :diaspora_handle + scope :searchable, where('profile.searchable' => true) + def self.search(query) - return Person.all if query.to_s.empty? + return Person.searchable.all if query.to_s.empty? query_tokens = query.to_s.strip.split(" ") full_query_text = Regexp.escape(query.to_s.strip) @@ -52,8 +54,9 @@ class Person query_tokens.each do |token| q = Regexp.escape(token.to_s.strip) - p = Person.all('profile.first_name' => /^#{q}/i) \ - | Person.all('profile.last_name' => /^#{q}/i) \ + p = Person.searchable.all('profile.first_name' => /^#{q}/i) \ + | Person.searchable.all('profile.last_name' => /^#{q}/i) \ + | Person.searchable.all('diaspora_handle' => /^#{q}/i) \ | p end @@ -120,7 +123,10 @@ class Person #hcard_profile = HCard.find profile.hcard.first[:href] Rails.logger.info("hcard: #{ hcard.inspect}") new_person.url = hcard[:url] - new_person.profile = Profile.new(:first_name => hcard[:given_name], :last_name => hcard[:family_name], :image_url => hcard[:photo]) + new_person.profile = Profile.new( :first_name => hcard[:given_name], + :last_name => hcard[:family_name], + :image_url => hcard[:photo], + :searchable => hcard[:searchable]) new_person.save! ? new_person : nil end diff --git a/app/models/photo.rb b/app/models/photo.rb index bce9d469da3206e0c4b2efa7fe4c66cacfe8a087..6c96e425cebcbec153c1ac1ae8b7c8e81769c037 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -38,6 +38,7 @@ class Photo < Post person = params.delete(:person) photo = Photo.new(params) + photo.diaspora_handle = params[:diaspora_handle] photo.image.store! image_file photo.person = person @@ -74,5 +75,9 @@ class Photo < Post def thumb_hash {:thumb_url => url(:thumb_medium), :id => id, :album_id => album_id} end + + def mutable? + true + end end diff --git a/app/models/post.rb b/app/models/post.rb index 298d25b5fcb8051f341bcd4d13f9678649aaa489..842af2b2e194fa0904dc3b992f9cf3cd87dc3022 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -50,6 +50,10 @@ class Post } end + def mutable? + false + end + protected def destroy_comments comments.each{|c| c.destroy} diff --git a/app/models/profile.rb b/app/models/profile.rb index d69c64e1253674d0840145f414d4e4f120bd4b1b..b8383de176c5a776f0faac7f432e52cc3e27019d 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -8,25 +8,27 @@ class Profile include Diaspora::Webhooks include ROXML + xml_reader :diaspora_handle xml_reader :first_name xml_reader :last_name xml_reader :image_url xml_reader :birthday xml_reader :gender xml_reader :bio - xml_accessor :diaspora_handle + xml_reader :searchable + key :diaspora_handle, String key :first_name, String key :last_name, String key :image_url, String key :birthday, Date key :gender, String key :bio, String - key :diaspora_handle, String + key :searchable, Boolean, :default => true after_validation :strip_names validates_length_of :first_name, :maximum => 32 - validates_length_of :last_name, :maximum => 32 + validates_length_of :last_name, :maximum => 32 before_save :strip_names diff --git a/app/models/user.rb b/app/models/user.rb index bb465e78ae560b81dca10077fe40978228a7342a..516a6cc71e391fb2fae7751c707ae72eb9b482a4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -22,11 +22,11 @@ class User key :invites, Integer, :default => 5 key :invitation_token, String key :invitation_sent_at, DateTime - key :inviter_ids, Array, :typecast => 'ObjectId' - key :friend_ids, Array, :typecast => 'ObjectId' - key :pending_request_ids, Array, :typecast => 'ObjectId' - key :visible_post_ids, Array, :typecast => 'ObjectId' - key :visible_person_ids, Array, :typecast => 'ObjectId' + key :inviter_ids, Array, :typecast => 'ObjectId' + key :friend_ids, Array, :typecast => 'ObjectId' + key :pending_request_ids, Array, :typecast => 'ObjectId' + key :visible_post_ids, Array, :typecast => 'ObjectId' + key :visible_person_ids, Array, :typecast => 'ObjectId' key :invite_messages, Hash @@ -39,9 +39,8 @@ class User validates_presence_of :username validates_uniqueness_of :username, :case_sensitive => false - validates_format_of :username, :with => /\A[A-Za-z0-9_.]+\z/ + validates_format_of :username, :with => /\A[A-Za-z0-9_.]+\z/ validates_length_of :username, :maximum => 32 - validates_inclusion_of :language, :in => AVAILABLE_LANGUAGE_CODES validates_presence_of :person, :unless => proc {|user| user.invitation_token.present?} @@ -61,6 +60,11 @@ class User #after_create :seed_aspects before_destroy :unfriend_everyone, :remove_person + before_save do + person.save if person + end + + attr_accessible :getting_started, :password, :password_confirmation, :language, def strip_and_downcase_username if username.present? @@ -98,11 +102,11 @@ class User def move_friend(opts = {}) return true if opts[:to] == opts[:from] - if opts[:friend_id] && opts[:to] && opts[:from] + if opts[:friend_id] && opts[:to] && opts[:from] from_aspect = self.aspects.first(:_id => opts[:from]) posts_to_move = from_aspect.posts.find_all_by_person_id(opts[:friend_id]) if add_person_to_aspect(opts[:friend_id], opts[:to], :posts => posts_to_move) - delete_person_from_aspect(opts[:friend_id], opts[:from], :posts => posts_to_move) + delete_person_from_aspect(opts[:friend_id], opts[:from], :posts => posts_to_move) return true end end @@ -116,7 +120,7 @@ class User raise 'Can not add person who is already in the aspect' if aspect.people.include?(contact) contact.aspects << aspect opts[:posts] ||= self.raw_visible_posts.all(:person_id => person_id) - + aspect.posts += opts[:posts] contact.save aspect.save @@ -146,15 +150,16 @@ class User post = build_post(class_name, options) - post.socket_to_uid(id, :aspect_ids => aspect_ids) if post.respond_to?(:socket_to_uid) - push_to_aspects(post, aspect_ids) - - if options[:public] == true - self.services.each do |service| - self.send("post_to_#{service.provider}".to_sym, service, post.message) + if post.persisted? + Rails.logger.info("Pushing: #{post.inspect} out to aspects") + push_to_aspects(post, aspect_ids) + post.socket_to_uid(id, :aspect_ids => aspect_ids) if post.respond_to?(:socket_to_uid) + if options[:public] == true + self.services.each do |service| + self.send("post_to_#{service.provider}".to_sym, service, post.message) + end end end - post end @@ -324,14 +329,14 @@ class User raise "Must invite to your aspect" else u = User.find_by_email(opts[:email]) - if u.nil? + if u.nil? elsif friends.include?(u.person) - raise "You are already friends with this person" + raise "You are already friends with this person" elsif not u.invited? self.send_friend_request_to(u.person, aspect_object) return elsif u.invited? && u.inviters.include?(self) - raise "You already invited this person" + raise "You already invited this person" end end request = Request.instantiate( @@ -402,16 +407,22 @@ class User ###Helpers############ def self.build(opts = {}) + u = User.new(opts) + + u.username = opts[:username] + u.email = opts[:email] + opts[:person] ||= {} opts[:person][:profile] ||= Profile.new - opts[:person][:diaspora_handle] = "#{opts[:username]}@#{APP_CONFIG[:terse_pod_url]}" - opts[:person][:url] = APP_CONFIG[:pod_url] + u.person = Person.new(opts[:person]) + u.person.diaspora_handle = "#{opts[:username]}@#{APP_CONFIG[:terse_pod_url]}" - opts[:serialized_private_key] = generate_key - opts[:person][:serialized_public_key] = opts[:serialized_private_key].public_key + u.person.url = APP_CONFIG[:pod_url] + new_key = generate_key + u.serialized_private_key = new_key + u.person.serialized_public_key = new_key.public_key - u = User.new(opts) u end @@ -420,10 +431,6 @@ class User self.aspects.create(:name => "Work") end - def diaspora_handle - person.diaspora_handle - end - def as_json(opts={}) { :user => { @@ -437,7 +444,8 @@ class User def self.generate_key - OpenSSL::PKey::RSA::generate 4096 + key_size = (Rails.env == 'test' ? 512 : 4096) + OpenSSL::PKey::RSA::generate key_size end def encryption_key diff --git a/app/views/js/_websocket_js.haml b/app/views/js/_websocket_js.haml index ec9854bb69e29f1d501c2b94b79dd01ae05d25d0..33fb0e97189c7ac1fbe9101220af926f81c2d14c 100644 --- a/app/views/js/_websocket_js.haml +++ b/app/views/js/_websocket_js.haml @@ -8,7 +8,7 @@ $(document).ready(function(){ function debug(str){ $("#debug").append("<p>" + str); }; - ws = new WebSocket("ws://#{request.host}:#{APP_CONFIG[:socket_port]}/#{CGI::escape(current_user.id.to_s)}"); + ws = new WebSocket("ws://#{request.host}:#{APP_CONFIG[:socket_port]}/"); //Attach onmessage to websocket ws.onmessage = function(evt) { diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 70f610ebc62d44bee0cd96065de3f1e9f44b83f5..5fc9f3b51fa821db1c08d35f29ed4a191339b2cd 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -3,7 +3,7 @@ -# the COPYRIGHT file. !!! -%html +%html{:lang => I18n.locale.to_s} %head %title = "#{current_user.real_name} | diaspora" if current_user @@ -43,7 +43,7 @@ %header .container{:style => "position:relative;"} - #diaspora_text{:href => root_path} + #diaspora_text = link_to "DIASPORA", (current_user ? root_path : new_user_session_path) %span.sub_text PREVIEW diff --git a/app/views/notifier/new_request.html.haml b/app/views/notifier/new_request.html.haml index 66bb56f1a162a998de7c1c02f970c103d157b984..1a994695a1917ea455dd33eab793685dd4f1e204 100644 --- a/app/views/notifier/new_request.html.haml +++ b/app/views/notifier/new_request.html.haml @@ -43,7 +43,7 @@ } %body %header - = image_tag 'diaspora_white.png' + = image_tag attachments['diaspora_white_on_grey.png'].url, :alt => "DIASPORA" #container %p Hello #{@receiver.profile.first_name}! diff --git a/app/views/notifier/request_accepted.html.haml b/app/views/notifier/request_accepted.html.haml index 191f8f42ce292af096106632686c0af541c474a7..15ca54647ce81d11f13cc89680afa0df63b96361 100644 --- a/app/views/notifier/request_accepted.html.haml +++ b/app/views/notifier/request_accepted.html.haml @@ -43,7 +43,7 @@ } %body %header - = image_tag 'diaspora_white.png' + = image_tag attachments['diaspora_white_on_grey.png'].url, :alt => "DIASPORA" #container %p Hello #{@receiver.profile.first_name}! diff --git a/app/views/people/edit.html.haml b/app/views/people/edit.html.haml index d3b8b135d157e8432d9b7073863de6ec696b570d..79440c94e115a2d554365c954379afd19167b3cd 100644 --- a/app/views/people/edit.html.haml +++ b/app/views/people/edit.html.haml @@ -44,6 +44,12 @@ = t('.your_photo') = render 'people/profile_photo_upload', :form => profile + %h4 + Search + %p{:class=>"checkbox_select"} + = profile.label :searchable, "Allow for people to search for you" + = profile.check_box :searchable, {:checked => @person.profile.searchable}, true, false + .submit_block = link_to t('cancel'), edit_user_path(current_user) = t('or') diff --git a/app/views/publics/hcard.erb b/app/views/publics/hcard.erb deleted file mode 100644 index c02d909b5d05163d05093c76472ad122d4a24925..0000000000000000000000000000000000000000 --- a/app/views/publics/hcard.erb +++ /dev/null @@ -1,44 +0,0 @@ -<div id="content"> - <h1><%=@person.real_name%></h1> - <div id="content_inner"> - <div id="i" class="entity_profile vcard author"> - <h2>User profile</h2> - <dl class="entity_nickname"> - <dt>Nickname</dt> - <dd> - <a href="<%=@person.url%>" rel="me" class="nickname url uid"><%= @person.real_name%></a> - </dd> - </dl> - <dl class="entity_given_name"> - <dt>First name</dt> - <dd> - <span class="given_name" ><%= @person.profile.first_name %></span> - </dd> - </dl> - <dl class="entity_family_name"> - <dt>Family name</dt> - <dd> - <span class="family_name" ><%= @person.profile.last_name %></span> - </dd> - </dl> - <dl class="entity_fn"> - <dt>Full name</dt> - <dd> - <span class="fn" ><%= @person.real_name %></span> - </dd> - </dl> - <dl class="entity_url"> - <dt>URL</dt> - <dd> - <a href="<%= @person.url%>" rel="me" id="pod_location" class="url"><%= @person.url%></a> - </dd> - </dl> - <dl class="entity_photo"> - <dt>Photo</dt> - <dd> - <img class="photo avatar" src="<%= image_or_default(@person)%>" width="100" height="100"/> - </dd> - </dl> - </div> - </div> -</div> diff --git a/app/views/publics/hcard.haml b/app/views/publics/hcard.haml new file mode 100644 index 0000000000000000000000000000000000000000..8692869640f7d795db2c6daccedb176899968cec --- /dev/null +++ b/app/views/publics/hcard.haml @@ -0,0 +1,40 @@ +#content + %h1= @person.real_name + #content_inner + #i.entity_profile.vcard.author + %h2 User profile + + %dl.entity_nickname + %dt Nickname + %dd + %a.nickname.url.uid{:href=>@person.url, :rel=>'me'}= @person.real_name + + %dl.entity_given_name + %dt First name + %dd + %span.given_name= @person.profile.first_name + + %dl.entity_family_name + %dt Family name + %dd + %span.family_name= @person.profile.last_name + + %dl.entity_fn + %dt Full name + %dd + %span.fn= @person.real_name + + %dl.entity_url + %dt URL + %dd + %a#pod_location.url{:href=>@person.url, :rel=>'me'}= @person.url + + %dl.entity_photo + %dt Photo + %dd + %img.photo.avatar{:src=>image_or_default(@person), :width=>'100px', :height=>'100px'} + + %dl.entity_searchable + %dt Searchable + %dd + %span.searchable= @person.profile.searchable diff --git a/app/views/registrations/new.html.haml b/app/views/registrations/new.html.haml index 41423e55e79275ccb9936a3ae7ea2682107a3f42..f6cd28981f591c4586ef291495cca9dda963dc4e 100644 --- a/app/views/registrations/new.html.haml +++ b/app/views/registrations/new.html.haml @@ -19,24 +19,3 @@ = f.submit t('.sign_up') - - .floating - %h3 - = t('.upload_existing_account') - - = form_tag '/users/import', :multipart => true do - - %p - = label_tag 'user[email]' - = text_field_tag 'user[email]' - %p - = label_tag 'user[password]' - = password_field_tag 'user[password]' - %p - = label_tag 'user[password_confirmation]' - = password_field_tag 'user[password_confirmation]' - - %label Select File - = file_field 'upload', 'file' - = submit_tag t('.upload') - diff --git a/app/views/requests/_new_request.haml b/app/views/requests/_new_request.haml index 05ce611882197b882c25a67adfc49c19c733e421..b4d7c25bd68658ca1dde653fec9d4a8e4be87fa5 100644 --- a/app/views/requests/_new_request.haml +++ b/app/views/requests/_new_request.haml @@ -10,7 +10,7 @@ = render 'shared/add_friend_dropdown', :aspect => aspect, :friends => current_user.friends_not_in_aspect(aspect), :manage => defined?(manage) - = form_for Request.new do |fr_request| + = form_for(Request.new, :html => {:id => "new_request_to_#{aspect.id}"}) do |fr_request| = fr_request.error_messages =t('.enter_a_diaspora_username') @@ -18,8 +18,8 @@ %i= t '.your_diaspora_username_is', :diaspora_handle => current_user.diaspora_handle %p - = fr_request.label :destination_url, t('.friends_username') - = fr_request.text_field :destination_url + = fr_request.label :destination_url, t('.friends_username'), :for => "request_d_url_to_#{aspect.id}" + = fr_request.text_field :destination_url, :id => "request_d_url_to_#{aspect.id}" = fr_request.hidden_field :aspect_id, :value => aspect.id - if defined?(getting_started) diff --git a/app/views/shared/_add_friend_dropdown.html.haml b/app/views/shared/_add_friend_dropdown.html.haml index 062f534b8f32973e3c89e01998eec73304012e34..f324b988ce43b0b17ba9940be497fed6439fee09 100644 --- a/app/views/shared/_add_friend_dropdown.html.haml +++ b/app/views/shared/_add_friend_dropdown.html.haml @@ -1,5 +1,5 @@ -= form_tag '/aspects/add_to_aspect', :id => 'add_to_aspect' do += form_tag '/aspects/add_to_aspect', :id => "add_to_aspect_#{aspect.id}" do = select_tag :friend_id, options_from_collection_for_select(friends, "id", "real_name"), :include_blank => true = hidden_field_tag :aspect_id, aspect.id - if defined?(manage) && manage diff --git a/app/views/shared/_publisher.haml b/app/views/shared/_publisher.haml index 94f7737d79acce40ff08224b28121269dfb37da9..c2ced4804cbaf414b977d71c65d8da3332780e0b 100644 --- a/app/views/shared/_publisher.haml +++ b/app/views/shared/_publisher.haml @@ -32,6 +32,11 @@ = status.hidden_field :to, :value => (aspect == :all ? aspect : aspect.id) .options_and_submit + - if aspect == :all + = status.submit t('.share'), :title => "Share with all aspects" + - else + = status.submit t('.share'), :title => "Share with #{aspect}" + - if aspect == :all .public_toggle = status.check_box( :public, {}, true, false ) @@ -42,10 +47,6 @@ #question_mark_pane = render 'shared/public_explain' - - if aspect == :all - = status.submit t('.share'), :title => "Share with all aspects" - - else - = status.submit t('.share'), :title => "Share with #{aspect}" #publisher_photo_upload = t('or') diff --git a/app/views/status_messages/_status_message.html.haml b/app/views/status_messages/_status_message.html.haml index f78f4d40574fbe98e4840b0198ee9cb82800e696..19f0b1bd3791c612d2f09f294f0f89db5ac402c6 100644 --- a/app/views/status_messages/_status_message.html.haml +++ b/app/views/status_messages/_status_message.html.haml @@ -23,7 +23,7 @@ = render "shared/reshare", :post => post, :current_user => current_user = link_to t('delete'), status_message_path(post), :confirm => t('are_you_sure'), :method => :delete, :remote => true, :class => "delete" - = make_links(post.message) + = markdownify(post.message) .info %span.time= link_to(how_long_ago(post), object_path(post)) diff --git a/app/views/status_messages/show.html.haml b/app/views/status_messages/show.html.haml index 8ab8d3a3522dee5ff16725d4f14a0f0f04b2e798..108580a3eac177c709c9e0fcfd9fd50e1575a5cc 100644 --- a/app/views/status_messages/show.html.haml +++ b/app/views/status_messages/show.html.haml @@ -7,7 +7,7 @@ .span-14.append-1.last %h1.show_text - = make_links(@status_message.message) + = markdownify(@status_message.message) = how_long_ago(@status_message) diff --git a/app/views/users/getting_started/_step_1.html.haml b/app/views/users/getting_started/_step_1.html.haml index 6ee9002117bfeacf73beb9743d34982d913f768c..56e5638b37c5b009d02cb2bab9325c38f6dda61b 100644 --- a/app/views/users/getting_started/_step_1.html.haml +++ b/app/views/users/getting_started/_step_1.html.haml @@ -35,6 +35,12 @@ Your photo = render 'people/profile_photo_upload', :form => profile + %h4 + Search + %p{:class=>"checkbox_select"} + = profile.label :searchable, "Allow for people to search for you" + = profile.check_box :searchable, {:checked => @person.profile.searchable}, true, false + = hidden_field_tag :getting_started, @step .submit_block diff --git a/config/locales/devise/devise.de.yml b/config/locales/devise/devise.de.yml index 543ab19350ffb3f7cf13f7e212c1a0b3be057a4f..ebbb2baa133b38087074717186b36d486b686ffe 100644 --- a/config/locales/devise/devise.de.yml +++ b/config/locales/devise/devise.de.yml @@ -19,6 +19,11 @@ de: timeout: "Deine Sitzung ist abgelaufen, bitte melde dich erneut an um fortzufahren." inactive: "Dein Konto wurde noch nicht aktiviert." sessions: + new: + login: 'Login' + username: 'Benutzername' + password: 'Passwort' + sign_in: 'Anmelden' signed_in: "Erfolgreich angemeldet." signed_out: "Erfolgreich abgemeldet." passwords: @@ -34,7 +39,21 @@ de: unlocks: send_instructions: "Du wirst in ein paar Minuten eine E-Mail erhalten, die beschreibt, wie du dein Konto entsperren kannst." unlocked: "Dein Konto wurde erfolgreich entsperrt. Du bist nun angemeldet." + invitations: + send_instructions: 'Deine Einladung wurde versandt.' + invitation_token_invalid: 'Das Einladungstoken ist ungültig!' #FIXME: translate token? + updated: 'Dein Passwort wurde erfolgreich gesetzt. Du bist nun angemeldet.' mailer: - confirmation_instructions: "Instruktionen zur Bestätigung" - reset_password_instructions: "Instruktionen zum Zurücksetzen des Passworts" - unlock_instructions: "Instruktionen zum Entsperren" + confirmation_instructions: + subject: "Instruktionen zur Bestätigung" + reset_password_instructions: + subject: "Instruktionen zum Zurücksetzen des Passworts" + unlock_instructions: + subject: "Instruktionen zum Entsperren" + invitation: + subject: 'Ein Freund möchte dich bei Diaspora einladen!' + shared: + links: + sign_in: 'Anmelden' + sign_up: 'Registrieren' + forgot_your_password: 'Passwort vergessen?' diff --git a/config/locales/diaspora/de.yml b/config/locales/diaspora/de.yml index 1f7c028aee71a57acb75eb21252d2f922c6d8d99..5e257644c8d865947292f58a60d4143305e21980 100644 --- a/config/locales/diaspora/de.yml +++ b/config/locales/diaspora/de.yml @@ -2,206 +2,445 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -# Localization file for German. Add more files in this directory for other locales. -# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. +# Localization file for German +# +# This file has parts from rails-i18n project at +# http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale de: + settings: "Einstellungen" + profile: "Profil" + account: "Konto" + services: "Dienste" + cancel: "Abbrechen" + delete: "Löschen" + or: "oder" + by: "von" + ago: "her" + username: "Benutzername" + email: "E-Mail" + home: "Start" + password: "Passwort" + password_confirmation: "Passwort bestätigen" + are_you_sure: "Bist du sicher?" + + activemodel: + errors: + models: + user: + attributes: + person: + invalid: "ist ungültig" + username: + taken: "ist bereits benutzt" + email: + taken: "ist bereits benutzt" + person: + attributes: + diaspora_handle: + taken: "ist bereits benutzt" hello: "Hallo Welt" application: helper: unknown_person: "unbekannte Person" - new_requests: "neue Anfrage" - dashboards: - helper: - home: "Startseite" + new_requests: "neue Anfragen" error_messages: helper: invalid_fields: "Ungültige Felder" - correct_the_following_errors_and_try_again: "Korrigiere die folgenden Fehler und probiere es erneut." - people: + correct_the_following_errors_and_try_again: "Korrigiere die folgenden Fehler und versuche es erneut." + people: #FIXME: seems unused helper: - results_for: " Resultate für %{params}" - people_on_pod_are_aware_of: " people on pod are aware of" + results_for: " Ergebnisse für %{params}" + people_on_pod_are_aware_of: " Leute auf dem Pod sind aufmerksam auf" layouts: application: + view_profile: "Profil anzeigen" edit_profile: "Profil bearbeiten" + account_settings: "Konto Einstellungen" + search: "Suche" logout: "Abmelden" shared: aspect_nav: all_aspects: "Alle Aspekte" manage: "Verwalten" - manage_your_aspects: "Aspekte verwalten" + manage_your_aspects: "Deine Aspekte verwalten" sub_header: all_aspects: "Alle Aspekte" manage_aspects: "Aspekte verwalten" publisher: share: "Teilen" + post_a_message_to: "Sende eine Nachricht an %{aspect}" + make_public: "öffentlich machen" aspect_friends: add_friends: "Freunde hinzufügen" + photos: "Fotos" + invitations: + invites: 'Einladungen' + invite_a_friend: 'Freund einladen' + invitations_left: '(%{count} übrig)' + reshare: + reshare: 'Erneut senden an' + author_info: + view_profile: 'View profile' albums: album: - you: "dir" + you: "Du" new_album: - create: "erstellen" + create: "Hinzufügen" add_a_new_album: "Album hinzufügen" show: edit_album: "Album bearbeiten" albums: "Alben" updated: "aktualisiert" - by: "von" edit: - editing: "Bearbeite" - updated: "geändert" - are_you_sure: "Bist du sicher?" + album_name: "Name des Albums" + editing: "Bearbeiten" + updated: "aktualisiert" + update_album: "Album aktualisieren" delete_album: "Album löschen" - cancel: "Abbrechen" index: - home: "Startseite" new_album: "Neues Album" create: success: "Du hast das Album %{name} erstellt." update: - success: "Album %{name} erfolgreich geändert." - failure: "%{name} wurde nicht geändert." + success: "Album %{name} erfolgreich bearbeitet." + failure: "Bearbeiten des Album %{name} fehlgeschlagen." destroy: success: "Album %{name} gelöscht." helper: friends_albums: "Alben von Freunden" your_albums: "Deine Alben" aspects: - index: - photos: "Fotos" - show: - photos: "Fotos" + no_friends_message: + nobody: "Wir wissen du hast Freunde, hole sie an Bord!" + nobody_in_aspect: "Dein Aspekt %{aspect_name} ist leer." + add_friend: "Freund hinzufügen" + add_friend_to: "Jemanden zum Aspekt %{aspect_name} hinzufügen" + invite: "Jemanden zu Diaspora einladen!" + no_posts_message: + start_talking: "Niemand hat bisher etwas gesagt. Beginne die Konversation!" manage: - add_a_new_aspect: "Neuen Aspekt erstellen" - add_a_new_friend: "Freund hinzufügen" - show: "Anzeigen" + add_a_new_aspect: "Neuen Aspekt hinzufügen" + add_a_new_friend: "Neuen Freund hinzufügen" + show: "Zeigen" update_aspects: "Aspekte aktualisieren" requests: "Anfragen" ignore_remove: "Ignorieren/Entfernen" new_aspect: - add_a_new_aspect: "Neuen Aspekt erstellen" + add_a_new_aspect: "Neuen Aspekt hinzufügen" + name: "Name" create: "Erstellen" create: - success: "Klicke auf das Plus auf der linken Seite um Diaspora mitzuteilen wer deinen neuen Aspekt sehen kann." + success: "Klicke auf das Plus auf der linken Seite um Diaspora zu sagen wer deinen neuen Aspekt sehen kann." + failure: "Erstellen des Aspekt fehlgeschlagen." destroy: - success: "%{name} wurde erfolgreich gelöscht." + success: "%{name} wurde erfolgreich entfernt." update: - success: "Dein Aspekt, %{name}, wurde erfolgreich geändert." - move_friends: - failure: "Ändern des Aspekts für deinen Freund %{real_name} fehlgeschlagen." - success: "Aspekt erfolgreich geändert." + success: "Dein Aspekt %{name} wurde erfolgreich bearbeitet." move_friend: - error: "didn't work %{inspect}" - notice: "Du zeigst deinem Freund jetzt einen anderen Aspekt von dir." + failure: "hat nicht funktioniert %{inspect}" + success: "Person zu neuem Aspekt verschoben" + add_to_aspect: + failure: "Hinzufügen des Freundes zum Aspekt fehlgeschlagen." + success: "Freund erfolgreich zum Aspekt hinzugefügt." helper: remove: "entfernen" aspect_not_empty: "Aspekt ist nicht leer" users: edit: editing_profile: "Profil bearbeiten" - profile: - cancel: "Abbrechen" - update_profile: "Profil aktualisieren" - home: "Startseite" - diaspora_username: "Diaspora Benutzername" - info: "Info" - picture: "Bild" - editing_profile: "Profil bearbeiten" - albums: "Alben" - you_dont_have_any_photos: "Du hast keine Fotos! Gehe auf die" - page_to_upload_some: "Seite um welche hochzuladen." + invite_friends: "Feunde einladen" + export_data: "Konto exportieren" + close_account: "Konto schließen" + change_language: "Sprache ändern" + change_password: "Passwort ändern" + new_password: "Neues Passwort" + destroy: "Konto erfolgreich geschlossen." + getting_started: + signup_steps: "Vervollständige deine Registrierung indem du folgende Dinge tust:" + 'step_1': + albums: "Alben" + you_dont_have_any_photos: "Du hast keine Fotos! Gehe zur" + page_to_upload_some: "Seite um welche hochzuladen." comments: - comment: - # this won't work in german at all. Needs more thorough I18n - ago: "ago" new_comment: - comment: "Kommentar" + comment: "Kommentieren" photos: show: prev: "zurück" full_size: "volle Größe" - next: "vor" + next: "weiter" edit_photo: "Foto bearbeiten" delete_photo: "Foto löschen" - are_you_sure: "Bist du sicher?" comments: "Kommentare" edit: - editing: "Bearbeite" - are_you_sure: "Bist du sicher?" + editing: "Bearbeiten" delete_photo: "Foto löschen" photo: - show_comments: "Kommentare anzeigen" - posted_a_new_photo_to: "neues Foto veröffentlicht bei" + show_comments: "Kommentare zeigen" + posted_a_new_photo_to: "Hinzugefügt:" new: - new_photo: "Foto erstellen" - back_to_list: "Zurück zur Liste" - post_it: "Hochladen" + new_photo: "Neues Foto" + back_to_list: "Zurück zu Liste" + post_it: "Poste es!" create: - runtime_error: "Hochladen eines Fotos fehlgeschlagen. Bist du sicher, dass dein Sicherheitsgurt befestigt ist?" - integrity_error: "Hochladen eines Fotos fehlgeschlagen. Bist du sicher, dass das ein Bild war?" - type_error: "Hochladen eines Fotos fehlgeschlagen. Bist du sicher, dass ein Bild hinzugefügt wurde?" + runtime_error: "Der Server wollte das Foto nicht bearbeiten, bist du darauf zu sehen?" + integrity_error: "Hochladen des Fotos fehlgeschlagen. Bist du sicher das es ein Foto war?" + type_error: "Hochladen des Foto fehlgeschlagen. Du solltest hier nur FOTOS hochladen..." update: notice: "Foto erfolgreich aktualisiert." - error: "Ändern des Fotos fehlgeschlagen." + error: "Bearbeiten des Fotos fehlgeschlagen." destroy: notice: "Foto gelöscht." registrations: new: - sign_up: "Anmelden" + sign_up: "Registrieren" + sign_up_for_diaspora: "Ein Diaspora Konto anlegen" + upload_existing_account: "Ein existierendes Konto hochladen" + upload: "Hochladen" + create: + success: "Willkommen bei Diaspora!" + invitations: create: - success: "Du bist Diaspora beigetreten!" + sent: 'Deine Einladung wurde verschickt.' + no_more: 'Du hast keine Einladungen mehr.' + already_sent: 'Du hast diese Person bereits eingeladen.' + already_friends: 'Du bist bereits mit dieser Person befreundet' + invitation_token_invalid: 'Das Einladungstoken ist ungültig!' + updated: 'Dein Passwort wurde erfolgreich gespeichert. Du bist jetzt angemeldet.' + new: + invite_someone_to_join: 'Lade jemanden zu Diaspora ein!' + if_they_accept_info: 'Wenn sie akzeptieren findest du sie im Aspekt in den du sie eingeladen hast' + to: 'An' + message: 'Nachricht:' + send_an_invitation: 'Eine Einladung senden' + send_invitation: 'Einladung senden' + status_messages: - new_status_message: - tell_me_something_good: "Erzähl' mir was schönes!" - oh_yeah: "Oh, super!" + new_status_message: #FIXME: seems unused + tell_me_something_good: "Was gibt es neues?" + oh_yeah: "oh yeah!" status_message: - show_comments: "Kommentare anzeigen" - delete: "Löschen" - are_you_sure: "Bist du sicher?" + show_comments: "Kommentare zeigen" show: - status_message: "Statusmeldung" + status_message: "Status Nachricht" comments: "Kommentare" - are_you_sure: "Bist du sicher?" - destroy: "Löschen" - view_all: "Alle anzeigen" + destroy: "Zerstören" + view_all: "Alle zeigen" message: "Nachricht" - owner: "Eigentümer" + owner: "Besitzer" helper: no_message_to_display: "Keine Nachricht zum anzeigen." people: person: add_friend: "Freund hinzufügen" - pending_request: "Anfrage ausstehend" + pending_request: "Ausstehende Anfrage" index: add_friend: "Freund hinzufügen" - real_name: "Echter Name" - diaspora_handle: "diaspora handle" - thats_you: "das bist du!" - friend_request_pending: "Ausstehende Freundschaftsanfrage" - you_have_a_friend_request_from_this_person: "Du hast eine Freundschaftsanfrage von dieser Person" + real_name: "Realer Name" + diaspora_handle: "Diaspora Adresse" + thats_you: "Das bist du!" + friend_request_pending: "Ausstehende Freundes-Anfrage" + you_have_a_friend_request_from_this_person: "Du hast eine Freundes-Anfrage von dieser Person" new: new_person: "Neue Person" back_to_list: "Zurück zur Liste" show: - last_seen: "zuletzt gesehen: %{how_long_ago}" + last_seen: "Zuletzt gesehen vor: %{how_long_ago}" #FIXME: appends ago friends_since: "Freunde seit: %{how_long_ago}" save: "speichern" - are_you_sure: "Bist du sicher?" remove_friend: "Freund entfernen" + no_posts: "Keine Posts zum anzeigen!" + add_friend: "Freund hinzufügen" + edit_my_profile: "Mein Profil bearbeiten" + edit: + info_available_to: "Diese Infos werden für alle verfügbar sein mit denen du bei Diaspora verbunden bist." + your_profile: "Dein Profil" + your_name: "Dein Name" + first_name: "Vorname" + last_name: "Nachname" + your_gender: "Dein Geschlecht" + your_birthday: "Dein Geburtstag" + your_bio: "Deine Info" + fill_me_out: "Füll mich aus" + your_photo: "Dein Foto" + update_profile: "Profil aktualisieren" + diaspora_username: "DIASPORA ADRESSE" + info: "Info" + picture: "Bild" + editing_profile: "Profil bearbeiten" + albums: "Alben" + you_dont_have_any_photos: "Du hast keine Fotos! Gehe zur" + page_to_upload_some: "Seite um welche hochzuladen." requests: new_request: - add_a_new_friend_to: "Add a new friend to" - enter_a_diaspora_username: "Gebe einen Diaspora Benutzernamen ein:" - your_diaspora_username_is: "Dein Diaspora Benutzername ist: %{diaspora_handle}" - friends_username: "Freundes Benutzername" + add_a_new_friend_to: "Neuen Freund hinzufügen zu" + enter_a_diaspora_username: "Gib eine Diaspora Adresse ein:" + your_diaspora_username_is: "Deine Diaspora Adresse ist: %{diaspora_handle}" + friends_username: "Diaspora Addresse deines Freundes" + create_request: "Anfrage erstellen" destroy: - success: "Ihr seid jetzt Freunde." - error: "Bitte wähle einen Aspekt aus!" - ignore: "Freundschaftsanfrage ignorieren." + success: "Ihr seit jetzt Freunde." + error: "Bitte wähle einen Aspekt!" + ignore: "Freundes-Anfrage ignoriert." create: - error: "Kein Diaspora-Seed in dieser E-Mail gefunden!" + error: "Keinen Diaspora Seed mit dieser E-Mail gefunden!" #FIXME: wtf? + invalid_identity: "Diese Diaspora Adresse ist nicht richtig formatiert" + error_server: "Problem mit dem anderen Server. Vielleicht existiert er nicht?" + yourself: "Du kannst dich nicht mit dir selbst befreunden!" already_friends: "Du bist bereits mit %{destination_url} befreundet!" - success: "Eine Freundschaftsanfrage wurde an %{destination_url} gesendet." - horribly_wrong: "Etwas ging tierisch schief." + success: "Eine Freundes-Anfrage wurde an %{destination_url} geschickt." + horribly_wrong: "Irgendwas ist furchtbar schief gelaufen." + +# The following is from the rails-i18n project at http://github.com/svenfuchs/rails-i18n + +# German translations for Ruby on Rails +# by Clemens Kofler (clemens@railway.at) + + date: + formats: + default: "%d.%m.%Y" + short: "%e. %b" + long: "%e. %B %Y" + only_day: "%e" + + day_names: [Sonntag, Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag] + abbr_day_names: [So, Mo, Di, Mi, Do, Fr, Sa] + month_names: [~, Januar, Februar, März, April, Mai, Juni, Juli, August, September, Oktober, November, Dezember] + abbr_month_names: [~, Jan, Feb, Mär, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez] + order: [ :day, :month, :year ] + + time: + formats: + default: "%A, %d. %B %Y, %H:%M Uhr" + short: "%d. %B, %H:%M Uhr" + long: "%A, %d. %B %Y, %H:%M Uhr" + time: "%H:%M" + + am: "vormittags" + pm: "nachmittags" + + datetime: + distance_in_words: + half_a_minute: 'eine halbe Minute' + less_than_x_seconds: + one: 'weniger als eine Sekunde' + other: 'weniger als %{count} Sekunden' + x_seconds: + one: 'eine Sekunde' + other: '%{count} Sekunden' + less_than_x_minutes: + one: 'weniger als eine Minute' + other: 'weniger als %{count} Minuten' + x_minutes: + one: 'eine Minute' + other: '%{count} Minuten' + about_x_hours: + one: 'etwa eine Stunde' + other: 'etwa %{count} Stunden' + x_days: + one: 'ein Tag' + other: '%{count} Tage' + about_x_months: + one: 'etwa ein Monat' + other: 'etwa %{count} Monate' + x_months: + one: 'ein Monat' + other: '%{count} Monate' + almost_x_years: + one: 'fast ein Jahr' + other: 'fast %{count} Jahre' + about_x_years: + one: 'etwa ein Jahr' + other: 'etwa %{count} Jahre' + over_x_years: + one: 'mehr als ein Jahr' + other: 'mehr als %{count} Jahre' + prompts: + second: "Sekunden" + minute: "Minuten" + hour: "Stunden" + day: "Tag" + month: "Monat" + year: "Jahr" + + number: + format: + precision: 2 + separator: ',' + delimiter: '.' + currency: + format: + unit: '€' + format: '%n%u' + separator: "," + delimiter: "" + precision: 2 + percentage: + format: + delimiter: "" + precision: + format: + delimiter: "" + human: + format: + delimiter: "" + precision: 1 + storage_units: + # Storage units output formatting. + # %u is the storage unit, %n is the number (default: 2 MB) + format: "%n %u" + units: + byte: + one: "Byte" + other: "Bytes" + kb: "KB" + mb: "MB" + gb: "GB" + tb: "TB" + + support: + array: + words_connector: ", " + two_words_connector: " und " + last_word_connector: " und " + select: + prompt: "Bitte wählen:" + + activemodel: + errors: + template: + header: + one: "Konnte %{model} nicht speichern: ein Fehler." + other: "Konnte %{model} nicht speichern: %{count} Fehler." + body: "Bitte überprüfen Sie die folgenden Felder:" + + activerecord: + errors: + template: + header: + one: "Konnte %{model} nicht speichern: ein Fehler." + other: "Konnte %{model} nicht speichern: %{count} Fehler." + body: "Bitte überprüfen Sie die folgenden Felder:" + + messages: + inclusion: "ist kein gültiger Wert" + exclusion: "ist nicht verfügbar" + invalid: "ist nicht gültig" + confirmation: "stimmt nicht mit der Bestätigung überein" + accepted: "muss akzeptiert werden" + empty: "muss ausgefüllt werden" + blank: "muss ausgefüllt werden" + too_long: "ist zu lang (nicht mehr als %{count} Zeichen)" + too_short: "ist zu kurz (nicht weniger als %{count} Zeichen)" + wrong_length: "hat die falsche Länge (muss genau %{count} Zeichen haben)" + taken: "ist bereits vergeben" + not_a_number: "ist keine Zahl" + greater_than: "muss größer als %{count} sein" + greater_than_or_equal_to: "muss größer oder gleich %{count} sein" + equal_to: "muss genau %{count} sein" + less_than: "muss kleiner als %{count} sein" + less_than_or_equal_to: "muss kleiner oder gleich %{count} sein" + odd: "muss ungerade sein" + even: "muss gerade sein" + record_invalid: "Gültigkeitsprüfung ist fehlgeschlagen: %{errors}" diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 3a9de1b7c58702c7477daabccdbd2817df125c62..582cc170a9b29731ddffd04064078cb65d4a8910 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -101,6 +101,7 @@ en: new_album: "New Album" create: success: "You've created an album called %{name}." + failure: "Failed to create album." update: success: "Album %{name} successfully edited." failure: "Failed to edit album %{name}." diff --git a/config/routes.rb b/config/routes.rb index 8604abaad7decbccee623fd97e713e6b2ee93c13..3bd37a018142c0065a2a4b6a5235cfa41dc26a23 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -20,7 +20,6 @@ Diaspora::Application.routes.draw do match 'public/:username', :to => 'users#public' match 'getting_started', :to => 'users#getting_started', :as => 'getting_started' match 'users/export', :to => 'users#export' - match 'users/import', :to => 'users#import' match 'users/export_photos', :to => 'users#export_photos' resources :users, :except => [:create, :new, :show] diff --git a/config/sprinkle/conf/nginx.conf b/config/sprinkle/conf/nginx.conf index 68eff160678a81603c140b9b1cb2692885762a8d..724645292051a4c9a255595eaffef4c97d8750d5 100644 --- a/config/sprinkle/conf/nginx.conf +++ b/config/sprinkle/conf/nginx.conf @@ -27,8 +27,9 @@ http { gzip_comp_level 2; gzip_proxied any; gzip_buffers 16 8k; - #gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript; - # gzip_disable "MSIE [1-6]\.(?!.*SV1)"; + gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript; + gzip_disable "MSIE [1-6]\.(?!.*SV1)"; + upstream thin_cluster { server unix:/tmp/thin.0.sock; server unix:/tmp/thin.1.sock; @@ -46,7 +47,6 @@ http { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; - proxy_buffering off; if (-f $request_filename/index.html) { rewrite (.*) $1/index.html break; diff --git a/lib/diaspora/importer.rb b/lib/diaspora/importer.rb deleted file mode 100644 index 57dd11ae9d0f1a5d9e14090a8fe46eff63b1a0d8..0000000000000000000000000000000000000000 --- a/lib/diaspora/importer.rb +++ /dev/null @@ -1,222 +0,0 @@ -# Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Diaspora - - class Importer - def initialize(strategy) - self.class.send(:include, strategy) - end - - def commit(user, person, aspects, people, posts, contacts, opts = {}) - filter = verify_and_clean(user, person, people, aspects, posts, contacts) - - #assume data is good - - # to go - user.email = opts[:email] - user.password= opts[:password] - user.password_confirmation = opts[:pasword_confirmation] - - - - user.person = person - - - user.person.diaspora_handle = opts[:diaspora_handle] - - user.visible_post_ids = filter[:whitelist].keys - - #user.friend_ids = - user.visible_person_ids = people.collect{ |x| x.id } - - - posts.each do |post| - post.save! if filter[:unknown].include? post.id - end - - - - aspects.each do |aspect| - user.aspects << aspect - end - - people.each do |p| - p.save! if filter[:people].include? p.id.to_s - end - - contacts.each do |contact| - contact.user = user - - user.friends << contact - contact.save! - end - - - puts user.persisted? - - puts user.inspect - user.save(:validate => false) - - - end - - def assign_aspect_ids(contacts, aspects) - a_hash = {} - aspects.each{|x| a_hash[x.name]=x.id} - - contacts.each do |contact| - contact.aspect_names.each do |x| - contact.aspect_ids << a_hash[x] - end - contact.aspect_names = nil - end - - - end - - ### verification (to be module) ################ - - def verify_and_clean(user, person, people, aspects, posts, contacts) - verify_user(user) - verify_person_for_user(user, person) - filters = filter_posts(posts, person) - clean_aspects(aspects, filters[:whitelist]) - filters[:all_person_ids] = people.collect{ |x| x.id.to_id } - - raise "incorrect number of contacts" unless verify_contacts(contacts, filters[:all_person_ids]) - assign_aspect_ids(contacts, aspects) - filters[:people] = filter_people(people) - filters - end - - def verify_contacts(contacts, person_ids) - return false if contacts.count != person_ids.count - contacts.all?{|x| person_ids.include?(x.person_id)} - end - - def verify_user(user) - User.find_by_id(user.id).nil? ? true : raise("User already exists!") - end - - def verify_person_for_user(user, person) - local_person = Person.find_by_id(person.id) - if local_person - unless user.encryption_key.public_key.to_s == local_person.public_key.to_s - raise "local person found with different owner" - end - end - true - end - - - def filter_people(people) - person_ids = people.collect{|x| x.id} - people_from_db = Person.find_all_by_id(person_ids) #this query should be limited to only return person_id - person_ids = person_ids - people_from_db.collect{ |x| x.id } - - person_hash = {} - person_ids.each{|x| person_hash[x.to_s] = true } - person_hash - end - - def filter_posts(posts, person) - post_ids = posts.collect{|x| x.id} - posts_from_db = Post.find_all_by_id(post_ids) #this query should be limited to only return post id and owner id - - unknown_posts = post_ids - posts_from_db.collect{|x| x.id} - - posts_from_db.delete_if{|x| x.person_id == person.id} - unauthorized_post_ids = posts_from_db.collect{|x| x.id} - post_whitelist = post_ids - unauthorized_post_ids - - unknown = {} - unknown_posts.each{|x| unknown[x.to_s] = true } - - whitelist = {} - post_whitelist.each{|x| whitelist[x.to_s] = true } - - return { - :unknown => unknown, - :whitelist => whitelist } - end - - - def clean_aspects(aspects, whitelist) - aspects.each do |aspect| - aspect.post_ids.delete_if{ |x| !whitelist.include? x.to_s } - end - end - end - - module Parsers - module XML - def execute(xml, opts = {}) - doc = Nokogiri::XML.parse(xml) - - user, person = parse_user_and_person(doc) - aspects = parse_aspects(doc) - contacts = parse_contacts(doc) - people = parse_people(doc) - posts = parse_posts(doc) - - user - commit(user, person, aspects, people, posts, contacts, opts) - end - - def parse_user_and_person(doc) - user = User.new - user_doc = doc.xpath('/export/user') - user.username = user_doc.xpath('//user/username').text - user.serialized_private_key= user_doc.xpath('//user/serialized_private_key').text - person = Person.from_xml(user_doc.xpath('//user/person').to_s) - [user, person] - end - - def parse_aspects(doc) - aspects = [] - aspect_doc = doc.xpath('/export/aspects/aspect') - - aspect_doc.each do |x| - a = Nokogiri::XML.parse(x.to_s) - - aspect = Aspect.new - aspect.name = a.xpath('/aspect/name').text - aspect.post_ids = a.xpath('/aspect/post_ids/post_id').collect{ |x| x.text.to_id } - aspects << aspect - end - aspects - end - - def parse_people(doc) - people_doc = doc.xpath('/export/people/person') - people_doc.inject([]) do |people,curr| - people << Person.from_xml(curr.to_s) - end - end - - def parse_contacts(doc) - contacts = [] - contact_doc = doc.xpath('/export/contacts/contact') - - contact_doc.each do |x| - contact = Contact.new - contact.person_id = x.xpath("person_id").text.to_id - contact.aspect_names = x.xpath('aspects/aspect/name').collect{ |x| x.text} - contacts << contact - end - contacts - end - - def parse_posts(doc) - post_doc = doc.xpath('/export/posts/status_message') - post_doc.inject([]) do |posts,curr| - posts << StatusMessage.from_xml(curr.to_s) - end - end - - end - - end -end diff --git a/lib/diaspora/parser.rb b/lib/diaspora/parser.rb index acdd27afdaf4009fa648017cda6d1293bb12e56e..da3344d84d61c2653b2035cd57124efb206decb0 100644 --- a/lib/diaspora/parser.rb +++ b/lib/diaspora/parser.rb @@ -10,14 +10,7 @@ module Diaspora begin new_object = body.name.camelize.constantize.from_xml body.to_s - - if new_object.is_a? Post - existing_object = new_object.class.find_by_id(new_object.id) - existing_object ? (return existing_object) : (return new_object) - end - - new_object - + return new_object rescue NameError => e if e.message.include? 'wrong constant name' Rails.logger.info "Not a real type: #{object.to_s}" diff --git a/lib/diaspora/user/receiving.rb b/lib/diaspora/user/receiving.rb index 9e9da020c22b17dc5002f3d6658f2b896b11e9b0..e0dd3ef8646cbc70791f243149f403b17e671000 100644 --- a/lib/diaspora/user/receiving.rb +++ b/lib/diaspora/user/receiving.rb @@ -7,10 +7,15 @@ module Diaspora salmon = Salmon::SalmonSlap.parse salmon_xml, self webfinger = EMWebfinger.new(salmon.author_email) - webfinger.on_person { |salmon_author| - if salmon.verified_for_key?(salmon_author.public_key) - Rails.logger.info("data in salmon: #{salmon.parsed_data}") - self.receive(salmon.parsed_data, salmon_author) + webfinger.on_person { |response| + if response.is_a? Person + salmon_author = response + if salmon.verified_for_key?(salmon_author.public_key) + Rails.logger.info("data in salmon: #{salmon.parsed_data}") + self.receive(salmon.parsed_data, salmon_author) + end + else + Rails.logger.info("#{salmon.author_email} not found error: #{response}") end } end @@ -45,13 +50,13 @@ module Diaspora raise "Not friends with that person" unless self.contact_for(salmon_author) if object.is_a?(Comment) - receive_comment object, xml + receive_comment object elsif object.is_a?(Retraction) - receive_retraction object, xml + receive_retraction object elsif object.is_a?(Profile) receive_profile object, person else - receive_post object, xml + receive_post object end end } @@ -60,7 +65,7 @@ module Diaspora end end - def receive_retraction retraction, xml + def receive_retraction retraction if retraction.type == 'Person' unless retraction.person.id.to_s == retraction.post_id.to_s raise "#{retraction.diaspora_handle} trying to unfriend #{retraction.post_id} from #{self.id}" @@ -91,7 +96,7 @@ module Diaspora person.save end - def receive_comment comment, xml + def receive_comment comment raise "In receive for #{self.real_name}, signature was not valid on: #{comment.inspect}" unless comment.post.person == self.person || comment.verify_post_creator_signature self.visible_people = self.visible_people | [comment.person] self.save @@ -105,7 +110,39 @@ module Diaspora comment.socket_to_uid(id) if (comment.respond_to?(:socket_to_uid) && !self.owns?(comment)) end - def receive_post post, xml + def exsists_on_pod?(post) + post.class.find_by_id(post.id) + end + + def receive_post post + #exsists locally, but you dont know about it + #does not exsist locally, and you dont know about it + + #exsists_locally? + #you know about it, and it is mutable + #you know about it, and it is not mutable + # + on_pod = exsists_on_pod?(post) + if on_pod && on_pod.diaspora_handle == post.diaspora_handle + known_post = find_visible_post_by_id(post.id) + if known_post + if known_post.mutable? + known_post.update_attributes(post.to_mongo) + else + Rails.logger.info("#{post.diaspora_handle} is trying to update an immutable object #{known_post.inspect}") + end + elsif on_pod == post + update_user_refs_and_add_to_aspects(on_pod) + end + elsif !on_pod + update_user_refs_and_add_to_aspects(post) + else + Rails.logger.info("#{post.diaspora_handle} is trying to update an exsisting object they do not own #{on_pod.inspect}") + end + end + + + def update_user_refs_and_add_to_aspects(post) Rails.logger.debug("Saving post: #{post}") post.user_refs += 1 post.save @@ -114,11 +151,13 @@ module Diaspora self.save aspects = self.aspects_with_person(post.person) - aspects.each{ |aspect| + aspects.each do |aspect| aspect.posts << post aspect.save - post.socket_to_uid(id, :aspect_ids => [aspect.id]) if (post.respond_to?(:socket_to_uid) && !self.owns?(post)) - } + end + + post.socket_to_uid(id, :aspect_ids => aspects.map{|x| x.id}) if (post.respond_to?(:socket_to_uid) && !self.owns?(post)) + end end end diff --git a/lib/diaspora/websocket.rb b/lib/diaspora/websocket.rb index 09c553e20c86ce30f8ab37c66a16e4c167297ea8..2fec38d397c314a5f409b3bf7e7b38f8efa0bddf 100644 --- a/lib/diaspora/websocket.rb +++ b/lib/diaspora/websocket.rb @@ -15,7 +15,7 @@ module Diaspora def self.push_to_user(uid, data) Rails.logger.debug "Websocketing to #{uid}" - @channels[uid.to_s][0].push(data) if @channels[uid.to_s] + @channels[uid][0].push(data) if @channels[uid] end def self.subscribe(uid, ws) diff --git a/lib/hcard.rb b/lib/hcard.rb index 5fd60b182c2e1da0b74223fbccc959a44d887d5c..09acb7c8f938c883b119e83b5e388c2caeb8de1e 100644 --- a/lib/hcard.rb +++ b/lib/hcard.rb @@ -3,23 +3,16 @@ # the COPYRIGHT file. module HCard - def self.fetch url - Nokogiri::HTML(Net::HTTP.get URI.parse(url)) - end - def self.parse doc { - :given_name => doc.css(".given_name").text, + :given_name => doc.css(".given_name").text, :family_name => doc.css(".family_name").text, - :url => doc.css("#pod_location").text, - :photo => doc.css(".photo[src]").attribute('src').text + :url => doc.css("#pod_location").text, + :photo => doc.css(".photo[src]").attribute('src').text, + :searchable => doc.css(".searchable").text } end - def self.find url - self.parse self.fetch(url) - end - def self.build(raw_hcard) self.parse Nokogiri::HTML(raw_hcard) end diff --git a/public/images/diaspora_white_on_grey.png b/public/images/diaspora_white_on_grey.png new file mode 100644 index 0000000000000000000000000000000000000000..6213e06712dd37b1c841e55ef4dc7bd85d1e778f Binary files /dev/null and b/public/images/diaspora_white_on_grey.png differ diff --git a/public/javascripts/aspect-edit.js b/public/javascripts/aspect-edit.js index c4e05d7d0051d2d6040aa46478cc4cece5576dae..8346bb7dd9fc9a0019384674798df43d30884447 100644 --- a/public/javascripts/aspect-edit.js +++ b/public/javascripts/aspect-edit.js @@ -1,160 +1,169 @@ /* Copyright (c) 2010, Diaspora Inc. This file is -* licensed under the Affero General Public License version 3 or later. See -* the COPYRIGHT file. -*/ - -function decrementRequestsCounter() { - var $new_requests = $(".new_requests"); - var request_html = $new_requests.html(); - var old_request_count = request_html.match(/\d+/); - - if( old_request_count == 1 ) { - $new_requests.html( - request_html.replace(/ \(\d+\)/,'') - ); - } else { - $new_requests.html( - request_html.replace(/\d+/,old_request_count-1) - ); - } -} - -// Dragging person between aspects -$(function() { - $("ul .person").draggable({ - revert: true, - start: function(event,ui){ - $(this).children("img").animate({'height':80, 'width':80, 'opacity':0.8},200) - .tipsy("hide"); - $(".draggable_info").fadeIn(100); - }, - drag: function(event,ui){ - $(this).children("img").tipsy("hide"); //ensure this is hidden - }, - stop: function(event,ui){ - $(this).children("img").animate({'height':70, 'width':70, 'opacity':1},200); - $(".draggable_info").fadeOut(100); - } - }); - - $(".aspect ul.dropzone").droppable({ - hoverClass: 'active', - drop: function(event, ui) { - - var dropzone = $(this); - var person = ui.draggable; - - if( person.hasClass('request') ){ - $.ajax({ - type: "DELETE", - url: "/requests/" + person.attr('data-guid'), - data: {"accept" : true, "aspect_id" : dropzone.attr('data-aspect_id') }, - success: function(data){ - decrementRequestsCounter(); - } - }); - }; - + * licensed under the Affero General Public License version 3 or later. See + * the COPYRIGHT file. + */ + +var AspectEdit = { + + initialize: function() { + $("ul .person").draggable({ + revert: true, + start: AspectEdit.startDrag, + drag: AspectEdit.duringDrag, + stop: AspectEdit.stopDrag + }); - if( dropzone.attr('data-aspect_id') != person.attr('data-aspect_id' )){ - $.ajax({ - url: "/aspects/move_friend/", - data: {"friend_id" : person.attr('data-guid'), - "from" : person.attr('data-aspect_id'), - "to" : { "to" : dropzone.attr('data-aspect_id') }}, - success: function(data){ - person.attr('data-aspect_id', dropzone.attr('data-aspect_id')); - }}); - } + $(".aspect ul.dropzone").droppable({ + hoverClass: 'active', + drop: AspectEdit.onDropMove + }); - dropzone.closest("ul").append(person); - } - }); + $(".aspect_remove ul").droppable({ + hoverClass: 'active', + drop: AspectEdit.onDropDelete + }); + $(".delete").live("click", AspectEdit.deletePerson); + $(".aspect h3").live('focus', AspectEdit.changeName); + }, - $(".aspect_remove ul").droppable({ - hoverClass: 'active', - drop: function(event, ui) { + startDrag: function(event, ui) { + $(this).children("img").animate({'height':80, 'width':80, 'opacity':0.8}, 200) + .tipsy("hide"); + $(".draggable_info").fadeIn(100); + }, - var person = ui.draggable; + duringDrag: function(event, ui) { + $(this).children("img").tipsy("hide"); //ensure this is hidden + }, - if ( person.attr('data-guid').length == 1 ) { - alert("You can not remove the person from the last aspect"); + stopDrag: function(event, ui) { + $(this).children("img").animate({'height':70, 'width':70, 'opacity':1}, 200); + $(".draggable_info").fadeOut(100); + }, - } else { - if( !person.hasClass('request') ){ + onDropMove: function(event, ui) { + var dropzone = $(this); + var person = ui.draggable; - $.ajax({ - type: "POST", - url: "/aspects/remove_from_aspect", - data:{ - 'friend_id' : person.attr('data-guid'), - 'aspect_id' : person.attr('data-aspect_id') } - }); + if (person.hasClass('request')) { + $.ajax({ + type: "DELETE", + url: "/requests/" + person.attr('data-guid'), + data: {"accept" : true, "aspect_id" : dropzone.attr('data-aspect_id') }, + success: function(data) { + AspectEdit.decrementRequestsCounter(); } - person.fadeOut(400, function(){person.remove();}); - } + }); + } + + if (dropzone.attr('data-aspect_id') != person.attr('data-aspect_id')) { + $.ajax({ + url: "/aspects/move_friend/", + data: {"friend_id" : person.attr('data-guid'), + "from" : person.attr('data-aspect_id'), + "to" : { "to" : dropzone.attr('data-aspect_id') }}, + success: function(data) { + person.attr('data-aspect_id', dropzone.attr('data-aspect_id')); + }}); } - }); -}); + dropzone.closest("ul").append(person); + }, -// Person deletion -$(".delete").live("click", function() { + onDropDelete: function(event, ui) { + var person = ui.draggable; - var person = $(this).closest("li.person"); + if (person.attr('data-guid').length == 1) { + alert("You can not remove the person from the last aspect"); - if (person.hasClass('request')){ - if( confirm("Ignore request?") ){ - var request_id = person.attr("data-guid"); + } else { + if (!person.hasClass('request')) { - $.ajax({ - type: "DELETE", - url: "/requests/" + request_id, - success: function () { - decrementRequestsCounter(); - } + $.ajax({ + type: "POST", + url: "/aspects/remove_from_aspect", + data:{ + 'friend_id' : person.attr('data-guid'), + 'aspect_id' : person.attr('data-aspect_id') } + }); + } + person.fadeOut(400, function() { + person.remove(); }); } + }, - } else { - if( confirm("Remove this person from all aspects?") ){ - var person_id = $(this).closest("li.person").attr('data-guid'); + changeName: function() { - $.ajax({ - type: "DELETE", - url: "/people/" + person_id, - success: function() { - person.fadeOut(200); - } - }); - } - } -}); + var $this = $(this); + var id = $this.closest("li.aspect").attr("data-guid"); + var link = "/aspects/" + id; + $this.keypress(function(e) { + if (e.which == 13) { + e.preventDefault(); + $this.blur(); -// Editing aspect name -$(".aspect h3").live('focus', function() { + //save changes + $.ajax({ + type: "PUT", + url: link, + data: {"aspect" : {"name" : $this.text() }} + }); + } + //update all other aspect links + $this.keyup(function(e) { + $("#aspect_nav a[href='" + link + "']").text($this.text()); + }); + }); + }, - var $this = $(this); - var id = $this.closest("li.aspect").attr("data-guid"); - var link = "/aspects/"+ id; + deletePerson: function() { + var person = $(this).closest("li.person"); - $this.keypress(function(e) { - if (e.which == 13) { - e.preventDefault(); - $this.blur(); + if (person.hasClass('request')) { + if (confirm("Ignore request?")) { + var request_id = person.attr("data-guid"); - //save changes - $.ajax({ - type: "PUT", - url: link, - data: {"aspect" : {"name" : $this.text() }} - }); + $.ajax({ + type: "DELETE", + url: "/requests/" + request_id, + success: function () { + AspectEdit.decrementRequestsCounter(); + } + }); + } + } else { + if (confirm("Remove this person from all aspects?")) { + var person_id = $(this).closest("li.person").attr('data-guid'); + + $.ajax({ + type: "DELETE", + url: "/people/" + person_id, + success: function() { + person.fadeOut(200); + } + }); + } } - //update all other aspect links - $this.keyup(function(e) { - $("#aspect_nav a[href='"+link+"']").text($this.text()); - }); - }); -}); + }, + + decrementRequestsCounter: function() { + var $new_requests = $(".new_requests"); + var request_html = $new_requests.html(); + var old_request_count = request_html.match(/\d+/); + + if (old_request_count == 1) { + $new_requests.html( + request_html.replace(/ \(\d+\)/, '') + ); + } else { + $new_requests.html( + request_html.replace(/\d+/, old_request_count - 1) + ); + } + } +}; + +$(document).ready(AspectEdit.initialize); \ No newline at end of file diff --git a/public/stylesheets/sass/application.sass b/public/stylesheets/sass/application.sass index c541f5c417044a000c814a11c51c3c7f0681a936..5577d829f6b2c44b7743bff6766ba95a5a16ab11 100644 --- a/public/stylesheets/sass/application.sass +++ b/public/stylesheets/sass/application.sass @@ -652,6 +652,11 @@ form p :padding 0 :margin 0 +form p.checkbox_select + label + :left 20px + :top 0 + label :font :family 'Arial', 'Helvetica', sans-serif @@ -1450,3 +1455,5 @@ ul.aspects :padding :left 120px + + diff --git a/script/websocket_server.rb b/script/websocket_server.rb index 3b458118b4b9200ef50eb31d79b19dbbcaee8245..cc788e734fdac89ed5dbe76281c23ca9499f9a26 100644 --- a/script/websocket_server.rb +++ b/script/websocket_server.rb @@ -48,11 +48,15 @@ begin :debug =>APP_CONFIG[:socket_debug]) do |ws| ws.onopen { - sid = Diaspora::WebSocket.subscribe(ws.request['Path'].gsub('/',''), ws) + encoded_cookie = ws.request["Cookie"].gsub("_diaspora_session=","") + cookie = Marshal.load(encoded_cookie.unpack("m*").first) + user_id = cookie["warden.user.user.key"].last + + sid = Diaspora::WebSocket.subscribe(user_id, ws) ws.onmessage { |msg| SocketsController.new.incoming(msg) } - ws.onclose { Diaspora::WebSocket.unsubscribe(ws.request['Path'].gsub('/',''), sid) } + ws.onclose { Diaspora::WebSocket.unsubscribe(user_id, sid) } } end PID_FILE = APP_CONFIG[:socket_pidfile] diff --git a/spec/controllers/albums_controller_spec.rb b/spec/controllers/albums_controller_spec.rb index 21e75068599e94c281079b19b1b6f3c778ec8ab7..78a4b429062d07f17185f037887205860458f78c 100644 --- a/spec/controllers/albums_controller_spec.rb +++ b/spec/controllers/albums_controller_spec.rb @@ -22,6 +22,19 @@ describe AlbumsController do params = {"album" => {"name" => "Sunsets","to" => @aspect.id.to_s}} post :create, params end + + context 'with invalid params' do + it 'should render a flash error message when album name is blank' do + params = {"album" => {"name" => "", "to" => "all"}} + post :create, params + flash[:error].should == "Failed to create album." + end + it 'should redirect back to album page for that given aspect' do + params = {"album" => {"name" => "", "to" => "all"}} + post :create, params + response.should redirect_to albums_path(:aspect => "all") + end + end end describe "#update" do @@ -29,7 +42,7 @@ describe AlbumsController do put :update, :id => @album.id, :album => { :name => "new_name"} @album.reload.name.should eql("new_name") end - + it "doesn't overwrite random attributes" do new_user = make_user params = {:name => "Bruisers", :person_id => new_user.person.id} diff --git a/spec/controllers/people_controller_spec.rb b/spec/controllers/people_controller_spec.rb index 16b0968a4da21e9646d2a2cd9dd8875878ceae46..c69c0f9d533bab3b7ff7b28dbb6c6cb92ec4267f 100644 --- a/spec/controllers/people_controller_spec.rb +++ b/spec/controllers/people_controller_spec.rb @@ -22,14 +22,17 @@ describe PeopleController do it 'should go to the current_user show page' do get :show, :id => user.person.id + response.should be_success end - it "doesn't error out on an invalid id" do + it "redirects on an invalid id" do get :show, :id => 'delicious' + response.should redirect_to people_path end - it "doesn't error out on a nonexistent person" do + it "redirects on a nonexistent person" do get :show, :id => user.id + response.should redirect_to people_path end describe '#update' do @@ -50,5 +53,11 @@ describe PeopleController do user.person.profile.image_url.should == image_url end end + it 'does not allow mass assignment' do + new_user = make_user + put :update, :id => user.person.id, :person => { + :owner_id => new_user.id} + user.person.reload.owner_id.should_not == new_user.id + end end end diff --git a/spec/controllers/requests_controller_spec.rb b/spec/controllers/requests_controller_spec.rb index 636d6e2b98b393c3beeaf5ca5c686ab89bcf4459..4a772c5a332347bd9c94868d98adde7fa11ada46 100644 --- a/spec/controllers/requests_controller_spec.rb +++ b/spec/controllers/requests_controller_spec.rb @@ -13,48 +13,54 @@ describe RequestsController do @user.aspects.create(:name => "lame-os") end - it "should not error out when requesting to be friends with yourself" do - put("create", "request" => { - "destination_url" => @user.diaspora_handle, - "aspect_id" => @user.aspects[0].id - } - ) - response.should redirect_to aspects_manage_path - end - - it "should not error out when requesting an invalid identity" do - put("create", "request" => { - "destination_url" => "not_a_@valid_email", - "aspect_id" => @user.aspects[0].id - } - ) - response.should redirect_to aspects_manage_path - end + describe '#create' do + it "redirects when requesting to be friends with yourself" do + put("create", "request" => { + "destination_url" => @user.diaspora_handle, + "aspect_id" => @user.aspects[0].id + } + ) + response.should redirect_to aspects_manage_path + end - it "should not error out when requesting an invalid identity with a port number" do - put("create", "request" => { - "destination_url" => "johndoe@email.com:3000", - "aspect_id" => @user.aspects[0].id - } - ) - response.should redirect_to aspects_manage_path - end + it "flashes and redirects when requesting an invalid identity" do + put("create", "request" => { + "destination_url" => "not_a_@valid_email", + "aspect_id" => @user.aspects[0].id + } + ) + flash[:error].should_not be_blank + response.should redirect_to aspects_manage_path + end - it "should not error out when requesting an identity from an invalid server" do - stub_request(:get, /notadiasporaserver\.com/).to_raise(Errno::ETIMEDOUT) - put("create", "request" => { - "destination_url" => "johndoe@notadiasporaserver.com", - "aspect_id" => @user.aspects[0].id - } - ) - response.should redirect_to aspects_manage_path - end + it "flashes and redirects when requesting an invalid identity with a port number" do + put("create", "request" => { + "destination_url" => "johndoe@email.com:3000", + "aspect_id" => @user.aspects[0].id + } + ) + flash[:error].should_not be_blank + response.should redirect_to aspects_manage_path + end - it 'should redirect to the page which you called it from ' do - pending "i need to figure out how to do this" - end + it "redirects when requesting an identity from an invalid server" do + stub_request(:get, /notadiasporaserver\.com/).to_raise(Errno::ETIMEDOUT) + put("create", "request" => { + "destination_url" => "johndoe@notadiasporaserver.com", + "aspect_id" => @user.aspects[0].id + } + ) + response.should redirect_to aspects_manage_path + end - it 'should not blow up if there is a problem mid way thru the webfinger process' do - pending "i need to do this tomorrow" + it 'should redirect to the page which you called it from ' do + pending "This controller should probably redirect to :back" + put("create", "request" => { + "destination_url" => "johndoe@notadiasporaserver.com", + "aspect_id" => @user.aspects[0].id + } + ) + response.should redirect_to(:back) + end end end diff --git a/spec/fixtures/hcard_response b/spec/fixtures/hcard_response index c3bfb2840ba320185ffe26d6dd26b6d8cffc2de4..d229660d2fed158559463eb173d6bbd3e4de9ce9 100644 --- a/spec/fixtures/hcard_response +++ b/spec/fixtures/hcard_response @@ -43,6 +43,12 @@ <dt>Note</dt> <dd class="note">Diaspora is awesome! vi is better than emacs!</dd> </dl> + <dl class='entity_searchable'> + <dt>Searchable</dt> + <dd> + <span class='searchable'>false</span> + </dd> + </dl> </div> </div> </div> diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 0ba2bb28a14c50e75e9207071f6909c32a414ed0..9e7cb7f4c5b697211f58ab52d6089dbad1532892 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -18,4 +18,155 @@ describe ApplicationHelper do person_url(@user).should == "/users/#{@user.id}" end + describe "markdownify" do + describe "autolinks" do + it "should not allow basic XSS/HTML" do + markdownify("<script>alert('XSS is evil')</script>").should == "<script>alert('XSS is evil')</script>" + end + + it "should recognize basic http links (1/3)" do + proto="http" + url="bugs.joindiaspora.com/issues/332" + markdownify(proto+"://"+url).should == "<a target=\"_blank\" href=\""+proto+"://"+url+"\">"+url+"</a>" + end + + it "should recognize basic http links (2/3)" do + proto="http" + url="webmail.example.com?~()!*/" + markdownify(proto+"://"+url).should == "<a target=\"_blank\" href=\""+proto+"://"+url+"\">"+url+"</a>" + end + + it "should recognize basic http links (3/3)" do + proto="http" + url="127.0.0.1:3000/users/sign_in" + markdownify(proto+"://"+url).should == "<a target=\"_blank\" href=\""+proto+"://"+url+"\">"+url+"</a>" + end + + it "should recognize secure https links" do + proto="https" + url="127.0.0.1:3000/users/sign_in" + markdownify(proto+"://"+url).should == "<a target=\"_blank\" href=\""+proto+"://"+url+"\">"+url+"</a>" + end + + it "should recognize youtube links" do + proto="http" + videoid = "0x__dDWdf23" + url="www.youtube.com/watch?v="+videoid+"&a=GxdCwVVULXdvEBKmx_f5ywvZ0zZHHHDU&list=ML&playnext=1" + title = "UP & down & UP & down &" + mock_http = mock("http") + Net::HTTP.stub!(:new).with('gdata.youtube.com', 80).and_return(mock_http) + mock_http.should_receive(:get).with('/feeds/api/videos/'+videoid+'?v=2', nil).and_return([nil, 'Foobar <title>'+title+'</title> hallo welt <asd><dasdd><a>dsd</a>']) + res = markdownify(proto+'://'+url) + res.should == "<a onclick=\"openVideo('youtube.com', '"+videoid+"', this)\" href=\"#video\">Youtube: "+title+"</a>" + end + + it "should recognize a bunch of different links" do + message = "http:// Hello World, this is for www.joindiaspora.com and not for http://www.google.com though their Youtube service is neat, take http://www.youtube.com/watch?v=foobar or www.youtube.com/watch?foo=bar&v=BARFOO&whatever=related It is a good idea we finally have youtube, so enjoy this video http://www.youtube.com/watch?v=rickrolld" + mock_http = mock("http") + Net::HTTP.stub!(:new).with('gdata.youtube.com', 80).and_return(mock_http) + mock_http.should_receive(:get).with('/feeds/api/videos/foobar?v=2', nil).and_return([nil, 'Foobar <title>F 007 - the bar is not enough</title> hallo welt <asd><dasdd><a>dsd</a>']) + mock_http.should_receive(:get).with('/feeds/api/videos/BARFOO?v=2', nil).and_return([nil, 'Foobar <title>BAR is the new FOO</title> hallo welt <asd><dasdd><a>dsd</a>']) + mock_http.should_receive(:get).with('/feeds/api/videos/rickrolld?v=2', nil).and_return([nil, 'Foobar <title>Never gonne give you up</title> hallo welt <asd><dasdd><a>dsd</a>']) + res = markdownify(message) + res.should == "http:// Hello World, this is for <a target=\"_blank\" href=\"http://www.joindiaspora.com\">www.joindiaspora.com</a> and not for <a target=\"_blank\" href=\"http://www.google.com\">www.google.com</a> though their Youtube service is neat, take <a onclick=\"openVideo('youtube.com', 'foobar', this)\" href=\"#video\">Youtube: F 007 - the bar is not enough</a> or <a onclick=\"openVideo('youtube.com', 'BARFOO', this)\" href=\"#video\">Youtube: BAR is the new FOO</a> It is a good idea we finally have youtube, so enjoy this video <a onclick=\"openVideo('youtube.com', 'rickrolld', this)\" href=\"#video\">Youtube: Never gonne give you up</a>" + end + + it "should recognize basic ftp links" do + proto="ftp" + url="ftp.uni-kl.de/CCC/26C3/mp4/26c3-3540-en-a_hackers_utopia.mp4" + # I did not watch that one, but the title sounds nice :P + markdownify(proto+"://"+url).should == "<a target=\"_blank\" href=\""+proto+"://"+url+"\">"+url+"</a>" + end + + it "should recognize www links" do + url="www.joindiaspora.com" + markdownify(url).should == "<a target=\"_blank\" href=\"http://"+url+"\">"+url+"</a>" + end + end + + describe "weak emphasis" do + it "should be recognized (1/2)" do + message = "*some text* some text *some text* some text" + markdownify(message).should == "<em>some text</em> some text <em>some text</em> some text" + end + + it "should be recognized (2/2)" do + message = "_some text_ some text _some text_ some text" + markdownify(message).should == "<em>some text</em> some text <em>some text</em> some text" + end + end + + describe "strong emphasis" do + it "should be recognized (1/2)" do + message = "**some text** some text **some text** some text" + markdownify(message).should == "<strong>some text</strong> some text <strong>some text</strong> some text" + end + + it "should be recognized (2/2)" do + message = "__some text__ some text __some text__ some text" + markdownify(message).should == "<strong>some text</strong> some text <strong>some text</strong> some text" + end + end + + describe "nested weak and strong emphasis" do + it "should be rendered correctly" do + message = "__this is _some_ text__" + markdownify(message).should == "<strong>this is <em>some</em> text</strong>" + message = "*this is **some** text*" + markdownify(message).should == "<em>this is <strong>some</strong> text</em>" + message = "___some text___" + markdownify(message).should == "<em><strong>some text</strong></em>" + end + end + + describe "links" do + it "should be recognized without title attribute" do + message = "[link text](http://someurl.com) [link text](http://someurl.com)" + markdownify(message).should == '<a target="_blank" href="http://someurl.com">link text</a> <a target="_blank" href="http://someurl.com">link text</a>' + end + + it "should be recognized with title attribute" do + message = '[link text](http://someurl.com "some title") [link text](http://someurl.com "some title")' + markdownify(message).should == '<a target="_blank" href="http://someurl.com" title="some title">link text</a> <a target="_blank" href="http://someurl.com" title="some title">link text</a>' + end + end + + describe "nested emphasis and links tags" do + it "should be rendered correctly" do + message = '[**some *link* text**](someurl.com "some title")' + markdownify(message).should == '<a target="_blank" href="someurl.com" title="some title"><strong>some <em>link</em> text</strong></a>' + end + end + + it "should allow escaping" do + message = '*some text* \\*some text* \\**some text* _some text_ \\_some text_ \\__some text_' + markdownify(message).should == "<em>some text</em> *some text<em> *</em>some text <em>some text</em> _some text<em> _</em>some text" + end + + describe "options" do + before do + @message = "http://url.com www.url.com www.youtube.com/watch?foo=bar&v=BARFOO&whatever=related *emphasis* __emphasis__ [link](www.url.com) [link](url.com \"title\")" + end + + it "should allow to render only autolinks" do + res = markdownify(@message, :youtube => false, :emphasis => false, :links => false) + res.should == "<a target=\"_blank\" href=\"http://url.com\">url.com</a> <a target=\"_blank\" href=\"http://www.url.com\">www.url.com</a> <a target=\"_blank\" href=\"http://www.youtube.com/watch?foo=bar&v=BARFOO&whatever=related\">www.youtube.com/watch?foo=bar&v=BARFOO&whatever=related</a> *emphasis* __emphasis__ [link](www.url.com) [link](url.com "title")" + end + + it "should allow to render only youtube autolinks" do + res = markdownify(@message, :autolinks => false, :emphasis => false, :links => false) + res.should == "http://url.com www.url.com <a onclick=\"openVideo('youtube.com', 'BARFOO', this)\" href=\"#video\">Youtube: BAR is the new FOO</a> *emphasis* __emphasis__ [link](www.url.com) [link](url.com "title")" + end + + it "should allow to render only emphasis tags" do + res = markdownify(@message, :autolinks => false, :youtube => false, :links => false) + res.should == "http://url.com www.url.com www.youtube.com/watch?foo=bar&v=BARFOO&whatever=related <em>emphasis</em> <strong>emphasis</strong> [link](www.url.com) [link](url.com "title")" + end + + it "should allo to render only links tags" do + res = markdownify(@message, :autolinks => false, :youtube => false, :emphasis => false) + res.should == "http://url.com www.url.com www.youtube.com/watch?foo=bar&v=BARFOO&whatever=related *emphasis* __emphasis__ <a target=\"_blank\" href=\"www.url.com\">link</a> <a target=\"_blank\" href=\"url.com\" title=\"title\">link</a>" + end + end + end end diff --git a/spec/helpers/status_messages_helper_spec.rb b/spec/helpers/status_messages_helper_spec.rb deleted file mode 100644 index 0aee3826ada8d4e01e265ef3db503c55ba460d83..0000000000000000000000000000000000000000 --- a/spec/helpers/status_messages_helper_spec.rb +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe StatusMessagesHelper do - it "should not allow basic XSS/HTML" do - make_links("<script>alert('XSS is evil')</script>").should == "<script>alert('XSS is evil')</script>" - end - - it "should recognize basic http links (1/3)" do - proto="http" - url="bugs.joindiaspora.com/issues/332" - make_links(proto+"://"+url).should == "<a target=\"_blank\" href=\""+proto+"://"+url+"\">"+url+"</a>" - end - - it "should recognize basic http links (2/3)" do - proto="http" - url="webmail.example.com?~()!*/" - make_links(proto+"://"+url).should == "<a target=\"_blank\" href=\""+proto+"://"+url+"\">"+url+"</a>" - end - - it "should recognize basic http links (3/3)" do - proto="http" - url="127.0.0.1:3000/users/sign_in" - make_links(proto+"://"+url).should == "<a target=\"_blank\" href=\""+proto+"://"+url+"\">"+url+"</a>" - end - - it "should recognize secure https links" do - proto="https" - url="127.0.0.1:3000/users/sign_in" - make_links(proto+"://"+url).should == "<a target=\"_blank\" href=\""+proto+"://"+url+"\">"+url+"</a>" - end - - it "should recognize youtube links" do - proto="http" - videoid = "0x__dDWdf23" - url="www.youtube.com/watch?v="+videoid+"&a=GxdCwVVULXdvEBKmx_f5ywvZ0zZHHHDU&list=ML&playnext=1" - title = "UP & down & UP & down &" - mock_http = mock("http") - Net::HTTP.stub!(:new).with('gdata.youtube.com', 80).and_return(mock_http) - mock_http.should_receive(:get).with('/feeds/api/videos/'+videoid+'?v=2', nil).and_return([nil, 'Foobar <title>'+title+'</title> hallo welt <asd><dasdd><a>dsd</a>']) - res = make_links(proto+'://'+url) - res.should == "<a onclick=\"openVideo('youtube.com', '"+videoid+"', this)\" href=\"#video\">Youtube: "+title+"</a>" - end - - it "should recognize a bunch of different links" do - message = "http:// Hello World, this is for www.joindiaspora.com and not for http://www.google.com though their Youtube service is neat, take http://www.youtube.com/watch?v=foobar or www.youtube.com/watch?foo=bar&v=BARFOO&whatever=related It is a good idea we finally have youtube, so enjoy this video http://www.youtube.com/watch?v=rickrolld" - mock_http = mock("http") - Net::HTTP.stub!(:new).with('gdata.youtube.com', 80).and_return(mock_http) - mock_http.should_receive(:get).with('/feeds/api/videos/foobar?v=2', nil).and_return([nil, 'Foobar <title>F 007 - the bar is not enough</title> hallo welt <asd><dasdd><a>dsd</a>']) - mock_http.should_receive(:get).with('/feeds/api/videos/BARFOO?v=2', nil).and_return([nil, 'Foobar <title>BAR is the new FOO</title> hallo welt <asd><dasdd><a>dsd</a>']) - mock_http.should_receive(:get).with('/feeds/api/videos/rickrolld?v=2', nil).and_return([nil, 'Foobar <title>Never gonne give you up</title> hallo welt <asd><dasdd><a>dsd</a>']) - res = make_links(message) - res.should == "http:// Hello World, this is for <a target=\"_blank\" href=\"http://www.joindiaspora.com\">www.joindiaspora.com</a> and not for <a target=\"_blank\" href=\"http://www.google.com\">www.google.com</a> though their Youtube service is neat, take <a onclick=\"openVideo('youtube.com', 'foobar', this)\" href=\"#video\">Youtube: F 007 - the bar is not enough</a> or <a onclick=\"openVideo('youtube.com', 'BARFOO', this)\" href=\"#video\">Youtube: BAR is the new FOO</a> It is a good idea we finally have youtube, so enjoy this video <a onclick=\"openVideo('youtube.com', 'rickrolld', this)\" href=\"#video\">Youtube: Never gonne give you up</a>" - end - - it "should recognize basic ftp links" do - proto="ftp" - url="ftp.uni-kl.de/CCC/26C3/mp4/26c3-3540-en-a_hackers_utopia.mp4" - # I did not watch that one, but the title sounds nice :P - make_links(proto+"://"+url).should == "<a target=\"_blank\" href=\""+proto+"://"+url+"\">"+url+"</a>" - end - - it "should recognize www links" do - url="www.joindiaspora.com" - make_links(url).should == "<a target=\"_blank\" href=\"http://"+url+"\">"+url+"</a>" - end - - -end diff --git a/spec/javascripts/aspect-edit-spec.js b/spec/javascripts/aspect-edit-spec.js index 5405f480e3dbc521a9a4b83b1e60e8b72ce18aae..9c2da462166a9558158b92643e8d999b86fd6e1b 100644 --- a/spec/javascripts/aspect-edit-spec.js +++ b/spec/javascripts/aspect-edit-spec.js @@ -1,27 +1,30 @@ -describe("editing aspects", function() { +describe("AspectEdit", function() { + +// describe("initialize", function() { +// +// }); describe("decrementRequestsCounter", function() { describe("when there is one request", function() { it("removes the counter from the new requests div", function() { $('#jasmine_content').html("<div class='new_requests'>Requests (1)</div>"); - decrementRequestsCounter(); + AspectEdit.decrementRequestsCounter(); expect($('.new_requests').first().html()).toEqual("Requests"); }); }); describe("when there is more than one request", function() { it("decrements the request counter", function() { $('#jasmine_content').html("<div class='new_requests'>Requests (67)</div>"); - decrementRequestsCounter(); + AspectEdit.decrementRequestsCounter(); expect($('.new_requests').first().html()).toEqual("Requests (66)"); }); }); describe("error cases", function() { it("fails silently if there are no requests", function() { $('#jasmine_content').html("<div class='new_requests'>Requests</div>"); - decrementRequestsCounter(); + AspectEdit.decrementRequestsCounter(); expect($('.new_requests').first().html()).toEqual("Requests"); }); }); }); - }); \ No newline at end of file diff --git a/spec/javascripts/support/jasmine.yml b/spec/javascripts/support/jasmine.yml index 74645d1e6ddc2a48348f5fe8d0628c75daee584d..dda4a5fdb8dcc362b6f8f4117103e8435fa172dc 100644 --- a/spec/javascripts/support/jasmine.yml +++ b/spec/javascripts/support/jasmine.yml @@ -12,6 +12,7 @@ # src_files: - public/javascripts/jquery142.js + - public/javascripts/jquery-ui-1.8.4.custom.min.js - public/javascripts/aspect-edit.js # stylesheets diff --git a/spec/lib/diaspora/importer_spec.rb b/spec/lib/diaspora/importer_spec.rb deleted file mode 100644 index f855f8bd0037fd31fdf61e3262fc9d3dde6bebc2..0000000000000000000000000000000000000000 --- a/spec/lib/diaspora/importer_spec.rb +++ /dev/null @@ -1,254 +0,0 @@ -# Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' -require File.join(Rails.root, 'lib/diaspora/exporter') -require File.join(Rails.root, 'lib/diaspora/importer') - -describe Diaspora::Importer do - def setup_for_exporting - # Five users on pod - @user1 = make_user - @user2 = make_user - @user3 = make_user - @user4 = make_user - @user5 = make_user - - # Two external people referenced on pod - @person1 = Factory(:person) - @person2 = Factory(:person) - - # User1 has four aspects(1-4), each following user has one aspect - @aspect1 = @user1.aspects.create(:name => "Dudes") - @aspect2 = @user1.aspects.create(:name => "Girls") - @aspect3 = @user1.aspects.create(:name => "Bros") - @aspect4 = @user1.aspects.create(:name => "People") - @aspect5 = @user2.aspects.create(:name => "Abe Lincolns") - @aspect6 = @user3.aspects.create(:name => "Cats") - @aspect7 = @user4.aspects.create(:name => "Dogs") - @aspect8 = @user5.aspects.create(:name => "Hamsters") - @aspect9 = @user5.aspects.create(:name => "Gophers") - - @aspect10 = @user1.aspects.create(:name => "Work") - @aspect11 = @user1.aspects.create(:name => "Family") - - # User1 posts one status messages to aspects (1-4), two other users post message to one aspect - @status_message1 = @user1.post(:status_message, :message => "One", :public => false, :to => @aspect1.id) - @status_message2 = @user1.post(:status_message, :message => "Two", :public => false, :to => @aspect2.id) - @status_message3 = @user1.post(:status_message, :message => "Three", :public => false, :to => @aspect3.id) - @status_message4 = @user1.post(:status_message, :message => "Four", :public => false, :to => @aspect4.id) - @status_message5 = @user2.post(:status_message, :message => "Five", :public => false, :to => @aspect5.id) - @status_message6 = @user3.post(:status_message, :message => "Six", :public => false, :to => @aspect6.id) - @status_message7 = @user5.post(:status_message, :message => "Seven", :public => false, :to => @aspect9.id) - - @aspect1.posts << @status_message1 - @aspect2.posts << @status_message2 - @aspect3.posts << @status_message3 - @aspect4.posts << @status_message4 - - # Friend users with user1 - friend_users( @user1, @aspect1, @user2, @aspect5 ) - friend_users( @user1, @aspect2, @user3, @aspect6 ) - friend_users( @user1, @aspect3, @user4, @aspect7 ) - friend_users( @user1, @aspect4, @user5, @aspect8 ) - - # Friend users 4 and 5 - friend_users( @user5, @aspect9, @user4, @aspect7 ) - - # Generate status messages and receive for user1 - @user2.receive @status_message1.to_diaspora_xml, @user1.person - @user3.receive @status_message2.to_diaspora_xml, @user1.person - @user4.receive @status_message3.to_diaspora_xml, @user1.person - @user5.receive @status_message4.to_diaspora_xml, @user1.person - @user1.receive @status_message5.to_diaspora_xml, @user2.person - @user1.receive @status_message6.to_diaspora_xml, @user3.person - - # Generate status message and recieve between user4 and user5 - @user4.receive @status_message7.to_diaspora_xml, @user5.person - - - end - - before(:all) do - DatabaseCleaner.clean - UserFixer.load_user_fixtures - setup_for_exporting - # Generate exported XML for user1 - exporter = Diaspora::Exporter.new(Diaspora::Exporters::XML) - @user1.aspects.reload - @xml = exporter.execute(@user1) - - @old_user = @user1 - - # Remove user1 from the server - @user1.aspects.each( &:delete ) - @user1.raw_visible_posts.find_all_by_person_id(@user1.person.id).each( &:delete ) - @user1.delete - end - - it 'should gut check this test' do - setup_for_exporting - @user1.friends.count.should be 4 - - @user1.contact_for(@user2.person).should_not be_nil - @user1.contact_for(@user3.person).should_not be_nil - @user1.contact_for(@user4.person).should_not be_nil - @user1.contact_for(@user5.person).should_not be_nil - - # User is generated with two pre-populated aspects - @user1.aspects.count.should be 6 - @user1.aspects.find_by_name("Dudes").people.find_by_person_id(@user2.person.id).should_not be_nil - @user1.aspects.find_by_name("Dudes").posts.should include @status_message5 - - @user1.raw_visible_posts.count.should be 6 - @user1.raw_visible_posts.find_all_by_person_id(@user1.person.id).count.should be 4 - @user1.raw_visible_posts.find_all_by_person_id(@user1.person.id).should_not include @status_message7 - end - - context 'parsing a user' do - - before(:each) do - @importer = Diaspora::Importer.new(Diaspora::Parsers::XML) - @doc = Nokogiri::XML::parse(@xml) - end - - describe '#parse_user_and_person' do - before(:each) do - @user, @person = @importer.parse_user_and_person(@doc) - end - - it 'should set username' do - @user.username.should == @old_user.username - end - - it 'should set private key' do - @user.serialized_private_key.should_not be nil - @user.serialized_private_key.should == @old_user.serialized_private_key - end - - end - - describe '#parse_aspects' do - let(:aspects) { @importer.parse_aspects(@doc) } - - it 'should return valid aspects' do - aspects.all?(&:valid?).should be true - end - - it 'should return an array' do - aspects.count.should == 6 - end - - it 'should should have post ids' do - aspects.any?{|x| x.post_ids.count > 0}.should be true - end - end - - describe '#parse_contacts' do - let(:contacts) { @importer.parse_contacts(@doc) } - - it 'should return an array' do - contacts.count.should == 4 - end - - it 'should should have post ids' do - contacts.all?{|x| x.aspect_names.count > 0}.should be true - end - - it 'should should have a person id' do - contacts.all?{|x| x.person_id.nil? || x.person_id == ""}.should be false - end - end - - describe '#parse_people' do - let(:people) { @importer.parse_people(@doc) } - - it 'should return an array' do - people.count.should == 4 - end - end - - describe '#parse_posts' do - let(:posts) { @importer.parse_posts(@doc) } - - it 'should return an array' do - posts.count.should == 4 - end - - it 'should return vaild posts' do - posts.all?(&:valid?).should be true - end - end - - end - - describe 'importing a user' do - - context '#execute' do - before(:each) do - # Generate exported XML for user1 - exporter = Diaspora::Exporter.new(Diaspora::Exporters::XML) - @xml = exporter.execute(@user1) - @username =@user1.username - # Remove user1 from the server - @user1.aspects.each( &:delete ) - @user1.friends.each( &:delete ) - @user1.raw_visible_posts.find_all_by_person_id(@user1.person.id).each( &:delete ) - @user1.delete - - @importer = Diaspora::Importer.new(Diaspora::Parsers::XML) - end - - it 'should import' do - pending "there is some weirdness with diaspora handle we need to look into... and this test needs love - the test passes when the validations are set to false when saving the user in the importer" - - User.delete_all - Person.delete_all - Post.delete_all - StatusMessage.delete_all - Aspect.delete_all - Contact.delete_all - - User.count.should == 0 - Person.count.should == 0 - - @importer.execute(@xml, - :email => "bob@bob.com", - :password => "bobbybob", - :password => "bobbybob", - :diaspora_handle => "#{@username}@#{APP_CONFIG[:terse_pod_url]}") - - User.count.should == 1 - n = User.first - Post.count.should == 4 - n.aspects.count.should == 6 - Person.count.should be == 5 - Contact.count.should be == 4 - - # need to check this - #User.first.person.diaspora_handle.should == User.first.diaspora_handle - User.first.diaspora_handle.should == "#{@username}@#{APP_CONFIG[:terse_pod_url]}" - - - Person.find_by_id( @user1.person.id ).nil?.should == false - Person.find_by_id( @user2.person.id ).nil?.should == false - - n.aspects.count.should == 6 - - people_count = 0 - n.aspects.each{|x| people_count += x.people.count } - people_count.should == 4 - - post_count = 0 - n.aspects.reload - n.aspects.each{ |x| post_count += x.post_ids.count } - post_count.should == 4 - - n.friends.count.should be 4 - end - end - end -end - diff --git a/spec/lib/hcard_spec.rb b/spec/lib/hcard_spec.rb index 8c75466f5ee29f58f966fc915e808cdef6a84968..fbd4bb42c50c536ed10d667792ada64281148edb 100644 --- a/spec/lib/hcard_spec.rb +++ b/spec/lib/hcard_spec.rb @@ -6,13 +6,13 @@ require 'spec_helper' require File.join(Rails.root, 'lib/hcard') describe HCard do - it 'should retreive and parse an hcard' do - stub_success("tom@tom.joindiaspora.com") - f = Redfinger.finger('tom@tom.joindiaspora.com') - hcard = HCard.find f.hcard.first[:href] + it 'should parse an hcard' do + raw_hcard = hcard_response + hcard = HCard.build raw_hcard hcard[:family_name].include?("Hamiltom").should be true hcard[:given_name].include?("Alex").should be true hcard[:photo].include?("tom.jpg").should be true - hcard[:url].should == "http://tom.joindiaspora.com/" + hcard[:url].should == "http://tom.joindiaspora.com/" + hcard[:searchable].should == "false" end end diff --git a/spec/lib/verify_spec.rb b/spec/lib/verify_spec.rb deleted file mode 100644 index 9dca1cb783e1eb6ea383500e2f0c8d8424ce0078..0000000000000000000000000000000000000000 --- a/spec/lib/verify_spec.rb +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' -require File.join(Rails.root, 'lib/diaspora/importer') - -describe Diaspora::Importer do - - let!(:user1) { make_user } - let!(:user2) { make_user } - let!(:user3) { make_user } - - let(:aspect1) { user1.aspects.create(:name => "Work") } - let(:aspect2) { user2.aspects.create(:name => "Family") } - let(:aspect3) { user3.aspects.create(:name => "Pivots") } - - let!(:status_message1) { user1.post(:status_message, :message => "One", :public => true, :to => aspect1.id) } - let!(:status_message2) { user1.post(:status_message, :message => "Two", :public => true, :to => aspect1.id) } - let!(:status_message3) { user2.post(:status_message, :message => "Three", :public => false, :to => aspect2.id) } - - let(:importer) { Diaspora::Importer.new(Diaspora::Parsers::XML) } - - context 'serialized user' do - describe '#verify_user' do - it 'should return true for a new valid user' do - new_user = make_user - new_user.delete - importer.verify_user(new_user).should be true - end - - it 'should return false if vaild user already exists' do - u = User.first - lambda{ importer.verify_user(user1) }.should raise_error - end - end - - describe '#verify_person_for_user' do - it 'should pass if keys match' do - importer.verify_person_for_user(user1, user1.person).should be true - end - - it 'should fail if private and public keys do not match' do - person = Factory(:person) - lambda{ importer.verify_person_for_user(user1, person) }.should raise_error - end - - it 'should pass if the person does not exist' do - user = Factory.build(:user) - importer.verify_person_for_user(user, user.person) - end - end - - describe 'verify contacts' do - let(:contact1) {Contact.new(:user => user1, :person => user2.person, :aspects => [aspect1])} - let(:contact2) {Contact.new(:user => user1, :person => user3.person, :aspects => [aspect2])} - let(:contact3) {Contact.new(:user => user1, :person => user3.person, :aspects => [aspect3])} - let(:less_contacts) {[contact1]} - let(:same_contacts) {[contact1, contact2]} - let(:more_contacts) {[contact1, contact2, contact3]} - - let(:person_ids) {[user2.person.id, user3.person.id]} - - - it 'should be false if the number of the number of contacts is not equal to the number of imported people' do - importer.verify_contacts(less_contacts, person_ids).should be false - importer.verify_contacts(same_contacts, person_ids).should be true - importer.verify_contacts(more_contacts, person_ids).should be false - end - end - - describe '#filter_posts' do - it 'should make sure all found posts are owned by the user' do - posts = [status_message1, status_message2] - whitelist = importer.filter_posts(posts, user1.person)[:whitelist] - - whitelist.should have(2).posts - whitelist.should include status_message1.id.to_s - whitelist.should include status_message2.id.to_s - end - - it 'should remove posts not owned by the user' do - posts = [status_message1, status_message2, status_message3] - whitelist = importer.filter_posts(posts, user1.person)[:whitelist] - - whitelist.should have(2).posts - whitelist.should_not include status_message3.id - end - - it 'should return a list of unknown posts' do - posts = [status_message1, status_message2, Factory.build(:status_message)] - unknown = importer.filter_posts(posts, user1.person)[:unknown] - - unknown.should have(1).post - end - - it 'should generate a whitelist, unknown posts inclusive' do - posts = [status_message1, status_message2, Factory.build(:status_message)] - filters = importer.filter_posts(posts, user1.person) - - filters[:whitelist].should include filters[:unknown].keys.first - end - end - - describe '#clean_aspects' do - it 'should purge posts not in whitelist that are present in aspects' do - whitelist = {status_message1.id.to_s => true, status_message2.id.to_s => true} - - aspect1.reload - aspect1.post_ids << status_message3.id.to_s - - proc{ importer.clean_aspects([aspect1], whitelist) }.should change(aspect1.post_ids, :count).by(-1) - aspect1.post_ids.should_not include status_message3.id - end - end - - describe '#filter_people' do - it 'should filter people who already exist in the database' do - new_peep = Factory.build(:person) - people = [user1.person, user2.person, new_peep] - - importer.filter_people(people).keys.should == [new_peep.id.to_s] - end - end - end -end diff --git a/spec/models/album_spec.rb b/spec/models/album_spec.rb index d8226c2dcc4e7da5366e0f475193bdf9937267bf..540d498298df7840a9a0905e51648c207154de43 100644 --- a/spec/models/album_spec.rb +++ b/spec/models/album_spec.rb @@ -23,6 +23,15 @@ describe Album do album.associations[:photos].type.should == :many end + it 'should be mutable' do + post = user.post :album, :name => "hello", :to => aspect.id + post.mutable?.should == true + end + + it 'has a diaspora_handle' do + album.diaspora_handle.should == user.diaspora_handle + end + context 'when an album has two attached images' do before do 2.times do @@ -65,4 +74,10 @@ describe Album do end end + describe 'serialization' do + it 'has a diaspora_handle' do + album.to_diaspora_xml.include?(user.diaspora_handle).should be_true + end + end + end diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index 498588fa85e8350d0ec031b5b8aed7a6a9d57841..a7ba0ca0d79ec1ac6b8bd968a05302e89c4b9eac 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -47,14 +47,15 @@ describe Person do @person.diaspora_handle.include?(APP_CONFIG[:terse_pod_url]).should be false end end + describe 'validation' do it 'is unique' do - person_two = Factory.build(:person, :url => @person.diaspora_handle) + person_two = Factory.build(:person, :diaspora_handle => @person.diaspora_handle) person_two.valid?.should be_false end it 'is case insensitive' do - person_two = Factory.build(:person, :url => @person.diaspora_handle.upcase) + person_two = Factory.build(:person, :url => @person.url.upcase) person_two.valid?.should be_false end end @@ -187,6 +188,16 @@ describe Person do people = Person.search("Casey Grippi") people.should == [@friend_four] end + + it 'should only display searchable people' do + invisible_person = Factory(:person, :profile => {:searchable => false, :first_name => "johnson"}) + Person.search("johnson").should_not include invisible_person + Person.search("").should_not include invisible_person + end + + it 'should search on handles' do + Person.search(@friend_one.diaspora_handle).should include @friend_one + end end context 'people finders for webfinger' do diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index f5d07fc552cce233acdbfc7a16e4ac593c526e23..f0e38fa4210cf4737000f6ecadcc065e01bc2040 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -16,6 +16,9 @@ describe Photo do @photo = Photo.new(:album => @album) @photo.person = @user.person + @photo.diaspora_handle = @user.person.diaspora_handle + + @photo2 = @user.post(:photo, :user_file=> File.open(@fixture_name), :to => @aspect.id) end describe "protected attributes" do @@ -31,6 +34,16 @@ describe Photo do end end + it 'should be mutable' do + @photo.mutable?.should == true + end + + describe '.instantiate' do + it 'sets the persons diaspora handle' do + @photo2.diaspora_handle.should == @user.person.diaspora_handle + end + end + it 'has a constructor' do image = File.open(@fixture_name) photo = Photo.instantiate( @@ -88,25 +101,23 @@ describe Photo do end - describe 'remote photos' do - it 'should write the url on serialization' do - @photo.image = File.open(@fixture_name) - @photo.image.store! - @photo.save - - xml = @photo.to_xml.to_s - - xml.include?(@photo.image.url).should be true - end - - it 'should have an album id on serialization' do + describe 'serialization' do + before do @photo.image.store! File.open(@fixture_name) - xml = @photo.to_xml.to_s - xml.include?(@photo.album_id.to_s).should be true + @xml = @photo.to_xml.to_s end - + it 'serializes the url' do + @xml.include?(@photo.image.url).should be true + end + it 'serializes the album_id' do + @xml.include?(@photo.album_id.to_s).should be true + end + it 'serializes the diaspora_handle' do + @xml.include?(@user.diaspora_handle).should be true + end + end + describe 'remote photos' do it 'should set the remote_photo on marshalling' do - pending "did the socket get unstubbed?" @photo.image.store! File.open(@fixture_name) @@ -114,10 +125,6 @@ describe Photo do user2 = Factory.create(:user) aspect2 = user2.aspects.create(:name => "foobars") friend_users(@user, @aspect, user2, aspect2) - @photo.person = user2.person - - @photo.save - #@photo.reload url = @photo.url thumb_url = @photo.url :thumb_medium @@ -126,7 +133,7 @@ describe Photo do id = @photo.id @photo.destroy - @user.receive xml, @photo.person + user2.receive xml, @user.person new_photo = Photo.first(:id => id) new_photo.url.nil?.should be false diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 587751b0ca036e003932792ea0dfe87d2652dd90..e4ca64938ca90093ecbd2a3537fe4a0edda10f45 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -29,5 +29,12 @@ describe Post do xml.include?(@user.person.diaspora_handle).should be true end end + + describe '#mutable?' do + it 'should be false by default' do + post = @user.post :status_message, :message => "hello", :to => @aspect.id + post.mutable?.should == false + end + end end diff --git a/spec/models/user/attack_vectors_spec.rb b/spec/models/user/attack_vectors_spec.rb index 8ee200dcee296842c4ff67d136809d46da6c541f..9f9b74f6bd50a05f6d3071f8703bc932735365c2 100644 --- a/spec/models/user/attack_vectors_spec.rb +++ b/spec/models/user/attack_vectors_spec.rb @@ -17,11 +17,6 @@ describe "attack vectors" do let(:user3) { make_user } let(:aspect3) { user3.aspects.create(:name => 'heroes') } - before do - friend_users(user, aspect, user2, aspect2) - friend_users(user, aspect, user3, aspect3) - end - context 'non-friend valid user' do it 'raises if receives post by non-friend' do @@ -41,7 +36,23 @@ describe "attack vectors" do end + it 'does not let a user attach to posts previously in the db unless its received from the author' do + friend_users(user, aspect, user3, aspect3) + + original_message = user2.post :status_message, :message => 'store this!', :to => aspect2.id + + original_message.diaspora_handle = user.diaspora_handle + user3.receive_salmon(user.salmon(original_message).xml_for(user3.person)) + user3.reload.visible_posts.should_not include(original_message) + end + context 'malicious friend attack vector' do + before do + friend_users(user, aspect, user2, aspect2) + friend_users(user, aspect, user3, aspect3) + end + + it 'overwrites messages with a different user' do original_message = user2.post :status_message, :message => 'store this!', :to => aspect2.id @@ -135,5 +146,18 @@ describe "attack vectors" do user.reload.friends.count.should == 2 end + + it 'does not let me update other persons post' do + original_message = user2.post :album, :name => 'store this!', :to => aspect2.id + user.receive_salmon(user2.salmon(original_message).xml_for(user.person)) + + original_message.diaspora_handle = user3.diaspora_handle + original_message.name = "bad bad bad" + xml = user3.salmon(original_message).xml_for(user.person) + user.receive_salmon(xml) + + original_message.reload.name.should == "store this!" + + end end end diff --git a/spec/models/user/receive_spec.rb b/spec/models/user/receive_spec.rb index 7d504f1d32fc8c966c6494981575e86687122fb6..e17b182b0fb716dd7ab7cc1aa22e0fe21d2e42f7 100644 --- a/spec/models/user/receive_spec.rb +++ b/spec/models/user/receive_spec.rb @@ -14,11 +14,21 @@ describe User do let(:user3) { make_user } let(:aspect3) { user3.aspects.create(:name => 'heroes') } + let(:status) {user.post(:status_message, :message => "Original", :to => aspect.id)} + let(:album) {user.post(:album, :name => "Original", :to => aspect.id)} before do friend_users(user, aspect, user2, aspect2) end + it 'should stream only one message to the everyone aspect when a multi-aspected friend posts' do + user.add_person_to_aspect(user2.person.id, user.aspects.create(:name => "villains").id) + status = user2.post(:status_message, :message => "Users do things", :to => aspect2.id) + xml = status.to_diaspora_xml + Diaspora::WebSocket.should_receive(:queue_to_user).exactly(:once) + user.receive xml, user2.person + end + it 'should be able to parse and store a status message from xml' do status_message = user2.post :status_message, :message => 'store this!', :to => aspect2.id @@ -41,6 +51,42 @@ describe User do user.aspects.size.should == num_aspects end + describe '#receive_salmon' do + it 'should handle the case where the webfinger fails' do + Person.should_receive(:by_account_identifier).and_return("not a person") + + proc{user2.receive_salmon(user.salmon(status).xml_for(user2.person))}.should_not raise_error + end + end + + context 'update posts' do + + it 'does not update posts not marked as mutable' do + user2.receive_salmon(user.salmon(status).xml_for(user2.person)) + status.message = 'foo' + xml = user.salmon(status).xml_for(user2.person) + + status.reload.message.should == 'Original' + + user2.receive_salmon(xml) + + status.reload.message.should == 'Original' + end + + it 'updates posts marked as mutable' do + user2.receive_salmon(user.salmon(album).xml_for(user2.person)) + album.name = 'foo' + xml = user.salmon(album).xml_for(user2.person) + + album.reload.name.should == 'Original' + + user2.receive_salmon(xml) + + album.reload.name.should == 'foo' + end + + end + describe 'post refs' do before do @status_message = user2.post :status_message, :message => "hi", :to =>aspect2.id @@ -113,11 +159,11 @@ describe User do post_in_db.comments.should == [] user2.receive_salmon(@xml) post_in_db.reload - + post_in_db.comments.include?(@comment).should be true post_in_db.comments.first.person.should == local_person end - + it 'should correctly marshal a stranger for the downstream user' do remote_person = user3.person remote_person.delete @@ -127,13 +173,13 @@ describe User do Person.should_receive(:by_account_identifier).twice.and_return{ |handle| if handle == user.person.diaspora_handle; user.person.save user.person; else; remote_person.save; remote_person; end } - + user2.reload.raw_visible_posts.size.should == 1 post_in_db = user2.raw_visible_posts.first post_in_db.comments.should == [] user2.receive_salmon(@xml) post_in_db.reload - + post_in_db.comments.include?(@comment).should be true post_in_db.comments.first.person.should == remote_person end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 0772246748f5b37753a9e63cebfb9abebd89a68d..55c5575fb2816bf708d48b7e3e5d3519033aa111 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -22,7 +22,6 @@ describe User do new_user.id.should_not == user.id end it 'does not overwrite old users with create' do - pending "Why do you want to set ids directly? MONGOMAPPERRRRR!!!" params = {:username => "ohai", :email => "ohai@example.com", :password => "password", @@ -163,13 +162,16 @@ describe User do } @user = User.build(params) end - it "makes a valid user" do - @user.should be_valid + it "does not save" do @user.persisted?.should be_false + @user.person.persisted?.should be_false User.find_by_username("ohai").should be_nil end it 'saves successfully' do + @user.should be_valid @user.save.should be_true + @user.persisted?.should be_true + @user.person.persisted?.should be_true User.find_by_username("ohai").should == @user end end