Merge branch 'master' of github.com:diaspora/diaspora into fb

Conflicts:
	config/routes.rb
This commit is contained in:
danielvincent 2010-09-22 16:09:25 -07:00
commit 8ed98270a6
34 changed files with 847 additions and 384 deletions

1
.gitignore vendored
View file

@ -13,3 +13,4 @@ gpg/diaspora-production/*.gpg
gpg/*/random_seed gpg/*/random_seed
public/uploads/* public/uploads/*
.rvmrc .rvmrc
config/app_config.yml

View file

@ -1,14 +1,23 @@
Diaspora is copyright Diaspora Inc., 2010, and files herein are licensed under the Affero General Public License version 3, the text of which can be found in GNU-AGPL-3.0, or any later version of the AGPL, unless otherwise noted. Components of Diaspora, including Rails, JQuery, and Devise, are licensed under the MIT/X11 license. Blueprint-CSS is licensed under a modified version of the MIT/X11 license. All unmodified files from these and other sources retain their original copyright and license notices: see the relevant individual files. Attribution information for Diaspora is contained in the AUTHORS file. Diaspora is copyright Diaspora Inc., 2010, and files herein are licensed
under the Affero General Public License version 3, the text of which can
be found in GNU-AGPL-3.0, or any later version of the AGPL, unless otherwise
noted. Components of Diaspora, including Rails, JQuery, and Devise, are
licensed under the MIT/X11 license. Blueprint-CSS is licensed under a
modified version of the MIT/X11 license. All unmodified files from these
and other sources retain their original copyright and license notices: see
the relevant individual files. Attribution information for Diaspora is
contained in the AUTHORS file.
* In addition, as a special exception, the copyright holders give In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations individual source file, and distribute linked combinations
* including the two. including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify You must obey the GNU Affero General Public License V3 or later in all respects
* file(s) with this exception, you may extend this exception to your for all of the code used other than OpenSSL or the components mentioned
* version of the file(s), but you are not obligated to do so. If you above. If you modify file(s) with this exception, you may extend this
* do not wish to do so, delete this exception statement from your exception to your version of the file(s), but you are not obligated to
* version. If you delete this exception statement from all source do so. If you do not wish to do so, delete this exception statement from your
* files in the program, then also delete it here. version. If you delete this exception statement from all source files in the
program, then also delete it here.

193
README.md
View file

@ -1,54 +1,87 @@
## Commit Guidlines ## Commit Guidlines
You are welcome to contribute, add and extend Diaspora however you see fit. We will do our best to incorporate everything that meets our guidelines.
We need you to fill out a [contributor agreement form](https://spreadsheets.google.com/a/joindiaspora.com/viewform?formkey=dGI2cHA3ZnNHLTJvbm10LUhXRTJjR0E6MQ&theme=0AX42CRMsmRFbUy1iOGYwN2U2Mi1hNWU0LTRlNjEtYWMyOC1lZmU4ODg1ODc1ODI&ifq) before we can accept your patches. The agreement gives Diaspora joint ownership of the patch so the copyright isn't scattered. You can find it [here](https://spreadsheets.google.com/a/joindiaspora.com/viewform?formkey=dGI2cHA3ZnNHLTJvbm10LUhXRTJjR0E6MQ&theme=0AX42CRMsmRFbUy1iOGYwN2U2Mi1hNWU0LTRlNjEtYWMyOC1lZmU4ODg1ODc1ODI&ifq). You are welcome to contribute, add to and extend Diaspora however you see fit. We
will do our best to incorporate everything that meets our guidelines.
All commits must be tested, and after each commit, all tests should be green before a pull request is sent. Please write your tests in Rspec. We need you to fill out a
[contributor agreement form](https://spreadsheets.google.com/a/joindiaspora.com/viewform?formkey=dGI2cHA3ZnNHLTJvbm10LUhXRTJjR0E6MQ&theme=0AX42CRMsmRFbUy1iOGYwN2U2Mi1hNWU0LTRlNjEtYWMyOC1lZmU4ODg1ODc1ODI&ifq)
before we can accept your patches. The agreement gives Diaspora joint
ownership of the patch so the copyright isn't scattered. You can find it
[here](https://spreadsheets.google.com/a/joindiaspora.com/viewform?formkey=dGI2cHA3ZnNHLTJvbm10LUhXRTJjR0E6MQ&theme=0AX42CRMsmRFbUy1iOGYwN2U2Mi1hNWU0LTRlNjEtYWMyOC1lZmU4ODg1ODc1ODI&ifq).
GEMS: We would like to keep external dependencies unduplicated. We're using Nokogiri, Mongomapper, and EM::HttpRequest as much as possible. We have a few gems in the project we'd rather not use, but if you can, use dependencies we already have. All commits must be tested, and after each commit, all tests should be green
before a pull request is sent. Please write your tests in Rspec.
GEMS: We would like to keep external dependencies unduplicated. We're using
Nokogiri, Mongomapper, and EM::HttpRequest as much as possible. We have a few
gems in the project we'd rather not use, but if you can, use dependencies we
already have.
# Diaspora # Diaspora
The privacy aware, personally controlled, do-it-all, open source social network. The privacy aware, personally controlled, do-it-all, open source social
network.
**DISCLAIMER: THIS IS PRE-ALPHA SOFTWARE AND SHOULD BE TREATED ACCORDINGLY.** **DISCLAIMER: THIS IS PRE-ALPHA SOFTWARE AND SHOULD BE TREATED ACCORDINGLY.**
**PLEASE, DO NOT RUN IN PRODUCTION. IT IS FUN TO GET RUNNING, BUT EXPECT THINGS TO BE BROKEN** **PLEASE, DO NOT RUN IN PRODUCTION. IT IS FUN TO GET RUNNING, BUT EXPECT THINGS
TO BE BROKEN**
Also, we really want to continue to focus on features and improving the code base. When we think it is We are continuing to build features and improve the code base.
ready for general use, we will post more detailed instructions. When we think it is ready for general use, we will post more detailed
instructions.
## Notice ## Notice
We currently run Diaspora with the [thin](http://code.macournoyer.com/thin/) as our webserver, behind [nginx](http://wiki.nginx.org/Main). Diaspora uses the asynchronous feature of [EventMachine](http://rubyeventmachine.com/) to send messages between seeds, We currently run Diaspora with the [thin](http://code.macournoyer.com/thin/) as
our webserver, behind [nginx](http://wiki.nginx.org/Main). Diaspora uses the
asynchronous feature of [EventMachine](http://rubyeventmachine.com/) to send
messages between seeds, using the power of the
[Reactor](http://en.wikipedia.org/wiki/Reactor_pattern) pattern. If you use
mod_rails, mongrel, or another non-eventmachine based application server,
federation and/or websockets may not work.
using the power of the [Reactor](http://en.wikipedia.org/wiki/Reactor_pattern) pattern. If you use mod_rails, mongrel, or another non-eventmachine based application server, federation and/or websockets may not work. If you don't like thin, you can always try
[Rainbows!](http://rainbows.rubyforge.org/) We will try and fully support more
webservers later, but that is what works for now.
If you don't like thin, you can always try [Rainbows!](http://rainbows.rubyforge.org/) These instructions are for machines running [Ubuntu](http://www.ubuntu.com/),
We will try and fully support more webservers later, but that is what works for now. [Fedora](http://www.fedoraproject.org) or Mac OS X. We are developing Diaspora
for the latest and greatest browsers, so please update your Firefox, Chrome or
Safari to the latest and greatest.
These instructions are for machines running [Ubuntu](http://www.ubuntu.com/), [Fedora](http://www.fedoraproject.org) or Mac OS X. We are developing Diaspora for the latest and greatest browsers, so please update your Firefox, Chrome or Safari to the latest and greatest.
## Preparing your system ## Preparing your system
In order to run Diaspora, you will need to download the following dependencies (specific instructions follow):
In order to run Diaspora, you will need to download the following dependencies
(specific instructions follow):
- Build Tools - Packages needed to compile the components that follow. - Build Tools - Packages needed to compile the components that follow.
- [Ruby](http://www.ruby-lang.org) - The Ruby programming language. (We're using **1.8.7**. It comes preinstalled on Mac OS X.) - [Ruby](http://www.ruby-lang.org) - The Ruby programming language.
(We're using **1.8.7**. It comes preinstalled on Mac OS X.)
- [MongoDB](http://www.mongodb.org) - A snappy noSQL database. - [MongoDB](http://www.mongodb.org) - A snappy noSQL database.
- [OpenSSL](http://www.openssl.org/) - An encryption library. (It comes preinstalled on Mac OS X and Ubuntu.) - [OpenSSL](http://www.openssl.org/) - An encryption library.
- [ImageMagick](http://www.imagemagick.org/) - An Image processing library used to resize uploaded photos. (It comes preinstalled on Mac OS X and Ubuntu.)
- [ImageMagick](http://www.imagemagick.org/) - An Image processing library used
to resize uploaded photos.
- [Git](http://git-scm.com/) - The fast version control system. - [Git](http://git-scm.com/) - The fast version control system.
After you have Ruby installed on your system, you will need to get RubyGems, then install Bundler: After you have Ruby installed on your system, you will need to get RubyGems,
then install Bundler:
- [RubyGems](http://rubygems.org/) - Source for Ruby gems. - [RubyGems](http://rubygems.org/) - Source for Ruby gems.
- [Bundler](http://gembundler.com/) - Gem management tool for Ruby projects. - [Bundler](http://gembundler.com/) - Gem management tool for Ruby projects.
**We suggest using a package management system to download these dependencies. Trust us, it's going to make your life a lot easier. If you're using Mac OS X, you can use [homebrew](http://mxcl.github.com/homebrew/); if you're using Ubuntu, just use [Synaptic](http://www.nongnu.org/synaptic/) (it comes pre-installed); if you're using Fedora simply use [yum](http://yum.baseurl.org/). The instructions below assume you have these installed.** **We suggest using a package management system to download these dependencies.
Trust us, it's going to make your life a lot easier. If you're using Mac OS X,
you can use [homebrew](http://mxcl.github.com/homebrew/); if you're using
Ubuntu, just use [Synaptic](http://www.nongnu.org/synaptic/) (it comes
pre-installed); if you're using Fedora simply use
[yum](http://yum.baseurl.org/). The instructions below assume you have these
installed.**
### Build Tools ### Build Tools
To install build tools on **Ubuntu**, run the following (includes the gcc and xml parsing dependencies): To install build tools on **Ubuntu**, run the following (includes the gcc and
xml parsing dependencies):
sudo apt-get install build-essential libxslt1.1 libxslt1-dev libxml2 sudo apt-get install build-essential libxslt1.1 libxslt1-dev libxml2
@ -56,7 +89,8 @@ To install build tools on **Fedora**, run the following:
sudo yum install libxslt libxslt-devel libxml2 libxml2-devel sudo yum install libxslt libxslt-devel libxml2 libxml2-devel
To install build tools on **Mac OS X**, you need to download and install [Xcode](http://developer.apple.com/technologies/tools/xcode.html). To install build tools on **Mac OS X**, you need to download and install
[Xcode](http://developer.apple.com/technologies/tools/xcode.html).
### Ruby ### Ruby
@ -64,22 +98,30 @@ To install Ruby 1.8.7 on **Ubuntu**, run the following command:
sudo apt-get install ruby-full sudo apt-get install ruby-full
Please note that you need to have Universe enabled in your /etc/apt/sources.list file to install ruby using apt-get. Please note that you need to have Universe enabled in your
/etc/apt/sources.list file to install ruby using apt-get.
At this time Fedora does not have Ruby 1.8.7. As a workaround it is possible to use [rvm](http://rvm.beginrescueend.com/) with a locally compiled Ruby installation. A semi automated method for doing this is available. It is highly recommended that you review the script before running it so you understand what will occur. The script can be executed by running the following command: At this time Fedora does not have Ruby 1.8.7. As a workaround it is possible to
use [rvm](http://rvm.beginrescueend.com/) with a locally compiled Ruby
installation. A semi automated method for doing this is available. It is
highly recommended that you review the script before running it so you
understand what will occur. The script can be executed by running the
following command:
./script/bootstrap-fedora-diaspora.sh ./script/bootstrap-fedora-diaspora.sh
After reviewing and executing the above script you will need to follow the "MongoDB" section and then you should skip all the way down to "Start Mongo". After reviewing and executing the above script you will need to follow the
"MongoDB" section and then you should skip all the way down to "Start Mongo".
If you're on **Mac OS X**, you already have Ruby on your system. Yay! If you're on **Mac OS X**, you already have Ruby on your system. Yay!
### MongoDB ### MongoDB
To install MongoDB on **Ubuntu**, add the official MongoDB repository [here](http://www.mongodb.org/display/DOCS/Ubuntu+and+Debian+packages). To install MongoDB on **Ubuntu**, add the official MongoDB repository
[here](http://www.mongodb.org/display/DOCS/Ubuntu+and+Debian+packages).
For Lucid, add the following line to your /etc/apt/sources.list (for other distros, see http://www.mongodb.org/display/DOCS/Ubuntu+and+Debian+packages): For Lucid, add the following line to your /etc/apt/sources.list (for other
distros, see http://www.mongodb.org/display/DOCS/Ubuntu+and+Debian+packages):
deb http://downloads.mongodb.org/distros/ubuntu 10.4 10gen deb http://downloads.mongodb.org/distros/ubuntu 10.4 10gen
@ -107,7 +149,10 @@ Then run:
sudo chmod -Rv 777 /data/ sudo chmod -Rv 777 /data/
To install MongoDB on a x86_64 **Fedora** system, add the official MongoDB repository from MongoDB (http://www.mongodb.org/display/DOCS/CentOS+and+Fedora+Packages) into /etc/yum.repos.d/10gen.repo: To install MongoDB on a x86_64 **Fedora** system, add the official MongoDB
repository from MongoDB
(http://www.mongodb.org/display/DOCS/CentOS+and+Fedora+Packages) into
/etc/yum.repos.d/10gen.repo:
[10gen] [10gen]
name=10gen Repository name=10gen Repository
@ -115,13 +160,14 @@ To install MongoDB on a x86_64 **Fedora** system, add the official MongoDB repos
gpgcheck=0 gpgcheck=0
enabled=1 enabled=1
Then use yum to install the packages: Then use yum to install the packages:
sudo yum install mongo-stable mongo-stable-server sudo yum install mongo-stable mongo-stable-server
If you're running a 32-bit system, run `wget
If you're running a 32-bit system, run `wget http://fastdl.mongodb.org/linux/mongodb-linux-i686-1.6.2.tgz`. If you're running a 64-bit system, run `wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-1.6.2.tgz`. http://fastdl.mongodb.org/linux/mongodb-linux-i686-1.6.2.tgz`. If you're
running a 64-bit system, run `wget
http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-1.6.2.tgz`.
# extract # extract
tar xzf mongodb-linux-i686-1.4.0.tgz tar xzf mongodb-linux-i686-1.4.0.tgz
@ -129,7 +175,6 @@ If you're running a 32-bit system, run `wget http://fastdl.mongodb.org/linux/mon
sudo mkdir -p /data/db sudo mkdir -p /data/db
sudo chmod -Rv 777 /data/ sudo chmod -Rv 777 /data/
To install MongoDB on **Mac OS X**, run the following: To install MongoDB on **Mac OS X**, run the following:
brew install mongo brew install mongo
@ -138,7 +183,8 @@ To install MongoDB on **Mac OS X**, run the following:
### OpenSSL ### OpenSSL
If you're running either **Ubuntu**, **Fedora** or **Mac OS X** you already have OpenSSL installed! If you're running either **Ubuntu**, **Fedora** or **Mac OS X** you already
have OpenSSL installed!
### ImageMagick ### ImageMagick
@ -178,60 +224,98 @@ On **Ubuntu** 10.04, run the following:
sudo apt-get update sudo apt-get update
sudo apt-get install rubygems sudo apt-get install rubygems
This PPA is maintained by an Ubuntu Developer. For Ubuntu 10.10, this version of rubygems is in the repositories. This PPA is maintained by an Ubuntu Developer. For Ubuntu 10.10, this version
of rubygems is in the repositories.
On **Fedora**, run the following: On **Fedora**, run the following:
sudo yum install rubygems sudo yum install rubygems
On **Mac OS X**, RubyGems comes preinstalled; however, you might need to update it for use with the latest Bundler. To update RubyGems, run `sudo gem update --system`. On **Mac OS X**, RubyGems comes preinstalled; however, you might need to update
it for use with the latest Bundler. To update RubyGems, run `sudo gem update
--system`.
### Bundler ### Bundler
After RubyGems is updated, simply run `sudo gem install bundler` to get Bundler. If you're using Ubuntu repository .debs, bundler is found at /var/lib/gems/1.8/bin/bundle After RubyGems is updated, simply run `sudo gem install bundler` to get
Bundler. If you're using Ubuntu repository .debs, bundler is found at
/var/lib/gems/1.8/bin/bundle
## Getting Diaspora ## Getting Diaspora
git clone http://github.com/diaspora/diaspora.git git clone http://github.com/diaspora/diaspora.git
If you have never used github before, their [help desk](http://help.github.com/) has a pretty awesome guide on getting setup. If you have never used github before, their
[help desk](http://help.github.com/) has a pretty awesome guide on getting
setup.
## Running Diaspora ## Running Diaspora
### Install required gems ### Install required gems
To start the app server for the first time, you need to use Bundler to install Diaspora's gem depencencies. Run `bundle install` from Diaspora's root directory. Bundler will also warn you if there is a new dependency and you need to bundle install again.
To start the app server for the first time, you need to use Bundler to install
Diaspora's gem depencencies. Run `bundle install` from Diaspora's root
directory. Bundler will also warn you if there is a new dependency and you
need to bundle install again.
### Start Mongo ### Start Mongo
If you installed the Ubuntu package, MongoDB should already be running (if not, run `service mongodb start`). If you installed the binary manually, run `sudo mongod` from where mongo is installed to start mongo.
If you installed the Fedora package, MongoDB will need to be started via `service mongodb start`. If you installed the binary manually, run `sudo mongod` from where Mongo is installed to start Mongo. If you installed the Ubuntu package, MongoDB should already be running (if not,
run `service mongodb start`). If you installed the binary manually, run `sudo
mongod` from where mongo is installed to start mongo.
If you installed the OsX package through "brew", MongoDB will need to be started via `sudo launchctl load /Library/LaunchDaemons/org.mongodb.mongod.plist`. (before you have to go to /Library/LaunchDaemons and add a symlink to /usr/local/Cellar/mongodb/1.6.2-x86_64/org.mongodb.mongod.plist) If you installed the Fedora package, MongoDB will need to be started via
`service mongodb start`. If you installed the binary manually, run `sudo
mongod` from where Mongo is installed to start Mongo.
Diaspora will not run unless Mongo is running. Mongo will not run by default, and will need to be started every time you wish to use or run the test suite for Diaspora. If you installed the OsX package through "brew", MongoDB will need to be
started via `sudo launchctl load
/Library/LaunchDaemons/org.mongodb.mongod.plist`. (before you have to go to
/Library/LaunchDaemons and add a symlink to
/usr/local/Cellar/mongodb/1.6.2-x86_64/org.mongodb.mongod.plist)
Diaspora will not run unless Mongo is running. Mongo will not run by default,
and will need to be started every time you wish to use or run the test suite
for Diaspora.
### Run the server ### Run the server
`./script/server` will start both thin and the websocket server. If you want to run a different app server, you will have to run them separately. See below for instructions.
`./script/server` will start both thin and the websocket server. If you want
to run a different app server, you will have to run them separately. See below
for instructions.
### Run the app server ### Run the app server
Once mongo is running and bundler has finished, run `bundle exec thin start` from the root Diaspora directory. This will start the app server in development mode[.](http://bit.ly/9mwtUw)
Once mongo is running and bundler has finished, run `bundle exec thin start`
from the root Diaspora directory. This will start the app server in
development mode[.](http://bit.ly/9mwtUw)
### Run the websocket server ### Run the websocket server
run `bundle exec ruby ./script/websocket_server` to start the websocket server on port 8080. Change the port in config/app_config.yml.
run `bundle exec ruby ./script/websocket_server` to start the websocket server
on port 8080. Change the port in config/app_config.yml.
### Logging in with a sample user ### Logging in with a sample user
Run `rake db:seed:tom`, then login with user `tom` and password `evankorth`. More details in db/seeds/tom.rb.
Run `rake db:seed:tom`, then login with user `tom` and password `evankorth`.
More details in db/seeds/tom.rb.
### Testing ### Testing
Diaspora's test suite uses [rspec](http://rspec.info/), a behavior driven testing framework. In order to run the tests, run `bundle exec rspec spec`.
Diaspora's test suite uses [rspec](http://rspec.info/), a behavior driven
testing framework. In order to run the tests, run `bundle exec rspec spec`.
## Resources ## Resources
We are maintaining a [public tracker project](http://www.pivotaltracker.com/projects/61641) and a [roadmap](https://github.com/diaspora/diaspora/wiki/Roadmap). Also, you can file [bug reports](https://github.com/diaspora/diaspora/issues) right here on github. We are maintaining a
[public tracker project](http://www.pivotaltracker.com/projects/61641)
and a
[roadmap](https://github.com/diaspora/diaspora/wiki/Roadmap). Also, you can
file [bug reports](https://github.com/diaspora/diaspora/issues) right here on
github.
Ongoing discussion: Ongoing discussion:
- [Diaspora Developer Google Group](http://groups.google.com/group/diaspora-dev) - [Diaspora Developer Google Group](http://groups.google.com/group/diaspora-dev)
@ -240,6 +324,11 @@ Ongoing discussion:
- [#diaspora-dev IRC channel](irc://irc.freenode.net/#diaspora-dev) - [#diaspora-dev IRC channel](irc://irc.freenode.net/#diaspora-dev)
([join via the web client](http://webchat.freenode.net?channels=diaspora-dev)) ([join via the web client](http://webchat.freenode.net?channels=diaspora-dev))
More general info and updates about the project can be found on our [blog](http://joindiaspora.com), [and on Twitter](http://twitter.com/joindiaspora). Also, be sure to join the official [mailing list](http://http://eepurl.com/Vebk). More general info and updates about the project can be found on:
[Our blog](http://joindiaspora.com),
[and on Twitter](http://twitter.com/joindiaspora).
Also, be sure to join the official [mailing list](http://http://eepurl.com/Vebk).
If you wish to contact us privately about any exploits in Diaspora you may find, you can email [exploits@joindiaspora.com](mailto:exploits@joindiaspora.com). If you wish to contact us privately about any exploits in Diaspora you may
find, you can email
[exploits@joindiaspora.com](mailto:exploits@joindiaspora.com).

View file

@ -52,7 +52,7 @@ class AlbumsController < ApplicationController
data = clean_hash(params[:album]) data = clean_hash(params[:album])
if @album.update_attributes data if current_user.update_post( @album, data )
flash[:notice] = "Album #{@album.name} successfully edited." flash[:notice] = "Album #{@album.name} successfully edited."
respond_with @album respond_with @album
else else

View file

@ -10,10 +10,7 @@ class PhotosController < ApplicationController
respond_to :json, :only => :show respond_to :json, :only => :show
def create def create
album = Album.find_by_id params[:album_id] album = Album.find_by_id params[:album_id]
puts params
begin begin
######################## dealing with local files ############# ######################## dealing with local files #############
@ -91,7 +88,7 @@ class PhotosController < ApplicationController
data = clean_hash(params) data = clean_hash(params)
if @photo.update_attributes data[:photo] if current_user.update_post( @photo, data[:photo] )
flash[:notice] = "Photo successfully updated." flash[:notice] = "Photo successfully updated."
respond_with @photo respond_with @photo
else else

View file

@ -47,8 +47,8 @@ class RequestsController < ApplicationController
begin begin
@request = current_user.send_friend_request_to(rel_hash[:friend], aspect) @request = current_user.send_friend_request_to(rel_hash[:friend], aspect)
rescue Exception => e rescue Exception => e
raise e unless e.message.include? "already friends" raise e unless e.message.include? "already"
flash[:notice] = "You are already friends with #{params[:request][:destination_url]}!" flash[:notice] = "#{e.message} #{params[:request][:destination_url]}"
respond_with :location => aspect respond_with :location => aspect
return return
end end

View file

@ -32,7 +32,6 @@ module RequestsHelper
def relationship_flow(identifier) def relationship_flow(identifier)
action = :none action = :none
person = nil person = nil
puts identifier
person = Person.by_webfinger identifier person = Person.by_webfinger identifier
if person if person
action = (person == current_user.person ? :none : :friend) action = (person == current_user.person ? :none : :friend)

View file

@ -104,8 +104,8 @@ class Person
return nil unless public_key_entry return nil unless public_key_entry
public_key = public_key_entry.first.href pubkey = public_key_entry.first.href
new_person.exported_key = Base64.decode64 public_key new_person.exported_key = Base64.decode64 pubkey
guid = profile.links.select{|x| x.rel == 'http://joindiaspora.com/guid'}.first.href guid = profile.links.select{|x| x.rel == 'http://joindiaspora.com/guid'}.first.href
new_person.id = guid new_person.id = guid

View file

@ -5,12 +5,14 @@
require 'lib/diaspora/user/friending.rb' require 'lib/diaspora/user/friending.rb'
require 'lib/diaspora/user/querying.rb' require 'lib/diaspora/user/querying.rb'
require 'lib/diaspora/user/receiving.rb'
require 'lib/salmon/salmon' require 'lib/salmon/salmon'
class User class User
include MongoMapper::Document include MongoMapper::Document
include Diaspora::UserModules::Friending include Diaspora::UserModules::Friending
include Diaspora::UserModules::Querying include Diaspora::UserModules::Querying
include Diaspora::UserModules::Receiving
include Encryptor::Private include Encryptor::Private
QUEUE = MessageHandler.new QUEUE = MessageHandler.new
@ -23,8 +25,6 @@ class User
key :visible_post_ids, Array key :visible_post_ids, Array
key :visible_person_ids, Array key :visible_person_ids, Array
key :url, String
one :person, :class_name => 'Person', :foreign_key => :owner_id one :person, :class_name => 'Person', :foreign_key => :owner_id
many :friends, :in => :friend_ids, :class_name => 'Person' many :friends, :in => :friend_ids, :class_name => 'Person'
@ -95,8 +95,6 @@ class User
######## Posting ######## ######## Posting ########
def post(class_name, options = {}) def post(class_name, options = {})
puts options.inspect
if class_name == :photo if class_name == :photo
raise ArgumentError.new("No album_id given") unless options[:album_id] raise ArgumentError.new("No album_id given") unless options[:album_id]
aspect_ids = aspects_with_post( options[:album_id] ) aspect_ids = aspects_with_post( options[:album_id] )
@ -105,20 +103,47 @@ class User
aspect_ids = options.delete(:to) aspect_ids = options.delete(:to)
end end
aspect_ids = [aspect_ids.to_s] if aspect_ids.is_a? BSON::ObjectId aspect_ids = validate_aspect_permissions(aspect_ids)
raise ArgumentError.new("You must post to someone.") if aspect_ids.nil? || aspect_ids.empty? intitial_post(class_name, aspect_ids, options)
aspect_ids.each{ |aspect_id| end
raise ArgumentError.new("Cannot post to an aspect you do not own.") unless aspect_id == "all" || self.aspects.find(aspect_id) }
def intitial_post(class_name, aspect_ids, options = {})
post = build_post(class_name, options) post = build_post(class_name, options)
post.socket_to_uid(id, :aspect_ids => aspect_ids) if post.respond_to?(:socket_to_uid) post.socket_to_uid(id, :aspect_ids => aspect_ids) if post.respond_to?(:socket_to_uid)
push_to_aspects(post, aspect_ids) push_to_aspects(post, aspect_ids)
post post
end end
def repost( post, options = {} )
aspect_ids = validate_aspect_permissions(options[:to])
push_to_aspects(post, aspect_ids)
post
end
def update_post( post, post_hash = {} )
if self.owns? post
post.update_attributes(post_hash)
end
end
def validate_aspect_permissions(aspect_ids)
aspect_ids = [aspect_ids.to_s] if aspect_ids.is_a? BSON::ObjectId
if aspect_ids.nil? || aspect_ids.empty?
raise ArgumentError.new("You must post to someone.")
end
aspect_ids.each do |aspect_id|
unless aspect_id == "all" || self.aspects.find(aspect_id)
raise ArgumentError.new("Cannot post to an aspect you do not own.")
end
end
aspect_ids
end
def build_post( class_name, options = {}) def build_post( class_name, options = {})
options[:person] = self.person options[:person] = self.person
model_class = class_name.to_s.camelize.constantize model_class = class_name.to_s.camelize.constantize
@ -221,86 +246,10 @@ class User
end end
end end
###### Receiving #######
def receive_salmon ciphertext
cleartext = decrypt( ciphertext)
salmon = Salmon::SalmonSlap.parse cleartext
if salmon.verified_for_key?(salmon.author.public_key)
Rails.logger.info("data in salmon: #{salmon.data}")
self.receive(salmon.data)
end
end
def receive xml
object = Diaspora::Parser.from_xml(xml)
Rails.logger.debug("Receiving object for #{self.real_name}:\n#{object.inspect}")
Rails.logger.debug("From: #{object.person.inspect}") if object.person
if object.is_a? Retraction
if object.type == 'Person'
Rails.logger.info( "the person id is #{object.post_id} the friend found is #{visible_person_by_id(object.post_id).inspect}")
unfriended_by visible_person_by_id(object.post_id)
else
object.perform self.id
aspects = self.aspects_with_person(object.person)
aspects.each{ |aspect| aspect.post_ids.delete(object.post_id.to_id)
aspect.save
}
end
elsif object.is_a? Request
person = Diaspora::Parser.parse_or_find_person_from_xml( xml )
person.serialized_key ||= object.exported_key
object.person = person
object.person.save
old_request = Request.first(:id => object.id)
object.aspect_id = old_request.aspect_id if old_request
object.save
receive_friend_request(object)
elsif object.is_a? Profile
person = Diaspora::Parser.owner_id_from_xml xml
person.profile = object
person.save
elsif object.is_a?(Comment)
object.person = Diaspora::Parser.parse_or_find_person_from_xml( xml ).save if object.person.nil?
self.visible_people = self.visible_people | [object.person]
self.save
Rails.logger.debug("The person parsed from comment xml is #{object.person.inspect}") unless object.person.nil?
object.person.save
Rails.logger.debug("From: #{object.person.inspect}") if object.person
raise "In receive for #{self.real_name}, signature was not valid on: #{object.inspect}" unless object.post.person == self.person || object.verify_post_creator_signature
object.save
unless owns?(object)
dispatch_comment object
end
object.socket_to_uid(id) if (object.respond_to?(:socket_to_uid) && !self.owns?(object))
else
Rails.logger.debug("Saving object: #{object}")
object.user_refs += 1
object.save
self.raw_visible_posts << object
self.save
aspects = self.aspects_with_person(object.person)
aspects.each{ |aspect|
aspect.posts << object
aspect.save
object.socket_to_uid(id, :aspect_ids => [aspect.id]) if (object.respond_to?(:socket_to_uid) && !self.owns?(object))
}
end
end
###Helpers############ ###Helpers############
def self.instantiate!( opts = {} ) def self.instantiate!( opts = {} )
hostname = opts[:url].gsub(/(https?:|www\.)\/\//, '') opts[:person][:diaspora_handle] = "#{opts[:username]}@#{APP_CONFIG[:terse_pod_url]}"
hostname.chop! if hostname[-1, 1] == '/' opts[:person][:url] = APP_CONFIG[:pod_url]
opts[:person][:diaspora_handle] = "#{opts[:username]}@#{hostname}"
puts opts[:person][:diaspora_handle]
opts[:person][:serialized_key] = generate_key opts[:person][:serialized_key] = generate_key
User.create(opts) User.create(opts)
end end
@ -311,7 +260,7 @@ else
end end
def terse_url def terse_url
terse = self.url.gsub(/(https?:|www\.)\/\//, '') terse = APP_CONFIG[:pod_url].gsub(/(https?:|www\.)\/\//, '')
terse = terse.chop! if terse[-1, 1] == '/' terse = terse.chop! if terse[-1, 1] == '/'
terse terse
end end

View file

@ -10,7 +10,7 @@
= f.label :username = f.label :username
= f.text_field :username = f.text_field :username
%p.user_network %p.user_network
="@#{request.host}" ="@#{APP_CONFIG[:pod_url]}"
%p %p
= f.label :password = f.label :password

View file

@ -2,7 +2,6 @@
= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| = form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f|
= f.hidden_field :url, :value => request.host
%p %p
= f.label :username = f.label :username
= f.text_field :username = f.text_field :username
@ -17,8 +16,6 @@
= f.password_field :password_confirmation = f.password_field :password_confirmation
= f.fields_for :person do |p| = f.fields_for :person do |p|
= p.hidden_field :url, :value => request.host
= p.fields_for :profile do |pr| = p.fields_for :profile do |pr|
%p %p
= pr.label :first_name = pr.label :first_name

View file

@ -10,7 +10,7 @@
= f.error_messages = f.error_messages
%p %p
%label{:for => "status_message_message"} Message %label{:for => "status_message_message"} Message
= f.text_area :message, :rows => 2 = f.text_area :message, :rows => 2, :value => params[:prefill]
%ul.aspect_selector{ :style => "display:none;"} %ul.aspect_selector{ :style => "display:none;"}
going to... going to...

View file

@ -0,0 +1,27 @@
-# Copyright (c) 2010, Diaspora Inc. This file is
-# licensed under the Affero General Public License version 3. See
-# the COPYRIGHT file.
:javascript
$(".reshare_button").toggle(function(e){
e.preventDefault();
$(this).parent(".reshare_pane").children(".reshare_box").fadeIn(200);
}, function(e) {
e.preventDefault();
$(this).parent(".reshare_pane").children(".reshare_box").fadeOut(200);
});
.reshare_pane
%span.reshare_button
= link_to "Reshare", "#"
%ul.reshare_box
- for aspect in current_user.aspects_with_post( post.id )
%li.currently_sharing= aspect.name
- for aspect in current_user.aspects
- unless aspect.posts.include? post
%li.aspect_to_share= link_to aspect, :controller => "aspects", :action => "show", :id => aspect.id, :prefill => post.message

View file

@ -22,3 +22,5 @@
- if current_user.owns?(post) - if current_user.owns?(post)
.destroy_link .destroy_link
= link_to 'Delete', status_message_path(post), :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "delete" = link_to 'Delete', status_message_path(post), :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "delete"
= render "shared/reshare", :post => post, :current_user => current_user

View file

@ -17,11 +17,11 @@
%h3 Picture %h3 Picture
%div#image_picker %div#image_picker
= p.hidden_field :image_url, :value => (@profile.image_url.sub(@user.url,'/') if @profile.image_url), :id => 'image_url_field' = p.hidden_field :image_url, :value => (@profile.image_url if @profile.image_url), :id => 'image_url_field'
- unless @photos.nil? || @photos.empty? - unless @photos.nil? || @photos.empty?
- for photo in @photos - for photo in @photos
- if @profile.image_url && (photo.url(:thumb_medium) == @profile.image_url.sub(@user.url,'/')) - if @profile.image_url && @profile.image_url.include?(photo.url(:thumb_medium))
%div.small_photo{:id => photo.url(:thumb_medium), :class=>'selected'} %div.small_photo{:id => photo.url(:thumb_medium), :class=>'selected'}
= check_box_tag 'checked_photo', true, true = check_box_tag 'checked_photo', true, true
= link_to image_tag(photo.url(:thumb_medium)), "#" = link_to image_tag(photo.url(:thumb_medium)), "#"

View file

@ -3,8 +3,8 @@
# the COPYRIGHT file. # the COPYRIGHT file.
default:
development: pod_url: "http://example.org/"
debug: false debug: false
socket_debug : false socket_debug : false
socket_host: 0.0.0.0 socket_host: 0.0.0.0
@ -14,20 +14,10 @@ development:
mongo_host: 'localhost' mongo_host: 'localhost'
mongo_post: 27017 mongo_post: 27017
development:
test: test:
debug: false pod_url: "http://example.org/"
socket_debug : false
socket_host: 0.0.0.0
socket_port: 8081 socket_port: 8081
pubsub_server: 'https://pubsubhubbub.appspot.com/'
mongo_host: 'localhost'
mongo_post: 27017
production: production:
debug: false
socket_debug : false
socket_host: 0.0.0.0
socket_port: 8080
pubsub_server: 'https://pubsubhubbub.appspot.com/'
mongo_host: 'localhost'
mongo_post: 27017

View file

@ -51,5 +51,6 @@ module Diaspora
# Configure sensitive parameters which will be filtered from the log file. # Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password] config.filter_parameters += [:password]
config.filter_parameters += [:xml]
end end
end end

View file

@ -53,6 +53,11 @@ namespace :deploy do
run "ln -s -f #{shared_path}/bundle #{current_path}/vendor/bundle" run "ln -s -f #{shared_path}/bundle #{current_path}/vendor/bundle"
end end
task :symlink_config do
run "touch #{shared_path}/app_config.yml"
run "ln -s -f #{shared_path}/app_config.yml #{current_path}/config/app_config.yml"
end
task :start do task :start do
start_mongo start_mongo
start_thin start_thin
@ -150,4 +155,4 @@ namespace :db do
end end
after "deploy:symlink", "deploy:symlink_images", "deploy:symlink_bundle" after "deploy:symlink", "deploy:symlink_images", "deploy:symlink_bundle", 'deploy:symlink_config'

View file

@ -2,6 +2,25 @@
# licensed under the Affero General Public License version 3. See # licensed under the Affero General Public License version 3. See
# the COPYRIGHT file. # the COPYRIGHT file.
def load_config_yaml filename
YAML.load(File.read(filename))
end
raw_config = File.read("#{Rails.root}/config/app_config.yml") if File.exist? "#{Rails.root}/config/app_config.yml"
APP_CONFIG = YAML.load(raw_config)[Rails.env].symbolize_keys all_envs = load_config_yaml "#{Rails.root}/config/app_config.yml"
all_envs = load_config_yaml "#{Rails.root}/config/app_config.yml.example" unless all_envs
else
puts "WARNING: No config/app_config.yml found! Look at config/app_config.yml.example for help."
all_envs = load_config_yaml "#{Rails.root}/config/app_config.yml.example"
end
if all_envs[Rails.env.to_s]
APP_CONFIG = all_envs['default'].merge(all_envs[Rails.env.to_s]).symbolize_keys
else
APP_CONFIG = all_envs['default'].symbolize_keys
end
APP_CONFIG[:terse_pod_url] = APP_CONFIG[:pod_url].gsub(/(https?:|www\.)\/\//, '')
APP_CONFIG[:terse_pod_url].chop! if APP_CONFIG[:terse_pod_url][-1, 1] == '/'
puts "WARNING: Please modify your app_config.yml to have a proper pod_url!" if APP_CONFIG[:terse_pod_url] == "example.org" && Rails.env != :test

View file

@ -7,4 +7,137 @@
# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
pt-BR: pt-BR:
hello: "Olá Mundo" hello: "Olá mundo"
layouts:
application:
edit_profile: "editar perfil"
logout: "sair"
shared:
aspect_nav:
all_aspects: "Todos Aspectos"
manage: "Gerenciar"
manage_your_aspects: "Gerencie seus Aspectos"
sub_header:
all_aspects: "Todos Aspectos"
manage_aspects: "Gerenciar Aspectos"
publisher:
share: "Compartilhar"
aspect_friends:
add_friends: "adicionar amigos"
albums:
album:
you: "você"
new_album:
create: "criar"
add_a_new_album: "Adicionar novo álbum"
show:
edit_album: "Editar Álbum"
albums: "álbuns"
updated: "atualizado"
by: "por"
edit:
editing: "Editando"
updated: "atualizado"
are_you_sure: "Tem certeza?"
delete_album: "Excluir Álbum"
cancel: "Cancelar"
index:
home: "home"
new_album: "Novo Álbum"
create:
success: "Você criou com sucesso um álbum chamado %{name}."
update:
success: "O álbum %{name} foi editado com sucesso."
failure: "Erro ao editar o álbum %{name}."
destroy:
success: "O álbum %{name} foi excluído com sucesso."
aspects:
index:
photos: "photos"
show:
photos: "photos"
manage:
add_a_new_aspect: "Adicionar um novo aspecto"
add_a_new_friend: "Adicionar um novo amigo"
show: "Exibir"
update_aspects: "Atualizar Aspectos"
requests: "Solicitações"
ignore_remove: "Ignorar/Excluir"
new_aspect:
add_a_new_aspect: "Adicionar um novo aspecto"
create: "Criar"
create:
success:"Clique no mais(+) do lado esquerdo para dizer ao Diaspora quem pode ver seu novo aspecto."
users:
edit:
cancel: "Cancelar"
update_profile: "Atualizar Perfil"
home: "Home"
diaspora_username: "USUÁRIO DIASPORA"
info: "Informações"
picture: "Imagem"
editing_profile: "Editando perfil"
albums: "Álbuns"
you_dont_have_any_photos: "Você não possui nenhuma photo! Vá para"
page_to_upload_some: "para fazer o upload de alguma."
comments:
comment:
ago: "atrás"
new_comment:
comment: "Comentário"
photos:
show:
prev: "anterior"
full_size: "tamanho máximo"
next: "próxima"
edit_photo: "Editar Foto"
delete_photo: "Excluir Foto"
are_you_sure: "Tem certeza?"
comments: "comentários"
edit:
editing: "Editando"
are_you_sure: "Tem certeza?"
delete_photo: "Excluir Foto"
photo:
show_comments: "exibir comentários"
posted_a_new_photo_to: "enviada um nova foto para"
new:
new_photo: "Nova Foto"
back_to_list: "Voltar para a Lista"
post_it: "enviar!"
registrations:
new:
sign_up: "Cadastro"
status_messages:
new_status_message:
tell_me_something_good: "diga-me qualquer coisa legal"
oh_yeah: "É isso aí!"
status_message:
show_comments: "exibir comentários"
delete: "Excluir"
are_you_sure: "Tem certeza?"
show:
status_message: "Mensagem de Status"
comments: "comentários"
are_you_sure: "Tem certeza?"
destroy: "Excluir"
view_all: "Exibir Todas"
message: "Mensagem"
owner: "Pertence a"
people:
index:
add_friend: "adicionar amigo(a)"
real_name: "nome real"
diaspora_handle: "diaspora handle"
thats_you: "esse é você!"
friend_request_pending: "pedido de amizade pendente"
you_have_a_friend_request_from_this_person: "você possui um pedido de amizade dessa pessoa"
new:
new_person: "Nova Pessoa"
back_to_list: "Voltar para a Lista"
show:
last_seen: "visto pela última vez a: %{how_long_ago}"
friends_since: "amigos desde: %{how_long_ago}"
save: "salvar"
are_you_sure: "Tem certeza?"
remove_friend: "excluir amigo"

View file

@ -15,25 +15,38 @@
require 'config/environment' require 'config/environment'
def create def create
config = YAML.load_file(File.dirname(__FILE__) + '/../../config/deploy_config.yml') config = YAML.load_file(File.dirname(__FILE__) + '/../../config/deploy_config.yml')
backer_info = config['servers']['backer'] backer_info = config['servers']['backer']
backer_number = YAML.load_file(Rails.root.join('config','backer_number.yml'))[:seed_number].to_i backer_number = YAML.load_file(Rails.root.join('config','backer_number.yml'))[:seed_number].to_i
# Create seed user
#set pod url
username = backer_info[backer_number]['username'].gsub(/ /,'').downcase username = backer_info[backer_number]['username'].gsub(/ /,'').downcase
set_app_config username
require 'config/initializers/_load_app_config.rb'
# Create seed user
user = User.instantiate!(:email => "#{username}@#{username}.joindiaspora.com", user = User.instantiate!(:email => "#{username}@#{username}.joindiaspora.com",
:username => username, :username => username,
:password => "#{username+backer_info[backer_number]['pin'].to_s}", :password => "#{username+backer_info[backer_number]['pin'].to_s}",
:password_confirmation => "#{username+backer_info[backer_number]['pin'].to_s}", :password_confirmation => "#{username+backer_info[backer_number]['pin'].to_s}",
:url=> "http://#{username}.joindiaspora.com/",
:person => Person.new( :person => Person.new(
:diaspora_handle => "#{username}@#{username}.joindiaspora.com",
:profile => Profile.new( :first_name => backer_info[backer_number]['given_name'], :last_name => backer_info[backer_number]['family_name'], :profile => Profile.new( :first_name => backer_info[backer_number]['given_name'], :last_name => backer_info[backer_number]['family_name'],
:image_url => "http://#{username}.joindiaspora.com/images/user/#{username}.jpg"), :image_url => "http://#{username}.joindiaspora.com/images/user/#{username}.jpg")
:url=> "http://#{username}.joindiaspora.com/") ))
)
user.person.save! user.person.save!
user.aspect(:name => "Presidents") user.aspect(:name => "Presidents")
end end
def set_app_config username
current_config = YAML.load(File.read(Rails.root.join('config', 'app_config.yml.example')))
current_config[Rails.env.to_s] ||= {}
current_config[Rails.env.to_s]['pod_url'] = "#{username}.joindiaspora.com"
current_config['default']['pod_url'] = "#{username}.joindiaspora.com"
file = File.new(Rails.root.join('..','..','shared','app_config.yml'),'w')
file.write(current_config.to_yaml)
file.close
end

View file

@ -6,31 +6,35 @@
require 'config/environment' require 'config/environment'
host = "localhost:3000" def set_app_config username
url = "http://#{host}/" current_config = YAML.load(File.read(Rails.root.join('config', 'app_config.yml.example')))
current_config[Rails.env.to_s] ||= {}
current_config[Rails.env.to_s]['pod_url'] = "#{username}.joindiaspora.com"
current_config['default']['pod_url'] = "#{username}.joindiaspora.com"
file = File.new(Rails.root.join('config','app_config.yml'),'w')
file.write(current_config.to_yaml)
file.close
end
username = "tom" username = "tom"
set_app_config username
# Create seed user # Create seed user
user = User.instantiate!( :email => "tom@tom.joindiaspora.com", user = User.instantiate!( :email => "tom@tom.joindiaspora.com",
:username => "tom", :username => "tom",
:password => "evankorth", :password => "evankorth",
:password_confirmation => "evankorth", :password_confirmation => "evankorth",
:url=> "http://#{username}.joindiaspora.com/"
:person => Person.new( :person => Person.new(
:diaspora_handle => "tom@tom.joindiaspora.com",
:url => url,
:profile => Profile.new( :first_name => "Alexander", :last_name => "Hamiltom" )) :profile => Profile.new( :first_name => "Alexander", :last_name => "Hamiltom" ))
) )
user.person.save! user.person.save!
user2 = User.instantiate!( :email => "korth@tom.joindiaspora.com", user2 = User.instantiate!( :email => "korth@tom.joindiaspora.com",
:username => "korth", :username => "korth",
:url=> "http://#{username}.joindiaspora.com/"
:password => "evankorth", :password => "evankorth",
:password_confirmation => "evankorth", :password_confirmation => "evankorth",
:person => Person.new( :diaspora_handle => "korth@tom.joindiaspora.com", :person => Person.new(
:url => url, :profile => Profile.new( :first_name => "Evan", :last_name => "Korth")))
:profile => Profile.new( :first_name => "Evan",
:last_name => "Korth")))
user2.person.save! user2.person.save!

View file

@ -6,17 +6,26 @@
require 'config/environment' require 'config/environment'
remote_url = "http://tom.joindiaspora.com/" def set_app_config username
#remote_url = "http://localhost:3000/" current_config = YAML.load(File.read(Rails.root.join('config', 'app_config.yml.example')))
current_config[Rails.env.to_s] ||= {}
current_config[Rails.env.to_s]['pod_url'] = "#{username}.joindiaspora.com"
current_config['default']['pod_url'] = "#{username}.joindiaspora.com"
file = File.new(Rails.root.join('..','..','shared','app_config.yml'),'w')
file.write(current_config.to_yaml)
file.close
end
set_app_config "tom"
require 'config/initializers/_load_app_config.rb'
# Create seed user # Create seed user
user = User.instantiate!( :email => "tom@tom.joindiaspora.com", user = User.instantiate!( :email => "tom@tom.joindiaspora.com",
:username => "tom", :username => "tom",
:password => "evankorth", :password => "evankorth",
:password_confirmation => "evankorth", :password_confirmation => "evankorth",
:url => remote_url,
:person => { :person => {
:diaspora_handle => "tom@tom.joindiaspora.com",
:url => remote_url,
:profile => { :first_name => "Alexander", :last_name => "Hamiltom", :profile => { :first_name => "Alexander", :last_name => "Hamiltom",
:image_url => "http://tom.joindiaspora.com/images/user/tom.jpg"}} :image_url => "http://tom.joindiaspora.com/images/user/tom.jpg"}}
) )
@ -26,11 +35,7 @@ user2 = User.instantiate!( :email => "korth@tom.joindiaspora.com",
:password => "evankorth", :password => "evankorth",
:password_confirmation => "evankorth", :password_confirmation => "evankorth",
:username => "korth", :username => "korth",
:url => remote_url, :person => {:profile => { :first_name => "Evan", :last_name => "Korth",
:person => { :diaspora_handle => "korth@tom.joindiaspora.com",
:url => remote_url,
:profile => { :first_name => "Evan",
:last_name => "Korth",
:image_url => "http://tom.joindiaspora.com/images/user/korth.jpg"}}) :image_url => "http://tom.joindiaspora.com/images/user/korth.jpg"}})
user2.person.save! user2.person.save!
@ -41,3 +46,5 @@ request = user.send_friend_request_to(user2, aspect)
reversed_request = user2.accept_friend_request( request.id, user2.aspect(:name => "presidents").id ) reversed_request = user2.accept_friend_request( request.id, user2.aspect(:name => "presidents").id )
user.receive reversed_request.to_diaspora_xml user.receive reversed_request.to_diaspora_xml
user.aspect(:name => "Presidents") user.aspect(:name => "Presidents")

View file

@ -8,6 +8,9 @@ module Diaspora
module UserModules module UserModules
module Friending module Friending
def send_friend_request_to(desired_friend, aspect) def send_friend_request_to(desired_friend, aspect)
# should have different exception types for these?
raise "You have already sent a friend request to that person!" if self.pending_requests.detect{
|x| x.destination_url == desired_friend.receive_url }
raise "You are already friends with that person!" if self.friends.detect{ raise "You are already friends with that person!" if self.friends.detect{
|x| x.receive_url == desired_friend.receive_url} |x| x.receive_url == desired_friend.receive_url}
request = Request.instantiate( request = Request.instantiate(

View file

@ -35,11 +35,6 @@ module Diaspora
aspects.detect{|x| x.id == id } aspects.detect{|x| x.id == id }
end end
def album_by_id( id )
id = id.to_id
albums.detect{|x| x.id == id }
end
def aspects_with_post( id ) def aspects_with_post( id )
self.aspects.find_all_by_post_ids( id.to_id ) self.aspects.find_all_by_post_ids( id.to_id )
end end

View file

@ -0,0 +1,93 @@
module Diaspora
module UserModules
module Receiving
def receive_salmon ciphertext
cleartext = decrypt( ciphertext)
salmon = Salmon::SalmonSlap.parse cleartext
if salmon.verified_for_key?(salmon.author.public_key)
Rails.logger.info("data in salmon: #{salmon.data}")
self.receive(salmon.data)
end
end
def receive xml
object = Diaspora::Parser.from_xml(xml)
Rails.logger.debug("Receiving object for #{self.real_name}:\n#{object.inspect}")
Rails.logger.debug("From: #{object.person.inspect}") if object.person
if object.is_a? Retraction
receive_retraction object, xml
elsif object.is_a? Request
receive_request object, xml
elsif object.is_a? Profile
receive_profile object, xml
elsif object.is_a?(Comment)
receive_comment object, xml
else
receive_post object, xml
end
end
def receive_retraction retraction, xml
if retraction.type == 'Person'
Rails.logger.info( "the person id is #{retraction.post_id} the friend found is #{visible_person_by_id(retraction.post_id).inspect}")
unfriended_by visible_person_by_id(retraction.post_id)
else
retraction.perform self.id
aspects = self.aspects_with_person(retraction.person)
aspects.each{ |aspect| aspect.post_ids.delete(retraction.post_id.to_id)
aspect.save
}
end
end
def receive_request request, xml
person = Diaspora::Parser.parse_or_find_person_from_xml( xml )
person.serialized_key ||= request.exported_key
request.person = person
request.person.save
old_request = Request.first(:id => request.id)
request.aspect_id = old_request.aspect_id if old_request
request.save
receive_friend_request(request)
end
def receive_profile profile, xml
person = Diaspora::Parser.owner_id_from_xml xml
person.profile = profile
person.save
end
def receive_comment comment, xml
comment.person = Diaspora::Parser.parse_or_find_person_from_xml( xml ).save if comment.person.nil?
self.visible_people = self.visible_people | [comment.person]
self.save
Rails.logger.debug("The person parsed from comment xml is #{comment.person.inspect}") unless comment.person.nil?
comment.person.save
Rails.logger.debug("From: #{comment.person.inspect}") if comment.person
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
comment.save
unless owns?(comment)
dispatch_comment comment
end
comment.socket_to_uid(id) if (comment.respond_to?(:socket_to_uid) && !self.owns?(comment))
end
def receive_post post, xml
Rails.logger.debug("Saving post: #{post}")
post.user_refs += 1
post.save
self.raw_visible_posts << post
self.save
aspects = self.aspects_with_person(post.person)
aspects.each{ |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
end
end
end

View file

@ -41,6 +41,12 @@ $(document).ready(function(){
} }
); );
$("#publisher textarea").keydown( function(e) {
if (e.shiftKey && e.keyCode == 13) {
$("#publisher form").submit();
}
});
});//end document ready });//end document ready

View file

@ -171,6 +171,41 @@ li.message {
li.message .content div.info .time a { li.message .content div.info .time a {
color: #666666; } color: #666666; }
.reshare_pane {
margin-left: 5px;
margin-right: 5px;
display: inline;
position: relative; }
.reshare_pane ul.reshare_box {
width: 150px;
display: none;
z-index: 10;
position: absolute;
margin-top: 5px;
padding: 0;
background-color: #fafafa;
list-style: none;
border: 5px solid #666666;
-webkit-box-shadow: 0 0 5px #666666;
-moz-box-shadow: 0 0 5px #666666;
text-shadow: 0 2px white;
color: black; }
.reshare_pane ul.reshare_box > li {
font-weight: bold;
padding: 8px;
padding-right: 15px;
border-top: 1px solid white;
border-bottom: 1px solid #cccccc; }
.reshare_pane ul.reshare_box > li:first-child {
border-top: none; }
.reshare_pane ul.reshare_box > li:last-child {
border-bottom: none; }
.reshare_pane ul.reshare_box > li a {
display: block;
height: 100%; }
.reshare_pane ul.reshare_box > li a:hover {
background-color: #eeeeee; }
form { form {
position: relative; position: relative;
font-size: 120%; font-size: 120%;
@ -270,6 +305,9 @@ ul.comment_set {
.destroy_link a, .request_button a { .destroy_link a, .request_button a {
color: #999999; color: #999999;
font-weight: normal; } font-weight: normal; }
.destroy_link a:hover, .request_button a:hover {
text-decoration: underline;
background: none; }
.destroy_link { .destroy_link {
display: none; display: none;

View file

@ -225,6 +225,59 @@ li.message
a a
:color #666 :color #666
.reshare_pane
:margin
:left 5px
:right 5px
:display inline
:position relative
ul.reshare_box
:width 150px
:display none
:z-index 10
:position absolute
:margin
:top 5px
:padding 0
:background
:color #fafafa
:list
:style none
:border 5px solid #666
:-webkit-box-shadow 0 0 5px #666
:-moz-box-shadow 0 0 5px #666
:text-shadow 0 2px #fff
:color #000
> li
:font
:weight bold
:padding 8px
:right 15px
:border
:top 1px solid #fff
:bottom 1px solid #ccc
&:first-child
:border
:top none
&:last-child
:border
:bottom none
a
:display block
:height 100%
&:hover
:background
:color #eee
form form
:position relative :position relative
@ -360,6 +413,10 @@ ul.comment_set
:color #999 :color #999
:font :font
:weight normal :weight normal
&:hover
:text
:decoration underline
:background none
.destroy_link .destroy_link
:display none :display none

View file

@ -39,7 +39,10 @@ Factory.define :user do |u|
u.sequence(:email) {|n| "bob#{n}@pivotallabs.com"} u.sequence(:email) {|n| "bob#{n}@pivotallabs.com"}
u.password "bluepin7" u.password "bluepin7"
u.password_confirmation "bluepin7" u.password_confirmation "bluepin7"
u.person { |a| Factory.create(:person_with_user, :owner_id => a._id)} u.person { |a| Factory.create(:person_with_user,
:owner_id => a._id,
:diaspora_handle => "#{a.username}@#{APP_CONFIG[:pod_url].gsub(/(https?:|www\.)\/\//, '').chop!}")
}
end end
Factory.define :status_message do |m| Factory.define :status_message do |m|

View file

@ -15,6 +15,20 @@ describe Person do
@aspect2 = @user2.aspect(:name => "Abscence of Babes") @aspect2 = @user2.aspect(:name => "Abscence of Babes")
end end
describe '#diaspora_handle' do
context 'local people' do
it 'uses the pod config url to set the diaspora_handle' do
@user.person.diaspora_handle.should == @user.username + "@example.org"
end
end
context 'remote people' do
it 'stores the diaspora_handle in the database' do
@person.diaspora_handle.include?(@user.terse_url).should be false
end
end
end
it 'should not allow two people with the same diaspora_handle' do it 'should not allow two people with the same diaspora_handle' do
person_two = Factory.build(:person, :url => @person.diaspora_handle) person_two = Factory.build(:person, :url => @person.diaspora_handle)
person_two.valid?.should == false person_two.valid?.should == false
@ -148,13 +162,11 @@ describe Person do
end end
it 'should search by diaspora_handle exactly' do it 'should search by diaspora_handle exactly' do
stub_success("tom@tom.joindiaspora.com") stub_success("tom@tom.joindiaspora.com")
Person.by_webfinger(@friend_one.diaspora_handle).should == @friend_one Person.by_webfinger(@friend_one.diaspora_handle).should == @friend_one
end end
it 'should create a stub for a remote user' do it 'should create a stub for a remote user' do
stub_success("tom@tom.joindiaspora.com") stub_success("tom@tom.joindiaspora.com")
tom = Person.by_webfinger('tom@tom.joindiaspora.com') tom = Person.by_webfinger('tom@tom.joindiaspora.com')
tom.real_name.include?("Hamiltom").should be true tom.real_name.include?("Hamiltom").should be true

View file

@ -7,65 +7,95 @@
require File.dirname(__FILE__) + '/../../spec_helper' require File.dirname(__FILE__) + '/../../spec_helper'
describe User do describe User do
let(:user) { Factory(:user) }
let(:user2) { Factory(:user) }
let(:user3) { Factory(:user) }
let(:user4) { Factory(:user) }
let(:aspect) {user.aspect(:name => 'heroes')}
let!(:aspect1) {user.aspect(:name => 'heroes')}
let!(:aspect2) {user2.aspect(:name => 'losers')}
let!(:aspect3) {user3.aspect(:name => 'heroes')}
let!(:aspect4) {user4.aspect(:name => 'heroes')}
before do before do
@user = Factory.create :user friend_users(user, aspect, user2, aspect2)
@aspect = @user.aspect(:name => 'heroes') friend_users(user, aspect, user3, aspect3)
@aspect1 = @user.aspect(:name => 'heroes') friend_users(user, aspect1, user4, aspect4)
@user2 = Factory.create(:user)
@aspect2 = @user2.aspect(:name => 'losers')
@user3 = Factory.create(:user)
@aspect3 = @user3.aspect(:name => 'heroes')
@user4 = Factory.create(:user)
@aspect4 = @user4.aspect(:name => 'heroes')
friend_users(@user, @aspect, @user2, @aspect2)
friend_users(@user, @aspect, @user3, @aspect3)
friend_users(@user, @aspect1, @user4, @aspect4)
end end
context 'posting' do
describe '#validate_aspect_permissions' do
it 'should not be able to post without a aspect' do it 'should not be able to post without a aspect' do
proc {@user.post(:status_message, :message => "heyheyhey")}.should raise_error /You must post to someone/ proc {
user.validate_aspect_permissions([])
}.should raise_error /You must post to someone/
end end
it 'should not be able to post to someone elses aspect' do it 'should not be able to post to someone elses aspect' do
proc {@user.post(:status_message, :message => "heyheyhey", :to => @aspect2.id)}.should raise_error /Cannot post to an aspect you do not own./ proc {
user.validate_aspect_permissions(aspect2.id)
}.should raise_error /Cannot post to an aspect you do not own./
end
end end
describe '#post' do
it 'should put the post in the aspect post array' do it 'should put the post in the aspect post array' do
post = @user.post(:status_message, :message => "hey", :to => @aspect.id) post = user.post(:status_message, :message => "hey", :to => aspect.id)
@aspect.reload aspect.reload
@aspect.post_ids.include?(post.id).should be true aspect.posts.should include post
end end
it 'should put an album in the aspect post array' do it 'should put an album in the aspect post array' do
album = @user.post :album, :name => "Georges", :to => @aspect.id album = user.post :album, :name => "Georges", :to => aspect.id
@aspect.reload aspect.reload
@aspect.post_ids.include?(album.id).should be true aspect.posts.should include album
@aspect.posts.include?(album).should be true end
end end
describe 'dispatching' do describe '#repost' do
before do let!(:status_message) { user.post(:status_message, :message => "hello", :to => aspect.id) }
@post = @user.build_post :status_message, :message => "hey"
it 'should make the post visible in another aspect' do
user.repost( status_message, :to => aspect1.id )
aspect1.reload
aspect1.posts.count.should be 1
end end
end
describe '#update_post' do
let!(:album) { user.post(:album, :name => "Profile Photos", :to => aspect.id) }
it 'should update fields' do
update_hash = { :name => "Other Photos" }
user.update_post( album, update_hash )
album.name.should == "Other Photos"
end
end
end
context 'dispatching' do
let!(:post) { user.build_post :status_message, :message => "hey" }
describe '#push_to_aspects' do
it 'should push a post to a aspect' do it 'should push a post to a aspect' do
@user.should_receive(:salmon).twice user.should_receive(:salmon).twice
@user.push_to_aspects(@post, @aspect.id) user.push_to_aspects(post, aspect.id)
end end
it 'should push a post to all aspects' do it 'should push a post to all aspects' do
@user.should_receive(:salmon).exactly(3).times user.should_receive(:salmon).exactly(3).times
@user.push_to_aspects(@post, :all) user.push_to_aspects(post, :all)
end
end end
describe '#push_to_people' do
it 'should push to people' do it 'should push to people' do
@user.should_receive(:salmon).twice user.should_receive(:salmon).twice
@user.push_to_people(@post, [@user2.person, @user3.person]) user.push_to_people(post, [user2.person, user3.person])
end end
end
end end
end end

View file

@ -7,82 +7,79 @@
require File.dirname(__FILE__) + '/../../spec_helper' require File.dirname(__FILE__) + '/../../spec_helper'
describe User do describe User do
let(:user) { Factory(:user) }
let(:user2) { Factory(:user) }
let(:user3) { Factory(:user) }
let(:user4) { Factory(:user) }
let!(:aspect) { user.aspect(:name => 'heroes') }
let!(:aspect2) { user.aspect(:name => 'losers') }
let!(:user2_aspect) { user2.aspect(:name => 'dudes') }
let!(:user3_aspect) { user3.aspect(:name => 'dudes') }
let!(:user4_aspect) { user4.aspect(:name => 'dudes') }
let(:status_message1) { user2.post :status_message, :message => "hi", :to => user2_aspect.id }
let(:status_message2) { user3.post :status_message, :message => "heyyyy", :to => user3_aspect.id }
let(:status_message3) { user4.post :status_message, :message => "yooo", :to => user4_aspect.id }
before do before do
@user = Factory.create(:user) friend_users(user, aspect, user2, user2_aspect)
@aspect = @user.aspect(:name => 'heroes') friend_users(user, aspect2, user3, user3_aspect)
@aspect2 = @user.aspect(:name => 'losers') friend_users(user, aspect2, user4, user4_aspect)
@user2 = Factory.create :user
@user2_aspect = @user2.aspect(:name => 'dudes')
friend_users(@user, @aspect, @user2, @user2_aspect)
@user3 = Factory.create :user
@user3_aspect = @user3.aspect(:name => 'dudes')
friend_users(@user, @aspect2, @user3, @user3_aspect)
@user4 = Factory.create :user
@user4_aspect = @user4.aspect(:name => 'dudes')
friend_users(@user, @aspect2, @user4, @user4_aspect)
end end
it 'should generate a valid stream for a aspect of people' do it 'should generate a valid stream for a aspect of people' do
status_message1 = @user2.post :status_message, :message => "hi", :to => @user2_aspect.id (1..3).each{ |n|
status_message2 = @user3.post :status_message, :message => "heyyyy", :to => @user3_aspect.id eval("user.receive status_message#{n}.to_diaspora_xml")
status_message3 = @user4.post :status_message, :message => "yooo", :to => @user4_aspect.id }
@user.receive status_message1.to_diaspora_xml user.visible_posts(:by_members_of => aspect).should include status_message1
@user.receive status_message2.to_diaspora_xml user.visible_posts(:by_members_of => aspect).should_not include status_message2
@user.receive status_message3.to_diaspora_xml user.visible_posts(:by_members_of => aspect).should_not include status_message3
@user.reload
@user.visible_posts(:by_members_of => @aspect).include?(status_message1).should be true user.visible_posts(:by_members_of => aspect2).should_not include status_message1
@user.visible_posts(:by_members_of => @aspect).include?(status_message2).should be false user.visible_posts(:by_members_of => aspect2).should include status_message2
@user.visible_posts(:by_members_of => @aspect).include?(status_message3).should be false user.visible_posts(:by_members_of => aspect2).should include status_message3
@user.visible_posts(:by_members_of => @aspect2).include?(status_message1).should be false
@user.visible_posts(:by_members_of => @aspect2).include?(status_message2).should be true
@user.visible_posts(:by_members_of => @aspect2).include?(status_message3).should be true
end end
describe 'querying' do context 'querying' do
describe '#find_visible_post_by_id' do
it 'should find a visible post by id' do it 'should query' do
status_message1 = @user.post :status_message, :message => "hi", :to => @aspect.id user2.find_visible_post_by_id(status_message1.id).should == status_message1
status_message2 = @user2.post :status_message, :message => "heyyyy", :to => @user2_aspect.id user.find_visible_post_by_id(status_message1.id).should == nil
status_message3 = @user3.post :status_message, :message => "yooo", :to => @user3_aspect.id end
end
@user.find_visible_post_by_id(status_message1.id).should == status_message1
@user2.find_visible_post_by_id(status_message1.id).should == nil
end end
end context 'albums' do
describe 'albums' do
before do before do
@album = @user.post :album, :name => "Georges", :to => @aspect.id @album = user.post :album, :name => "Georges", :to => aspect.id
@aspect.reload aspect.reload
@aspect2.reload aspect2.reload
@user.reload user.reload
@album2 = @user.post :album, :name => "Borges", :to => @aspect.id @album2 = user.post :album, :name => "Borges", :to => aspect.id
@aspect.reload aspect.reload
@aspect2.reload aspect2.reload
@user.reload user.reload
@user.post :album, :name => "Luises", :to => @aspect2.id user.post :album, :name => "Luises", :to => aspect2.id
@aspect.reload aspect.reload
@aspect2.reload aspect2.reload
@user.reload user.reload
end end
it 'should find all albums if passed :all' do it 'should find all albums if passed :all' do
@user.albums_by_aspect(:all).size.should == 3 user.albums_by_aspect(:all).should have(3).albums
end end
it 'should return the right number of albums' do it 'should return the right number of albums' do
@user.albums_by_aspect(@aspect).size.should == 2 user.albums_by_aspect(aspect).should have(2).albums
@user.albums_by_aspect(@aspect2).size.should == 1 user.albums_by_aspect(aspect2).should have(1).album
end end
end end
end end

View file

@ -7,55 +7,42 @@
require File.dirname(__FILE__) + '/../spec_helper' require File.dirname(__FILE__) + '/../spec_helper'
describe User do describe User do
before do let(:user) { Factory(:user) }
@user = Factory.create(:user) let(:aspect) { user.aspect(:name => 'heroes') }
@aspect = @user.aspect(:name => 'heroes')
describe '#diaspora_handle' do
it 'uses the pod config url to set the diaspora_handle' do
user.diaspora_handle.should == user.username + "@example.org"
end
end end
it 'should create with pivotal or allowed emails' do context 'profiles' do
user1 = Factory.create(:user, :email => "kimfuh@yahoo.com")
user2 = Factory.create(:user, :email => "awesome@sofaer.net")
user3 = Factory.create(:user, :email => "steveellis@pivotallabs.com")
user1.created_at.nil?.should be false
user2.created_at.nil?.should be false
user3.created_at.nil?.should be false
end
describe 'profiles' do
it 'should be able to update their profile and send it to their friends' do it 'should be able to update their profile and send it to their friends' do
Factory.create(:person) updated_profile = { :profile => {
:first_name => 'bob',
:last_name => 'billytown',
:image_url => "http://clown.com"} }
updated_profile = {:profile => {:first_name => 'bob', :last_name => 'billytown', :image_url => "http://clown.com"}} user.update_profile(updated_profile).should be true
user.profile.image_url.should == "http://clown.com"
@user.update_profile(updated_profile).should == true
@user.profile.image_url.should == "http://clown.com"
end end
end end
describe 'aspects' do context 'aspects' do
let(:user2) { Factory(:user) }
let(:aspect2) { user2.aspect(:name => 'stuff') }
it 'should delete an empty aspect' do it 'should delete an empty aspect' do
@user.aspects.include?(@aspect).should == true user.drop_aspect(aspect)
@user.drop_aspect(@aspect) user.aspects.include?(aspect).should == false
@user.reload
@user.aspects.include?(@aspect).should == false
end end
it 'should not delete an aspect with friends' do it 'should not delete an aspect with friends' do
user2 = Factory.create(:user) friend_users(user, Aspect.find_by_id(aspect.id), user2, Aspect.find_by_id(aspect2.id))
aspect2 = user2.aspect(:name => 'stuff') aspect.reload
user2.reload proc{user.drop_aspect(aspect)}.should raise_error /Aspect not empty/
aspect2.reload user.aspects.include?(aspect).should == true
friend_users(@user, Aspect.find_by_id(@aspect.id), user2, Aspect.find_by_id(aspect2.id))
@aspect.reload
@user.aspects.include?(@aspect).should == true
proc{@user.drop_aspect(@aspect)}.should raise_error /Aspect not empty/
@user.reload
@user.aspects.include?(@aspect).should == true
end end
end end
end end