Merging master into production
2
Gemfile
|
|
@ -26,7 +26,7 @@ gem 'json'
|
||||||
|
|
||||||
#Standards
|
#Standards
|
||||||
gem 'pubsubhubbub'
|
gem 'pubsubhubbub'
|
||||||
gem 'redfinger'
|
gem 'redfinger', :git => 'git://github.com/rsofaer/redfinger.git'
|
||||||
|
|
||||||
#EventMachine
|
#EventMachine
|
||||||
gem 'em-http-request',:git => 'git://github.com/igrigorik/em-http-request.git', :require => 'em-http'
|
gem 'em-http-request',:git => 'git://github.com/igrigorik/em-http-request.git', :require => 'em-http'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
protect_from_forgery :except => :receive
|
protect_from_forgery :except => :receive
|
||||||
|
|
||||||
before_filter :set_friends_and_status, :count_requests
|
before_filter :set_friends_and_status
|
||||||
|
before_filter :count_requests
|
||||||
|
|
||||||
layout :layout_by_resource
|
layout :layout_by_resource
|
||||||
|
|
||||||
|
|
@ -17,8 +18,6 @@ class ApplicationController < ActionController::Base
|
||||||
def set_friends_and_status
|
def set_friends_and_status
|
||||||
if current_user
|
if current_user
|
||||||
@groups = current_user.groups
|
@groups = current_user.groups
|
||||||
@friends = current_user.friends
|
|
||||||
@group = params[:group] ? current_user.group_by_id(params[:group]) : current_user.groups.first
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
class GridfsController < ActionController::Metal
|
|
||||||
def serve
|
|
||||||
gridfs_path = env["PATH_INFO"].gsub("/images/", "")
|
|
||||||
begin
|
|
||||||
gridfs_file = Mongo::GridFileSystem.new(MongoMapper.database).open(gridfs_path, 'r')
|
|
||||||
self.response_body = gridfs_file.read
|
|
||||||
self.content_type = gridfs_file.content_type
|
|
||||||
rescue
|
|
||||||
self.status = :file_not_found
|
|
||||||
self.content_type = 'text/plain'
|
|
||||||
self.response_body = "File totally imaginary #{gridfs_path}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
@ -2,7 +2,9 @@ class GroupsController < ApplicationController
|
||||||
before_filter :authenticate_user!
|
before_filter :authenticate_user!
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@posts = current_user.raw_visible_posts.paginate :page => params[:page], :order => 'created_at DESC'
|
@posts = current_user.visible_posts(:by_members_of => :all).paginate :page => params[:page], :order => 'created_at DESC'
|
||||||
|
@group = :all
|
||||||
|
@friends = current_user.friends
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
|
@ -28,12 +30,9 @@ class GroupsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@people_ids = @group.person_ids
|
|
||||||
|
|
||||||
@group = Group.first(:id => params[:id])
|
@group = Group.first(:id => params[:id])
|
||||||
|
@friends = @group.people
|
||||||
@posts = current_user.visible_posts( :by_members_of => @group ).paginate :order => 'created_at DESC'
|
@posts = current_user.visible_posts( :by_members_of => @group ).paginate :order => 'created_at DESC'
|
||||||
#@posts = Post.paginate :person_id => @people_ids, :order => 'created_at DESC'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ class PhotosController < ApplicationController
|
||||||
before_filter :authenticate_user!
|
before_filter :authenticate_user!
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
render :nothing => true
|
||||||
begin
|
begin
|
||||||
@photo = current_user.post(:photo, params)
|
@photo = current_user.post(:photo, params)
|
||||||
|
|
||||||
|
|
@ -21,6 +22,8 @@ class PhotosController < ApplicationController
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@photo = Photo.new
|
@photo = Photo.new
|
||||||
|
@album = current_user.album_by_id(params[:album_id])
|
||||||
|
render :partial => "new_photo"
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
|
||||||
|
|
@ -31,22 +31,31 @@ class RequestsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
puts params.inspect
|
begin
|
||||||
rel_hash = relationship_flow(params[:request][:destination_url])
|
rel_hash = relationship_flow(params[:request][:destination_url])
|
||||||
|
rescue Exception => e
|
||||||
|
flash[:error] = "no diaspora seed found with this email!"
|
||||||
|
redirect_to current_user.group_by_id(params[:request][:group_id])
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
Rails.logger.debug("Sending request: #{rel_hash}")
|
Rails.logger.debug("Sending request: #{rel_hash}")
|
||||||
@request = current_user.send_request(rel_hash, params[:request][:group_id])
|
|
||||||
|
begin
|
||||||
|
@request = current_user.send_request(rel_hash, params[:request][:group_id])
|
||||||
|
rescue Exception => e
|
||||||
|
raise e unless e.message.include? "already friends"
|
||||||
|
flash[:notice] = "You are already friends with #{params[:request][:destination_url]}!"
|
||||||
|
redirect_to current_user.group_by_id(params[:request][:group_id])
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if @request
|
if @request
|
||||||
flash[:notice] = "a friend request was sent to #{@request.destination_url}"
|
flash[:notice] = "a friend request was sent to #{@request.destination_url}"
|
||||||
redirect_to requests_url
|
redirect_to current_user.group_by_id(params[:request][:group_id])
|
||||||
else
|
else
|
||||||
if url.include? '@'
|
flash[:error] = "Something went horribly wrong..."
|
||||||
flash[:error] = "no diaspora seed found with this email!"
|
redirect_to current_user.group_by_id(params[:request][:group_id])
|
||||||
else
|
|
||||||
flash[:error] = "you have already friended this person"
|
|
||||||
end
|
|
||||||
@request = Request.new
|
|
||||||
render :action => 'new'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,8 @@
|
||||||
class StatusMessagesController < ApplicationController
|
class StatusMessagesController < ApplicationController
|
||||||
before_filter :authenticate_user!
|
before_filter :authenticate_user!
|
||||||
|
|
||||||
def index
|
|
||||||
@status_messages = StatusMessage.paginate :page => params[:page], :order => 'created_at DESC'
|
|
||||||
respond_to do |format|
|
|
||||||
format.html
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
def create
|
||||||
puts params.inspect
|
params[:status_message][:group_ids] = params[:group_ids]
|
||||||
@status_message = current_user.post(:status_message, params[:status_message])
|
@status_message = current_user.post(:status_message, params[:status_message])
|
||||||
|
|
||||||
if @status_message.created_at
|
if @status_message.created_at
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
module ApplicationHelper
|
module ApplicationHelper
|
||||||
|
|
||||||
def current_group?(group)
|
def current_group?(group)
|
||||||
@group.id == group.id
|
@group == :all || @group.id == group.id
|
||||||
end
|
end
|
||||||
|
|
||||||
def object_path(object)
|
def object_path(object)
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ module PhotosHelper
|
||||||
link_to (image_tag photo.url(:scaled_full)), photo_path(album.next_photo(photo)), :rel => "prefetch"
|
link_to (image_tag photo.url(:scaled_full)), photo_path(album.next_photo(photo)), :rel => "prefetch"
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_prev(photo, album)
|
def url_to_prev(photo, album)
|
||||||
link_to "<< prev", photo_path(album.prev_photo(photo)), :rel => "prefetch"
|
photo_path(album.prev_photo(photo))
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_next(photo, album)
|
def url_to_next(photo, album)
|
||||||
link_to "next >>", photo_path(album.next_photo(photo)), :rel => "prefetch"
|
photo_path(album.next_photo(photo))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ module RequestsHelper
|
||||||
action = :none
|
action = :none
|
||||||
url = nil
|
url = nil
|
||||||
local_person = Person.by_webfinger identifier
|
local_person = Person.by_webfinger identifier
|
||||||
puts local_person.inspect
|
|
||||||
if local_person
|
if local_person
|
||||||
action = (local_person == current_user.person ? :none : :friend)
|
action = (local_person == current_user.person ? :none : :friend)
|
||||||
url = local_person.receive_url
|
url = local_person.receive_url
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ class Person
|
||||||
serialized_key = new_key.export
|
serialized_key = new_key.export
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def public_key_hash
|
||||||
|
Base64.encode64 OpenSSL::Digest::SHA256.new(self.export_key).to_s
|
||||||
|
end
|
||||||
|
|
||||||
def export_key
|
def export_key
|
||||||
encryption_key.public_key.export
|
encryption_key.public_key.export
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,6 @@ class Post
|
||||||
self.create params
|
self.create params
|
||||||
end
|
end
|
||||||
|
|
||||||
#Querying
|
|
||||||
def self.newest_for(person)
|
|
||||||
self.where(:person_id => person.id, :order => '_id desc')
|
|
||||||
end
|
|
||||||
|
|
||||||
#ENCRYPTION
|
#ENCRYPTION
|
||||||
xml_accessor :creator_signature
|
xml_accessor :creator_signature
|
||||||
key :creator_signature, String
|
key :creator_signature, String
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,7 @@ class User
|
||||||
|
|
||||||
|
|
||||||
def allowed_email?
|
def allowed_email?
|
||||||
allowed_emails = ["@pivotallabs.com", "@joindiaspora.com", "@sofaer.net",
|
allowed_emails = ["@pivotallabs.com", "@joindiaspora.com", "@sofaer.net"]
|
||||||
"wchulley@gmail.com", "kimfuh@yahoo.com", "CJichi@yahoo.com",
|
|
||||||
"madkisso@mit.edu", "bribak@msn.com", "asykley@verizon.net",
|
|
||||||
"paulhaeberli@gmail.com","bondovatic@gmail.com", "dixon1e@yahoo.com"]
|
|
||||||
allowed_emails.each{|allowed|
|
allowed_emails.each{|allowed|
|
||||||
if email.include?(allowed)
|
if email.include?(allowed)
|
||||||
return true
|
return true
|
||||||
|
|
@ -59,23 +56,25 @@ class User
|
||||||
def post(class_name, options = {})
|
def post(class_name, options = {})
|
||||||
options[:person] = self.person
|
options[:person] = self.person
|
||||||
|
|
||||||
group_id = options[:group_id]
|
group_ids = options[:group_ids]
|
||||||
options.delete(:group_id)
|
options.delete(:group_ids)
|
||||||
|
|
||||||
model_class = class_name.to_s.camelize.constantize
|
model_class = class_name.to_s.camelize.constantize
|
||||||
|
|
||||||
post = model_class.instantiate(options)
|
post = model_class.instantiate(options)
|
||||||
post.creator_signature = post.sign_with_key(encryption_key)
|
post.creator_signature = post.sign_with_key(encryption_key)
|
||||||
post.save
|
post.save
|
||||||
|
|
||||||
|
|
||||||
if group_id
|
groups = self.groups.find_all_by_id(group_ids)
|
||||||
group = self.groups.find_by_id(group_id)
|
target_people = []
|
||||||
|
|
||||||
|
groups.each{ |group|
|
||||||
group.posts << post
|
group.posts << post
|
||||||
group.save
|
group.save
|
||||||
post.push_to( group.people.all )
|
target_people = target_people | group.people
|
||||||
else
|
}
|
||||||
post.push_to( self.friends.all )
|
post.push_to( target_people )
|
||||||
end
|
|
||||||
|
|
||||||
post.socket_to_uid(id) if post.respond_to?(:socket_to_uid)
|
post.socket_to_uid(id) if post.respond_to?(:socket_to_uid)
|
||||||
|
|
||||||
|
|
@ -86,6 +85,7 @@ class User
|
||||||
|
|
||||||
def visible_posts( opts = {} )
|
def visible_posts( opts = {} )
|
||||||
if opts[:by_members_of]
|
if opts[:by_members_of]
|
||||||
|
return raw_visible_posts if opts[:by_members_of] == :all
|
||||||
group = self.groups.find_by_id( opts[:by_members_of].id )
|
group = self.groups.find_by_id( opts[:by_members_of].id )
|
||||||
group.posts
|
group.posts
|
||||||
end
|
end
|
||||||
|
|
@ -139,22 +139,22 @@ class User
|
||||||
|
|
||||||
######### Friend Requesting ###########
|
######### Friend Requesting ###########
|
||||||
def send_friend_request_to(friend_url, group_id)
|
def send_friend_request_to(friend_url, group_id)
|
||||||
unless self.friends.detect{ |x| x.receive_url == friend_url}
|
raise "You are already friends with that person!" if self.friends.detect{ |x| x.receive_url == friend_url}
|
||||||
request = Request.instantiate(:to => friend_url, :from => self.person, :into => group_id)
|
request = Request.instantiate(:to => friend_url, :from => self.person, :into => group_id)
|
||||||
if request.save
|
if request.save
|
||||||
self.pending_requests << request
|
self.pending_requests << request
|
||||||
self.save
|
self.save
|
||||||
|
|
||||||
group = self.group_by_id(group_id)
|
group = self.group_by_id(group_id)
|
||||||
|
|
||||||
group.requests << request
|
group.requests << request
|
||||||
group.save
|
group.save
|
||||||
|
|
||||||
request.push_to_url friend_url
|
request.push_to_url friend_url
|
||||||
end
|
|
||||||
request
|
|
||||||
end
|
end
|
||||||
end
|
request
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def accept_friend_request(friend_request_id, group_id)
|
def accept_friend_request(friend_request_id, group_id)
|
||||||
request = Request.find_by_id(friend_request_id)
|
request = Request.find_by_id(friend_request_id)
|
||||||
|
|
@ -358,7 +358,12 @@ class User
|
||||||
group(:name => "Acquaintances")
|
group(:name => "Acquaintances")
|
||||||
group(:name => "Family")
|
group(:name => "Family")
|
||||||
group(:name => "Nemeses")
|
group(:name => "Nemeses")
|
||||||
group(:name => "Work")
|
group(:name => "Pivots")
|
||||||
|
end
|
||||||
|
|
||||||
|
def album_by_id( id )
|
||||||
|
id = ensure_bson id
|
||||||
|
albums.detect{|x| x.id == id }
|
||||||
end
|
end
|
||||||
|
|
||||||
def groups_with_person person
|
def groups_with_person person
|
||||||
|
|
@ -369,8 +374,8 @@ class User
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def setup_person
|
def setup_person
|
||||||
self.person.serialized_key = generate_key.export
|
self.person.serialized_key ||= generate_key.export
|
||||||
self.person.email = email
|
self.person.email ||= email
|
||||||
self.person.save!
|
self.person.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ class ImageUploader < CarrierWave::Uploader::Base
|
||||||
%w(jpg jpeg gif png)
|
%w(jpg jpeg gif png)
|
||||||
end
|
end
|
||||||
|
|
||||||
# def filename
|
def filename
|
||||||
# model.id.to_s + File.extname(@filename)
|
model.id.to_s + File.extname(@filename) if @filename
|
||||||
# end
|
end
|
||||||
|
|
||||||
version :thumb_small do
|
version :thumb_small do
|
||||||
process :resize_to_fill => [30,30]
|
process :resize_to_fill => [30,30]
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
:javascript
|
||||||
|
$(document).ready(function(){
|
||||||
|
reset_photo_fancybox();
|
||||||
|
});
|
||||||
|
|
||||||
|
.album_id{:id => @album.id, :style => "display:hidden;"}
|
||||||
.back= link_to '⇧ albums', albums_path
|
.back= link_to '⇧ albums', albums_path
|
||||||
%h1.big_text
|
%h1.big_text
|
||||||
|
|
||||||
|
|
@ -11,7 +17,6 @@
|
||||||
|
|
||||||
.yo{:style => "display:none;"}
|
.yo{:style => "display:none;"}
|
||||||
#new_photo_pane
|
#new_photo_pane
|
||||||
= render "photos/new_photo", :photo => @photo, :album => @album
|
|
||||||
|
|
||||||
.sub_header
|
.sub_header
|
||||||
="updated #{how_long_ago(@album)}"
|
="updated #{how_long_ago(@album)}"
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@
|
||||||
welcome,
|
welcome,
|
||||||
= current_user.profile.first_name
|
= current_user.profile.first_name
|
||||||
|
|
||||||
- @group.nil? ? group_id = nil : group_id = @group.id
|
= render "shared/publisher", :group_ids => :all
|
||||||
|
|
||||||
= render "shared/publisher", :group_id => group_id
|
|
||||||
|
|
||||||
%ul#stream
|
%ul#stream
|
||||||
- for post in @posts
|
- for post in @posts
|
||||||
|
|
|
||||||
|
|
@ -1,103 +1,101 @@
|
||||||
- if user_signed_in?
|
= javascript_include_tag 'FABridge', 'swfobject', 'web_socket'
|
||||||
= javascript_include_tag 'FABridge', 'swfobject', 'web_socket'
|
:javascript
|
||||||
:javascript
|
WebSocket.__swfLocation = "/javascripts/WebSocketMain.swf";
|
||||||
WebSocket.__swfLocation = "/javascripts/WebSocketMain.swf";
|
$(document).ready(function(){
|
||||||
:javascript
|
function debug(str){ $("#debug").append("<p>" + str); };
|
||||||
$(document).ready(function(){
|
|
||||||
function debug(str){ $("#debug").append("<p>" + str); };
|
|
||||||
|
|
||||||
ws = new WebSocket("ws://#{request.host}:8080/#{CGI::escape(current_user.id.to_s)}");
|
ws = new WebSocket("ws://#{request.host}:8080/#{CGI::escape(current_user.id.to_s)}");
|
||||||
|
|
||||||
//Attach onmessage to websocket
|
//Attach onmessage to websocket
|
||||||
ws.onmessage = function(evt) {
|
ws.onmessage = function(evt) {
|
||||||
var obj = jQuery.parseJSON(evt.data);
|
var obj = jQuery.parseJSON(evt.data);
|
||||||
debug("got a " + obj['class'] + " for group " + obj['group_id']);
|
debug("got a " + obj['class'] + " for group " + obj['group_id']);
|
||||||
|
|
||||||
if (obj['class']=="retractions"){
|
if (obj['class']=="retractions"){
|
||||||
processRetraction(obj['post_id']);
|
processRetraction(obj['post_id']);
|
||||||
|
|
||||||
}else if (obj['class']=="comments"){
|
|
||||||
processComment(obj['post_id'], obj['html'])
|
|
||||||
|
|
||||||
}else if (obj['class']=='photos' && onPageForClass('albums')){
|
|
||||||
processPhotoInAlbum(obj['photo_hash'])
|
|
||||||
}else if (obj['class']=='status_messages'){
|
|
||||||
processStatusMessage(obj['class'], obj['html'], obj['status_message_hash'], obj['group_id'], obj['mine?'])
|
|
||||||
}else{
|
|
||||||
processPost(obj['class'], obj['html'], obj['group_id'], obj['mine?'])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
ws.onclose = function() { debug("socket closed"); };
|
|
||||||
ws.onopen = function() {
|
|
||||||
ws.send(location.pathname);
|
|
||||||
debug("connected...");
|
|
||||||
};
|
|
||||||
|
|
||||||
function processRetraction(post_id){
|
|
||||||
$('#' + post_id ).fadeOut(500, function(){
|
|
||||||
$(this).remove;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function processComment(post_id, html){
|
|
||||||
post = $('#' + post_id)[0]
|
|
||||||
$(' .comment_set li:last', post ).before(
|
|
||||||
$(html).fadeIn("fast", function(){})
|
|
||||||
);
|
|
||||||
toggler = $('.show_post_comments', post)
|
|
||||||
toggler.html(
|
|
||||||
toggler.html().replace(/\d/,$('.comment_set', post)[0].childElementCount -1));
|
|
||||||
}
|
|
||||||
|
|
||||||
function processPost(className, html, groupId, mineBool){
|
|
||||||
if(mineBool || onPageForClass(className) || onPageForGroup(groupId)){
|
|
||||||
$("#stream").prepend(
|
|
||||||
$(html).fadeIn("fast", function(){
|
|
||||||
$("#stream label:first").inFieldLabels();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function processStatusMessage(className, html, messageHash, groupId, mineBool){
|
|
||||||
processPost(className, html, groupId, mineBool);
|
|
||||||
console.log(messageHash)
|
|
||||||
if(messageHash['mine?']){
|
|
||||||
updateMyLatestStatus(messageHash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateMyLatestStatus(messageHash){
|
}else if (obj['class']=="comments"){
|
||||||
$("#latest_message").text(messageHash['text']);
|
processComment(obj['post_id'], obj['html'])
|
||||||
$("#latest_message_time").text(' - just now');
|
|
||||||
|
}else if (obj['class']=='photos' && onPageForClass('albums')){
|
||||||
|
processPhotoInAlbum(obj['photo_hash'])
|
||||||
|
}else if (obj['class']=='status_messages'){
|
||||||
|
processStatusMessage(obj['class'], obj['html'], obj['status_message_hash'], obj['group_id'], obj['mine?'])
|
||||||
|
}else{
|
||||||
|
processPost(obj['class'], obj['html'], obj['group_id'], obj['mine?'])
|
||||||
}
|
}
|
||||||
|
|
||||||
function processPhotoInAlbum(photoHash){
|
|
||||||
if (location.href.indexOf(photoHash['album_id']) == -1){
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
html = "<div class=\'image_thumb\' id=\'"+photoHash['id']+"\' style=\'padding-right:3px;\'> \
|
|
||||||
<a href=\"/photos/"+ photoHash['id'] +"\"> \
|
|
||||||
<img alt=\"New thumbnail\" src=\""+ photoHash['thumb_url'] +"\" /> \
|
|
||||||
</a> </div>"
|
|
||||||
$("#thumbnails").append( $(html) )
|
|
||||||
$("#"+ photoHash['id'] + " img").load( function() {
|
|
||||||
$(this).fadeIn("slow");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onPageForClass(className){
|
};
|
||||||
return ((location.href.indexOf(className) != -1 ) || (location.pathname == '/')) && onPageOne();
|
ws.onclose = function() { debug("socket closed"); };
|
||||||
}
|
ws.onopen = function() {
|
||||||
|
ws.send(location.pathname);
|
||||||
|
debug("connected...");
|
||||||
|
};
|
||||||
|
|
||||||
function onPageForGroup(groupId){
|
function processRetraction(post_id){
|
||||||
return (location.href.indexOf(groupId) != -1 )
|
$('#' + post_id ).fadeOut(500, function(){
|
||||||
|
$(this).remove;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function processComment(post_id, html){
|
||||||
|
post = $('#' + post_id)[0]
|
||||||
|
$(' .comment_set li:last', post ).before(
|
||||||
|
$(html).fadeIn("fast", function(){})
|
||||||
|
);
|
||||||
|
toggler = $('.show_post_comments', post)
|
||||||
|
toggler.html(
|
||||||
|
toggler.html().replace(/\d/,$('.comment_set', post)[0].childElementCount -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function processPost(className, html, groupId, mineBool){
|
||||||
|
if(mineBool || onPageForClass(className) || onPageForGroup(groupId)){
|
||||||
|
$("#stream").prepend(
|
||||||
|
$(html).fadeIn("fast", function(){
|
||||||
|
$("#stream label:first").inFieldLabels();
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
function onPageOne() {
|
|
||||||
var c = document.location.search.charAt(document.location.search.length-1);
|
function processStatusMessage(className, html, messageHash, groupId, mineBool){
|
||||||
return ((c =='') || (c== '1'));
|
processPost(className, html, groupId, mineBool);
|
||||||
|
console.log(messageHash)
|
||||||
|
if(messageHash['mine?']){
|
||||||
|
updateMyLatestStatus(messageHash);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
function updateMyLatestStatus(messageHash){
|
||||||
|
$("#latest_message").text(messageHash['text']);
|
||||||
|
$("#latest_message_time").text(' - just now');
|
||||||
|
}
|
||||||
|
|
||||||
|
function processPhotoInAlbum(photoHash){
|
||||||
|
if (location.href.indexOf(photoHash['album_id']) == -1){
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
html = "<div class=\'image_thumb\' id=\'"+photoHash['id']+"\' style=\'padding-right:3px;\'> \
|
||||||
|
<a href=\"/photos/"+ photoHash['id'] +"\"> \
|
||||||
|
<img alt=\"New thumbnail\" src=\""+ photoHash['thumb_url'] +"\" /> \
|
||||||
|
</a> </div>"
|
||||||
|
$("#thumbnails").append( $(html) )
|
||||||
|
$("#"+ photoHash['id'] + " img").load( function() {
|
||||||
|
$(this).fadeIn("slow");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPageForClass(className){
|
||||||
|
return ((location.href.indexOf(className) != -1 ) || (location.pathname == '/')) && onPageOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPageForGroup(groupId){
|
||||||
|
return (location.href.indexOf(groupId) != -1 )
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPageOne() {
|
||||||
|
var c = document.location.search.charAt(document.location.search.length-1);
|
||||||
|
return ((c =='') || (c== '1'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
|
|
||||||
/= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"
|
/= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"
|
||||||
= javascript_include_tag 'jquery142', 'rails', 'google'
|
= javascript_include_tag 'jquery142', 'rails', 'google'
|
||||||
= javascript_include_tag 'tiny_mce/tiny_mce'
|
|
||||||
= javascript_include_tag 'jquery.infieldlabel', 'jquery.cycle/jquery.cycle.min.js'
|
= javascript_include_tag 'jquery.infieldlabel', 'jquery.cycle/jquery.cycle.min.js'
|
||||||
|
|
||||||
= javascript_include_tag 'fancybox/jquery.fancybox-1.3.1.pack'
|
= javascript_include_tag 'fancybox/jquery.fancybox-1.3.1.pack'
|
||||||
|
|
@ -33,26 +32,35 @@
|
||||||
%header
|
%header
|
||||||
.container
|
.container
|
||||||
#session_action
|
#session_action
|
||||||
- if user_signed_in?
|
%ul#user_menu
|
||||||
%ul#user_menu
|
%li#global_search
|
||||||
%li.name= link_to current_user.real_name, current_user.person
|
= form_tag(users_path, :method => 'get') do
|
||||||
%li= link_to "requests (#{@request_count})", requests_path, :class => new_request(@request_count)
|
%label{:for => 'q'} Search
|
||||||
%li= link_to "settings", edit_user_path(current_user)
|
= text_field_tag 'q'
|
||||||
%li= link_to "search", users_path
|
|
||||||
%li= link_to "logout", destroy_user_session_path
|
%li
|
||||||
- else
|
%ul#other_user_menu
|
||||||
= link_to "login", new_user_session_path
|
%li
|
||||||
|
= owner_image_tag
|
||||||
|
= link_to current_user.real_name, current_user.person
|
||||||
|
%li.requests= link_to "requests (#{@request_count})", requests_path, :class => new_request(@request_count)
|
||||||
|
%li.settings= link_to "settings", edit_user_path(current_user)
|
||||||
|
%li.logout= link_to "logout", destroy_user_session_path
|
||||||
|
|
||||||
|
|
||||||
#diaspora_text{:href => root_path}
|
#diaspora_text{:href => root_path}
|
||||||
= link_to "DIASPORA*", root_path
|
= link_to "DIASPORA*", root_path
|
||||||
%span.sub_text
|
%span.sub_text
|
||||||
PREVIEW
|
PREVIEW
|
||||||
= render "shared/group_nav"
|
|
||||||
|
|
||||||
= link_to "photos", albums_path
|
%span{:style => "padding-left:30px;"}
|
||||||
|
= link_to "photos", albums_path
|
||||||
|
|
||||||
.container
|
.container
|
||||||
.span-24.last
|
.span-4.append-1.last
|
||||||
|
= render "shared/group_nav"
|
||||||
|
|
||||||
|
.span-19.last
|
||||||
= yield
|
= yield
|
||||||
.span-24.last
|
|
||||||
= render "posts/debug"
|
= render "posts/debug"
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
%ul#friend_stream.nav
|
|
||||||
%h3 friends
|
|
||||||
- for friend in @friends
|
|
||||||
= person_image_link(friend)
|
|
||||||
|
|
||||||
%li= link_to "view all", people_path
|
|
||||||
|
|
||||||
%br
|
|
||||||
%br
|
|
||||||
|
|
||||||
= link_to "add a new person", requests_path
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
$(function() {
|
$(function() {
|
||||||
$("#photo_image").html5_upload({
|
$("#photo_image").html5_upload({
|
||||||
// WE INSERT ALBUM_ID PARAM HERE
|
// WE INSERT ALBUM_ID PARAM HERE
|
||||||
url: "/photos?album_id=#{album.id}",
|
url: "/photos?album_id=#{@album.id}",
|
||||||
sendBoundary: window.FormData || $.browser.mozilla,
|
sendBoundary: window.FormData || $.browser.mozilla,
|
||||||
setName: function(text) {
|
setName: function(text) {
|
||||||
$("#progress_report_name").text(text);
|
$("#progress_report_name").text(text);
|
||||||
|
|
@ -12,8 +12,10 @@
|
||||||
$("#add_photo_loader").fadeOut(400);
|
$("#add_photo_loader").fadeOut(400);
|
||||||
|
|
||||||
$("#photo_title_status").text("Done!");
|
$("#photo_title_status").text("Done!");
|
||||||
$("#progress_report").html("Great job!");
|
$("#progress_report").html("Good job me!");
|
||||||
},
|
|
||||||
|
$("#add_photo_button").addClass("uploading_complete");
|
||||||
|
},
|
||||||
onStart: function(event, total){
|
onStart: function(event, total){
|
||||||
$("#add_photo_button").html( "Uploading Photos" );
|
$("#add_photo_button").html( "Uploading Photos" );
|
||||||
$("#add_photo_loader").fadeIn(400);
|
$("#add_photo_loader").fadeIn(400);
|
||||||
|
|
@ -29,10 +31,10 @@
|
||||||
%h1
|
%h1
|
||||||
%span{:id=>"photo_title_status"}
|
%span{:id=>"photo_title_status"}
|
||||||
Add photos to
|
Add photos to
|
||||||
%i= album.name
|
%i= @album.name
|
||||||
= form_for photo, :html => {:multipart => true} do |f|
|
= form_for @photo, :html => {:multipart => true} do |f|
|
||||||
= f.error_messages
|
= f.error_messages
|
||||||
= f.hidden_field :album_id, :value => album.id
|
= f.hidden_field :album_id, :value => @album.id
|
||||||
= f.file_field :image, :multiple => 'multiple'
|
= f.file_field :image, :multiple => 'multiple'
|
||||||
|
|
||||||
#progress_report{ :style => "display:none;text-align:center;" }
|
#progress_report{ :style => "display:none;text-align:center;" }
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,16 @@
|
||||||
|
:javascript
|
||||||
|
$(document).keydown(function(e){
|
||||||
|
switch(e.keyCode) {
|
||||||
|
case 37:
|
||||||
|
window.location.replace( "#{url_to_prev(@photo,@album)}" );
|
||||||
|
break;
|
||||||
|
case 39:
|
||||||
|
window.location.replace( "#{url_to_next(@photo,@album)}" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
.back= link_to "⇧ #{@album.name}", album_path(@album)
|
.back= link_to "⇧ #{@album.name}", album_path(@album)
|
||||||
%h1.big_text
|
%h1.big_text
|
||||||
= @photo.image
|
= @photo.image
|
||||||
|
|
@ -6,11 +19,11 @@
|
||||||
= link_to 'Edit Photo', edit_photo_path(@photo), :class => "button"
|
= link_to 'Edit Photo', edit_photo_path(@photo), :class => "button"
|
||||||
|
|
||||||
.sub_header
|
.sub_header
|
||||||
= link_to_prev @photo, @album
|
= link_to "<< prev", url_to_prev(@photo, @album)
|
||||||
|
|
|
|
||||||
= link_to "full size", @photo.url
|
= link_to "full size", @photo.url
|
||||||
|
|
|
|
||||||
= link_to_next @photo, @album
|
= link_to "next >>", url_to_next(@photo, @album)
|
||||||
|
|
||||||
%div{:id => @photo.id}
|
%div{:id => @photo.id}
|
||||||
#show_photo
|
#show_photo
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
= form_for @request do |f|
|
|
||||||
= f.error_messages
|
|
||||||
|
|
||||||
.field_with_submit
|
|
||||||
= f.text_field :destination_url
|
|
||||||
= f.submit
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
%h1 requests
|
|
||||||
|
|
||||||
= render 'form'
|
|
||||||
|
|
||||||
%p= link_to "Back to List", requests_path
|
|
||||||
|
|
@ -1,8 +1,16 @@
|
||||||
#group
|
#group
|
||||||
%ul
|
%ul
|
||||||
|
- if @group == :all
|
||||||
|
= link_to "All Groups", root_url, :class => "selected"
|
||||||
|
|
||||||
|
- elsif @group
|
||||||
|
= link_to @group.name, @group, :class => "selected"
|
||||||
|
= link_to "edit", edit_group_path(@group)
|
||||||
|
|
||||||
- for group in @groups
|
- for group in @groups
|
||||||
%li{:class => ("selected" if group.id.to_s == params[:id])}
|
- unless (group.id.to_s == params[:id])
|
||||||
= link_to group.name, group
|
%li
|
||||||
|
= link_to group.name, group
|
||||||
|
|
||||||
%li.new_group= link_to("NEW GROUP", "#add_group_pane", :id => "add_group_button")
|
%li.new_group= link_to("NEW GROUP", "#add_group_pane", :id => "add_group_button")
|
||||||
|
|
||||||
|
|
@ -12,15 +20,11 @@
|
||||||
|
|
||||||
- if @group
|
- if @group
|
||||||
#friend_pictures
|
#friend_pictures
|
||||||
- for friend in @group.people
|
- for friend in @friends
|
||||||
= person_image_link(friend)
|
= person_image_link(friend)
|
||||||
= link_to (image_tag 'add_friend_button.png'), "#add_request_pane", :id => 'add_request_button'
|
= link_to (image_tag 'add_friend_button.png'), "#add_request_pane", :id => 'add_request_button'
|
||||||
|
|
||||||
- if @group.people.count == 0
|
- unless @group == :all
|
||||||
%span.add_new_description
|
.yo{:style => 'display:none'}
|
||||||
<< click the plus to add friends to this group
|
#add_request_pane
|
||||||
|
= render "requests/new_request"
|
||||||
|
|
||||||
.yo{:style => 'display:none'}
|
|
||||||
#add_request_pane
|
|
||||||
= render "requests/new_request"
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,24 @@
|
||||||
#publisher
|
#publisher
|
||||||
#publisher_form
|
.span-19.last
|
||||||
= form_for StatusMessage.new, :remote => true do |f|
|
= form_for StatusMessage.new, :remote => true do |f|
|
||||||
= f.error_messages
|
= f.error_messages
|
||||||
|
|
||||||
-if group_id
|
.span-15.last
|
||||||
= f.hidden_field :group_id, :value => group_id
|
.span-2.last
|
||||||
|
.user_image
|
||||||
|
= owner_image_tag
|
||||||
|
.span-13.last
|
||||||
|
%p
|
||||||
|
%label{:for => "status_message_message"} Message
|
||||||
|
= f.text_area :message, :rows => 2
|
||||||
|
|
||||||
|
.span-3.last
|
||||||
|
|
||||||
%label{:for => "status_message_message"} Message
|
%ul.group_selector
|
||||||
= f.text_area :message, :rows => 2
|
going to...
|
||||||
%ul
|
- for group in current_user.groups
|
||||||
- for group in current_user.groups
|
%li
|
||||||
%li
|
= check_box_tag("group_ids[]", group.id, current_group?(group) )
|
||||||
= group.name
|
= group.name
|
||||||
= check_box_tag("groups_id[]", group.id, current_group?(group))
|
.span-1.last
|
||||||
.right
|
|
||||||
= f.submit "Post"
|
= f.submit "Post"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,17 @@
|
||||||
development:
|
development:
|
||||||
debug: false
|
debug: false
|
||||||
|
socket_debug : false
|
||||||
socket_port: 8080
|
socket_port: 8080
|
||||||
pubsub_server: 'https://pubsubhubbub.appspot.com/'
|
pubsub_server: 'https://pubsubhubbub.appspot.com/'
|
||||||
|
|
||||||
test:
|
test:
|
||||||
debug: false
|
debug: false
|
||||||
|
socket_debug : false
|
||||||
socket_port: 8081
|
socket_port: 8081
|
||||||
pubsub_server: 'https://pubsubhubbub.appspot.com/'
|
pubsub_server: 'https://pubsubhubbub.appspot.com/'
|
||||||
|
|
||||||
production:
|
production:
|
||||||
debug: false
|
debug: false
|
||||||
|
socket_debug : false
|
||||||
socket_port: 8080
|
socket_port: 8080
|
||||||
pubsub_server: 'https://pubsubhubbub.appspot.com/'
|
pubsub_server: 'https://pubsubhubbub.appspot.com/'
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
require 'lib/mongo_mapper/clear_dev_memory'
|
||||||
Diaspora::Application.configure do
|
Diaspora::Application.configure do
|
||||||
# Settings specified here will take precedence over those in config/environment.rb
|
# Settings specified here will take precedence over those in config/environment.rb
|
||||||
|
|
||||||
|
|
@ -17,6 +18,7 @@ Diaspora::Application.configure do
|
||||||
# Don't care if the mailer can't send
|
# Don't care if the mailer can't send
|
||||||
config.action_mailer.raise_delivery_errors = true
|
config.action_mailer.raise_delivery_errors = true
|
||||||
config.active_support.deprecation = :log
|
config.active_support.deprecation = :log
|
||||||
|
config.middleware.use MongoMapper::ClearDevMemory
|
||||||
#config.threadsafe!
|
#config.threadsafe!
|
||||||
config.action_mailer.delivery_method = :smtp
|
config.action_mailer.delivery_method = :smtp
|
||||||
config.action_mailer.default_url_options = {:host => 'localhost:3000'}
|
config.action_mailer.default_url_options = {:host => 'localhost:3000'}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ require "lib/diaspora/websocket"
|
||||||
EventMachine::WebSocket.start(
|
EventMachine::WebSocket.start(
|
||||||
:host => "0.0.0.0",
|
:host => "0.0.0.0",
|
||||||
:port => APP_CONFIG[:socket_port],
|
:port => APP_CONFIG[:socket_port],
|
||||||
:debug =>APP_CONFIG[:debug]) do |ws|
|
:debug =>APP_CONFIG[:socket_debug]) do |ws|
|
||||||
ws.onopen {
|
ws.onopen {
|
||||||
|
|
||||||
sid = Diaspora::WebSocket.subscribe(ws.request['Path'].gsub('/',''), ws)
|
sid = Diaspora::WebSocket.subscribe(ws.request['Path'].gsub('/',''), ws)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
Diaspora::Application.routes.draw do
|
Diaspora::Application.routes.draw do
|
||||||
resources :people
|
resources :people, :only => [:index, :show, :destroy]
|
||||||
resources :users, :except => [:create, :new]
|
resources :users, :except => [:create, :new]
|
||||||
resources :status_messages
|
resources :status_messages, :except => [:index]
|
||||||
resources :comments
|
resources :comments, :except => [:index]
|
||||||
resources :requests
|
resources :requests, :except => [:edit, :update]
|
||||||
resources :photos
|
resources :photos, :except => [:index]
|
||||||
resources :albums
|
resources :albums
|
||||||
resources :groups
|
resources :groups
|
||||||
|
|
||||||
|
|
|
||||||
19
lib/mongo_mapper/clear_dev_memory.rb
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
module MongoMapper
|
||||||
|
class ClearDevMemory
|
||||||
|
def initialize(app)
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
if Rails.configuration.cache_classes
|
||||||
|
else
|
||||||
|
MongoMapper::Document.descendants.each do |m|
|
||||||
|
m.descendants.clear if m.respond_to? :descendants
|
||||||
|
end
|
||||||
|
MongoMapper::Document.descendants.clear
|
||||||
|
MongoMapper::EmbeddedDocument.descendants.clear
|
||||||
|
end
|
||||||
|
@app.call(env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
220
lib/salmon/salmon.rb
Normal file
|
|
@ -0,0 +1,220 @@
|
||||||
|
# Add URL safe Base64 support
|
||||||
|
module Base64
|
||||||
|
module_function
|
||||||
|
# Returns the Base64-encoded version of +bin+.
|
||||||
|
# This method complies with RFC 4648.
|
||||||
|
# No line feeds are added.
|
||||||
|
def strict_encode64(bin)
|
||||||
|
[bin].pack("m0")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the Base64-decoded version of +str+.
|
||||||
|
# This method complies with RFC 4648.
|
||||||
|
# ArgumentError is raised if +str+ is incorrectly padded or contains
|
||||||
|
# non-alphabet characters. Note that CR or LF are also rejected.
|
||||||
|
def strict_decode64(str)
|
||||||
|
str.unpack("m0").first
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the Base64-encoded version of +bin+.
|
||||||
|
# This method complies with ``Base 64 Encoding with URL and Filename Safe
|
||||||
|
# Alphabet'' in RFC 4648.
|
||||||
|
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
||||||
|
def urlsafe_encode64(bin)
|
||||||
|
strict_encode64(bin).tr("+/", "-_")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the Base64-decoded version of +str+.
|
||||||
|
# This method complies with ``Base 64 Encoding with URL and Filename Safe
|
||||||
|
# Alphabet'' in RFC 4648.
|
||||||
|
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
||||||
|
def urlsafe_decode64(str)
|
||||||
|
strict_decode64(str.tr("-_", "+/"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Verify documents secured with Magic Signatures
|
||||||
|
module Salmon
|
||||||
|
class SalmonSlap
|
||||||
|
attr_accessor :magic_sig, :user, :data, :data_type, :sig
|
||||||
|
def self.parse(xml)
|
||||||
|
slap = self.new
|
||||||
|
doc = Nokogiri::XML(xml)
|
||||||
|
|
||||||
|
sig_doc = doc.search('entry')
|
||||||
|
slap.magic_sig = MagicSigEnvelope.parse sig_doc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if 'base64url' == slap.magic_sig.encoding
|
||||||
|
slap.data = decode64url(slap.magic_sig.data)
|
||||||
|
slap.sig = slap.magic_sig.sig
|
||||||
|
else
|
||||||
|
raise ArgumentError, "Magic Signature data must be encoded with base64url, was #{slap.magic_sig.encoding}"
|
||||||
|
end
|
||||||
|
|
||||||
|
slap.data_type = slap.magic_sig.data_type
|
||||||
|
|
||||||
|
raise ArgumentError, "Magic Signature data must be signed with RSA-SHA256, was #{slap.magic_sig.alg}" unless 'RSA-SHA256' == slap.magic_sig.alg
|
||||||
|
|
||||||
|
slap
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def self.create(user, activity)
|
||||||
|
salmon = self.new
|
||||||
|
salmon.user = user
|
||||||
|
salmon.magic_sig = MagicSigEnvelope.create(user, activity)
|
||||||
|
salmon
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_xml
|
||||||
|
xml =<<ENTRY
|
||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<entry xmlns='http://www.w3.org/2005/Atom'>
|
||||||
|
<author>
|
||||||
|
<name>#{@user.real_name}</name>
|
||||||
|
<uri>acct:#{@user.email}</uri>
|
||||||
|
</author>
|
||||||
|
#{@magic_sig.to_xml}
|
||||||
|
</entry>
|
||||||
|
ENTRY
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode URL-safe-Base64. This implements
|
||||||
|
def self.decode64url(str)
|
||||||
|
# remove whitespace
|
||||||
|
sans_whitespace = str.gsub(/\s/, '')
|
||||||
|
# pad to a multiple of 4
|
||||||
|
string = sans_whitespace + '=' * ((4 - sans_whitespace.size) % 4)
|
||||||
|
# convert to standard Base64
|
||||||
|
# string = padded.tr('-','+').tr('_','/')
|
||||||
|
|
||||||
|
# Base64.decode64(string)
|
||||||
|
Base64.urlsafe_decode64 string
|
||||||
|
end
|
||||||
|
|
||||||
|
# def verified?
|
||||||
|
#
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Check whether this envelope's signature can be verified with the
|
||||||
|
# provided OpenSSL::PKey::RSA public_key.
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# env.verified_for_key? OpenSSL::PKey::RSA.new(File.open('public_key.pem'))
|
||||||
|
# # -> true
|
||||||
|
def verified_for_key?(public_key)
|
||||||
|
signature = Base64.urlsafe_decode64(self.magic_sig.sig)
|
||||||
|
signed_data = self.magic_sig.signable_string# Base64.urlsafe_decode64(self.magic_sig.signable_string)
|
||||||
|
|
||||||
|
|
||||||
|
public_key.verify(OpenSSL::Digest::SHA256.new, signature, signed_data )
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode a string containing URL safe Base64 into an integer
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# MagicSig.b64_to_n('AQAB')
|
||||||
|
# # -> 645537
|
||||||
|
def self.b64_to_n(str)
|
||||||
|
packed = decode64url(str)
|
||||||
|
packed.unpack('B*')[0].to_i(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse a string containing a magic-public-key into an OpenSSL::PKey::RSA key.
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# key = MagicSig.parse_key('RSA.mVgY8RN6URBTstndvmUUPb4UZTdwvwmddSKE5z_jvKUEK6yk1u3rrC9yN8k6FilGj9K0eeUPe2hf4Pj-5CmHww.AQAB')
|
||||||
|
# key.n
|
||||||
|
# # -> 8031283789075196565022891546563591368344944062154100509645398892293433370859891943306439907454883747534493461257620351548796452092307094036643522661681091
|
||||||
|
# key.e
|
||||||
|
# # -> 65537
|
||||||
|
def self.parse_key(str)
|
||||||
|
n,e = str.match(/^RSA.([^.]*).([^.]*)$/)[1..2]
|
||||||
|
build_key(b64_to_n(n),b64_to_n(e))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Take two integers e, n and create a new OpenSSL::PKey::RSA key with them
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# n = 9487834027867356975347184933768917275269369900665861930617802608089634337052392076689226301419587057117740995382286148368168197915234368486155306558161867
|
||||||
|
# e = 65537
|
||||||
|
# key = MagicSig.build_key(n,e)
|
||||||
|
# key.public_encrypt(...) # for sending to strangers
|
||||||
|
# key.public_decrypt(...) # very rarely used
|
||||||
|
# key.verify(...) # for verifying signatures
|
||||||
|
def self.build_key(n,e)
|
||||||
|
key = OpenSSL::PKey::RSA.new
|
||||||
|
key.n = n
|
||||||
|
key.e = e
|
||||||
|
key
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class MagicSigEnvelope
|
||||||
|
attr_accessor :data, :data_type, :encoding, :alg, :sig, :user
|
||||||
|
def self.parse(doc)
|
||||||
|
env = self.new
|
||||||
|
ns = {'me'=>'http://salmon-protocol.org/ns/magic-env'}
|
||||||
|
env.encoding = doc.search('//me:env/me:encoding', ns).text.strip
|
||||||
|
env.data = doc.search('//me:env/me:data', ns).text
|
||||||
|
env.alg = doc.search('//me:env/me:alg', ns).text.strip
|
||||||
|
env.sig = doc.search('//me:env/me:sig', ns).text
|
||||||
|
env.data_type = doc.search('//me:env/me:data', ns).first['type'].strip
|
||||||
|
env
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create(user, activity)
|
||||||
|
env = MagicSigEnvelope.new
|
||||||
|
env.user = user
|
||||||
|
env.data = Base64.urlsafe_encode64(activity)
|
||||||
|
env.data_type = env.get_data_type
|
||||||
|
env.encoding = env.get_encoding
|
||||||
|
env.alg = env.get_alg
|
||||||
|
|
||||||
|
|
||||||
|
env.sig = Base64.urlsafe_encode64(
|
||||||
|
user.encryption_key.sign OpenSSL::Digest::SHA256.new, env.signable_string )
|
||||||
|
|
||||||
|
env
|
||||||
|
end
|
||||||
|
|
||||||
|
def signable_string
|
||||||
|
[@data, Base64.urlsafe_encode64(@data_type),Base64.urlsafe_encode64(@encoding), Base64.urlsafe_encode64(@alg)].join(".")
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_xml
|
||||||
|
xml= <<ENTRY
|
||||||
|
<me:env xmlns:me="http://salmon-protocol.org/ns/magic-env">
|
||||||
|
<me:data type='#{@data_type}'>#{@data}</me:data>
|
||||||
|
<me:encoding>#{@encoding}</me:encoding>
|
||||||
|
<me:alg>#{@alg}</me:alg>
|
||||||
|
<me:sig>#{@sig}</me:sig>
|
||||||
|
</me:env>
|
||||||
|
ENTRY
|
||||||
|
xml
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_encoding
|
||||||
|
'base64url'
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_data_type
|
||||||
|
'application/atom+xml'
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_alg
|
||||||
|
'RSA-SHA256'
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -29,7 +29,7 @@ namespace :db do
|
||||||
MongoMapper::connection.drop_database(MongoMapper::database.name)
|
MongoMapper::connection.drop_database(MongoMapper::database.name)
|
||||||
|
|
||||||
puts 'Deleting tmp folder...'
|
puts 'Deleting tmp folder...'
|
||||||
`rm -rf #{File.dirname(__FILE__)}/../../public/uploads/tmp`
|
`rm -rf #{File.dirname(__FILE__)}/../../public/uploads/*`
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Purge and seed the current RAILS_ENV database using information from db/seeds.rb'
|
desc 'Purge and seed the current RAILS_ENV database using information from db/seeds.rb'
|
||||||
|
|
|
||||||
13
public/images/glyphish-icons/Read me first - license.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
Created by Joseph Wain (see http://penandthink.com) at and probably downloaded from http://glyphish.com
|
||||||
|
|
||||||
|
This work is licensed under the Creative Commons Attribution 3.0 United States License. To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
|
||||||
|
|
||||||
|
You are free to share it and to remix it remix under the following conditions:
|
||||||
|
|
||||||
|
* You must attribute the work in the manner specified by the author (SEE BELOW).
|
||||||
|
* For any reuse or distribution, you must make clear to others the license terms of this work.
|
||||||
|
* The above conditions can be waived if you get permission from the copyright holder (send me an email!).
|
||||||
|
|
||||||
|
ATTRIBUTION -- a note reading "icons by Joseph Wain / glyphish.com" or similar, plus a link back to glyphish.com from your app's website, is the preferred form of attribution. Also acceptable would be, like, a link from within your iPhone application, or from the iTunes store page, but those aren't as useful to other people. If none of these work for you, please contact hello@glyphish.com and we can work something out.
|
||||||
|
|
||||||
|
USE WITHOUT ATTRIBUTION -- If attribution is not possible, workable or desirable for your application, contact hello@glyphish.com for commercial non-attributed licensing terms.
|
||||||
1637
public/images/glyphish-icons/glyphish-icons.pdf
Normal file
BIN
public/images/glyphish-icons/icons/01-refresh.png
Normal file
|
After Width: | Height: | Size: 459 B |
BIN
public/images/glyphish-icons/icons/02-redo.png
Normal file
|
After Width: | Height: | Size: 490 B |
BIN
public/images/glyphish-icons/icons/03-loopback.png
Normal file
|
After Width: | Height: | Size: 473 B |
BIN
public/images/glyphish-icons/icons/04-squiggle.png
Normal file
|
After Width: | Height: | Size: 411 B |
BIN
public/images/glyphish-icons/icons/05-shuffle.png
Normal file
|
After Width: | Height: | Size: 356 B |
BIN
public/images/glyphish-icons/icons/06-magnifying-glass.png
Normal file
|
After Width: | Height: | Size: 388 B |
BIN
public/images/glyphish-icons/icons/07-map-marker.png
Normal file
|
After Width: | Height: | Size: 353 B |
BIN
public/images/glyphish-icons/icons/08-chat.png
Normal file
|
After Width: | Height: | Size: 281 B |
BIN
public/images/glyphish-icons/icons/09-chat2.png
Normal file
|
After Width: | Height: | Size: 311 B |
BIN
public/images/glyphish-icons/icons/10-medical.png
Normal file
|
After Width: | Height: | Size: 210 B |
BIN
public/images/glyphish-icons/icons/100-coffee.png
Normal file
|
After Width: | Height: | Size: 267 B |
BIN
public/images/glyphish-icons/icons/101-gameplan.png
Normal file
|
After Width: | Height: | Size: 447 B |
BIN
public/images/glyphish-icons/icons/102-walk.png
Normal file
|
After Width: | Height: | Size: 445 B |
BIN
public/images/glyphish-icons/icons/103-map.png
Normal file
|
After Width: | Height: | Size: 507 B |
BIN
public/images/glyphish-icons/icons/104-index-cards.png
Normal file
|
After Width: | Height: | Size: 263 B |
BIN
public/images/glyphish-icons/icons/105-piano.png
Normal file
|
After Width: | Height: | Size: 158 B |
BIN
public/images/glyphish-icons/icons/106-sliders.png
Normal file
|
After Width: | Height: | Size: 235 B |
BIN
public/images/glyphish-icons/icons/107-widescreen.png
Normal file
|
After Width: | Height: | Size: 309 B |
BIN
public/images/glyphish-icons/icons/108-badge.png
Normal file
|
After Width: | Height: | Size: 371 B |
BIN
public/images/glyphish-icons/icons/109-chicken.png
Normal file
|
After Width: | Height: | Size: 276 B |
BIN
public/images/glyphish-icons/icons/11-clock.png
Normal file
|
After Width: | Height: | Size: 508 B |
BIN
public/images/glyphish-icons/icons/110-bug.png
Normal file
|
After Width: | Height: | Size: 546 B |
BIN
public/images/glyphish-icons/icons/111-user.png
Normal file
|
After Width: | Height: | Size: 310 B |
BIN
public/images/glyphish-icons/icons/112-group.png
Normal file
|
After Width: | Height: | Size: 467 B |
BIN
public/images/glyphish-icons/icons/113-navigation.png
Normal file
|
After Width: | Height: | Size: 418 B |
BIN
public/images/glyphish-icons/icons/114-balloon.png
Normal file
|
After Width: | Height: | Size: 416 B |
BIN
public/images/glyphish-icons/icons/115-bow-and-arrow.png
Normal file
|
After Width: | Height: | Size: 567 B |
BIN
public/images/glyphish-icons/icons/116-controller.png
Normal file
|
After Width: | Height: | Size: 523 B |
BIN
public/images/glyphish-icons/icons/117-todo.png
Normal file
|
After Width: | Height: | Size: 324 B |
BIN
public/images/glyphish-icons/icons/118-coathanger.png
Normal file
|
After Width: | Height: | Size: 435 B |
BIN
public/images/glyphish-icons/icons/119-piggybank.png
Normal file
|
After Width: | Height: | Size: 395 B |
BIN
public/images/glyphish-icons/icons/12-eye.png
Normal file
|
After Width: | Height: | Size: 322 B |
BIN
public/images/glyphish-icons/icons/120-headphones.png
Normal file
|
After Width: | Height: | Size: 351 B |
BIN
public/images/glyphish-icons/icons/121-lanscape.png
Normal file
|
After Width: | Height: | Size: 292 B |
BIN
public/images/glyphish-icons/icons/122-stats.png
Normal file
|
After Width: | Height: | Size: 358 B |
BIN
public/images/glyphish-icons/icons/123-id-card.png
Normal file
|
After Width: | Height: | Size: 270 B |
BIN
public/images/glyphish-icons/icons/124-bullhorn.png
Normal file
|
After Width: | Height: | Size: 254 B |
BIN
public/images/glyphish-icons/icons/125-food.png
Normal file
|
After Width: | Height: | Size: 356 B |
BIN
public/images/glyphish-icons/icons/126-moon.png
Normal file
|
After Width: | Height: | Size: 336 B |
BIN
public/images/glyphish-icons/icons/127-sock.png
Normal file
|
After Width: | Height: | Size: 308 B |
BIN
public/images/glyphish-icons/icons/128-bone.png
Normal file
|
After Width: | Height: | Size: 223 B |
BIN
public/images/glyphish-icons/icons/129-golf.png
Normal file
|
After Width: | Height: | Size: 418 B |
BIN
public/images/glyphish-icons/icons/13-target.png
Normal file
|
After Width: | Height: | Size: 601 B |
BIN
public/images/glyphish-icons/icons/130-dice.png
Normal file
|
After Width: | Height: | Size: 445 B |
BIN
public/images/glyphish-icons/icons/14-tag.png
Normal file
|
After Width: | Height: | Size: 350 B |
BIN
public/images/glyphish-icons/icons/15-tags.png
Normal file
|
After Width: | Height: | Size: 489 B |
BIN
public/images/glyphish-icons/icons/16-line-chart.png
Normal file
|
After Width: | Height: | Size: 550 B |
BIN
public/images/glyphish-icons/icons/17-bar-chart.png
Normal file
|
After Width: | Height: | Size: 181 B |
BIN
public/images/glyphish-icons/icons/18-envelope.png
Normal file
|
After Width: | Height: | Size: 248 B |
BIN
public/images/glyphish-icons/icons/19-gear.png
Normal file
|
After Width: | Height: | Size: 413 B |
BIN
public/images/glyphish-icons/icons/20-gear2.png
Normal file
|
After Width: | Height: | Size: 375 B |
BIN
public/images/glyphish-icons/icons/21-skull.png
Normal file
|
After Width: | Height: | Size: 397 B |
BIN
public/images/glyphish-icons/icons/22-skull-n-crossbones.png
Normal file
|
After Width: | Height: | Size: 743 B |
BIN
public/images/glyphish-icons/icons/23-bird.png
Normal file
|
After Width: | Height: | Size: 356 B |
BIN
public/images/glyphish-icons/icons/24-gift.png
Normal file
|
After Width: | Height: | Size: 359 B |
BIN
public/images/glyphish-icons/icons/25-weather.png
Normal file
|
After Width: | Height: | Size: 363 B |
BIN
public/images/glyphish-icons/icons/26-bandaid.png
Normal file
|
After Width: | Height: | Size: 302 B |
BIN
public/images/glyphish-icons/icons/27-planet.png
Normal file
|
After Width: | Height: | Size: 489 B |
BIN
public/images/glyphish-icons/icons/28-star.png
Normal file
|
After Width: | Height: | Size: 375 B |
BIN
public/images/glyphish-icons/icons/29-heart.png
Normal file
|
After Width: | Height: | Size: 280 B |
BIN
public/images/glyphish-icons/icons/30-key.png
Normal file
|
After Width: | Height: | Size: 266 B |
BIN
public/images/glyphish-icons/icons/31-ipod.png
Normal file
|
After Width: | Height: | Size: 323 B |
BIN
public/images/glyphish-icons/icons/32-iphone.png
Normal file
|
After Width: | Height: | Size: 183 B |
BIN
public/images/glyphish-icons/icons/33-cabinet.png
Normal file
|
After Width: | Height: | Size: 167 B |
BIN
public/images/glyphish-icons/icons/34-coffee.png
Normal file
|
After Width: | Height: | Size: 303 B |
BIN
public/images/glyphish-icons/icons/35-shopping-bag.png
Normal file
|
After Width: | Height: | Size: 243 B |