another set of oauth work
This commit is contained in:
commit
b4f0d3b9eb
3
Gemfile
3
Gemfile
|
|
@ -28,6 +28,9 @@ gem 'tire'
|
|||
gem 'rb-readline'
|
||||
gem 'omniauth'
|
||||
gem 'omniauth-facebook'
|
||||
gem 'fb_graph'
|
||||
gem 'sendgrid'
|
||||
gem 'recaptcha'
|
||||
|
||||
group :development, :test do
|
||||
gem 'rspec-rails', '2.11.0'
|
||||
|
|
|
|||
|
|
@ -126,9 +126,7 @@ Message from Seth on sequence for creating/joining sessions:
|
|||
self.location = '#/session/' + newSessionId;
|
||||
});
|
||||
}
|
||||
).fail(function(jqXHR, textStatus, errorMessage) {
|
||||
app.notify({title: textStatus, text: errorMessage, detail: jqXHR.responseText});
|
||||
});
|
||||
).fail(app.ajaxError);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -147,9 +145,7 @@ Message from Seth on sequence for creating/joining sessions:
|
|||
data: invite
|
||||
}).done(function(response) {
|
||||
callCount--;
|
||||
}).fail(function(jqXHR, textStatus, errorMessage) {
|
||||
app.notify({title: textStatus, text: errorMessage, detail: jqXHR.responseText});
|
||||
});
|
||||
}).fail(app.ajaxError);
|
||||
});
|
||||
// TODO - this is the second time I've used this pattern.
|
||||
// refactor to make a common utility for this.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
context.JK.Header = function(app) {
|
||||
|
||||
var logger = context.JK.logger;
|
||||
var searcher; // Will hold an instance to a JK.Searcher (search.js)
|
||||
var userMe = null;
|
||||
var instrumentAutoComplete;
|
||||
var instrumentIds = [];
|
||||
|
|
@ -97,9 +98,7 @@
|
|||
data: JSON.stringify(user)
|
||||
}).done(function(response) {
|
||||
userMe = response;
|
||||
}).fail(function(jqXHR, textStatus, errorMessage) {
|
||||
app.notify({title: textStatus, text: errorMessage, detail: jqXHR.responseText});
|
||||
});
|
||||
}).fail(app.ajaxError);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -134,9 +133,7 @@
|
|||
data: JSON.stringify(user)
|
||||
}).done(function(response) {
|
||||
userMe = response;
|
||||
}).fail(function(jqXHR, textStatus, errorMessage) {
|
||||
app.notify({title: textStatus, text: errorMessage, detail: jqXHR.responseText});
|
||||
});
|
||||
}).fail(app.ajaxError);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -149,9 +146,7 @@
|
|||
}).done(function(r) {
|
||||
userMe = r;
|
||||
updateAccountForms();
|
||||
}).fail(function(jqXHR, textStatus, errorMessage) {
|
||||
app.notify({title: textStatus, text: errorMessage, detail: jqXHR.responseText});
|
||||
});
|
||||
}).fail(app.ajaxError);
|
||||
}
|
||||
|
||||
function updateAccountForms() {
|
||||
|
|
@ -178,6 +173,9 @@
|
|||
events();
|
||||
loadInstruments();
|
||||
loadMe();
|
||||
|
||||
searcher = new JK.Searcher(app);
|
||||
searcher.initialize();
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,13 @@
|
|||
context.JK.MessageType.LOGIN_ACK, loggedIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic error handler for Ajax calls.
|
||||
*/
|
||||
function ajaxError(jqXHR, textStatus, errorMessage) {
|
||||
notify({title: textStatus, text: errorMessage, detail: jqXHR.responseText});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register for all known types, logging events as they happen, and
|
||||
* notifying subscribers (see this.subscribe) as they occur.
|
||||
|
|
@ -107,6 +114,11 @@
|
|||
*/
|
||||
this.fireEvent = handleMessage;
|
||||
|
||||
/**
|
||||
* Expose ajaxError.
|
||||
*/
|
||||
this.ajaxError = ajaxError;
|
||||
|
||||
/**
|
||||
* Provide a handler object for events related to a particular screen
|
||||
* being shown or hidden.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
client.JoinSession({ sessionID: session_id });
|
||||
}
|
||||
context.JK.refreshMusicSession(session_id);
|
||||
});
|
||||
}).fail(app.ajaxError);
|
||||
};
|
||||
|
||||
})(window,jQuery);
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
(function(context,$) {
|
||||
|
||||
context.JK = context.JK || {};
|
||||
context.JK.Searcher = function(app) {
|
||||
var logger = context.JK.logger;
|
||||
|
||||
var searchSectionTemplate;
|
||||
var searchItemTemplate;
|
||||
var noResultsTemplate;
|
||||
|
||||
function events() {
|
||||
$('.searchtextinput').keyup(handleKeyup);
|
||||
$('.searchtextinput').focus(function(evt) {
|
||||
var searchVal = $(this).val();
|
||||
search(searchVal);
|
||||
});
|
||||
$('.searchtextinput').blur(hideSearchResults);
|
||||
}
|
||||
|
||||
function templates() {
|
||||
searchSectionTemplate = $('#template-search-section').html();
|
||||
searchItemTemplate = $('#template-search-item').html();
|
||||
noResultsTemplate = $('#template-search-noresults').html();
|
||||
}
|
||||
|
||||
function hideSearchResults() {
|
||||
$('.searchresults').hide();
|
||||
}
|
||||
|
||||
function showSearchResults() {
|
||||
$('.searchresults').show();
|
||||
}
|
||||
|
||||
function handleKeyup(evt) {
|
||||
if (evt.which === 27) {
|
||||
return hideSearchResults();
|
||||
}
|
||||
var searchVal = $(this).val();
|
||||
search(searchVal);
|
||||
}
|
||||
|
||||
function search(query) {
|
||||
if (query.length < 2) {
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/api/search?query=" + query,
|
||||
success: searchResponse,
|
||||
error: app.ajaxError
|
||||
});
|
||||
}
|
||||
|
||||
function searchResponse(response) {
|
||||
ensureResultsDiv();
|
||||
updateResultsDiv(response);
|
||||
positionResultsDiv();
|
||||
showSearchResults();
|
||||
}
|
||||
|
||||
function ensureResultsDiv() {
|
||||
if ($('.searchresults').length === 0) {
|
||||
$searchresults = $('<div/>');
|
||||
$searchresults.addClass('searchresults');
|
||||
$searchresults.css({position:'absolute'});
|
||||
$('body').append($searchresults);
|
||||
}
|
||||
}
|
||||
|
||||
function updateResultsDiv(searchResults) {
|
||||
var sections = ['musicians', 'bands', 'fans', 'recordings'];
|
||||
var fullHtml = '';
|
||||
$.each(sections, function() {
|
||||
fullHtml += getSectionHtml(this, searchResults);
|
||||
});
|
||||
if (fullHtml === '') {
|
||||
fullHtml += getNoResultsMessage();
|
||||
}
|
||||
$('.searchresults').html(fullHtml);
|
||||
}
|
||||
|
||||
function getNoResultsMessage() {
|
||||
// No replacement needed at the moment.
|
||||
return noResultsTemplate;
|
||||
}
|
||||
|
||||
function getSectionHtml(section, searchResults) {
|
||||
if (section in searchResults && searchResults[section].length === 0) {
|
||||
return '';
|
||||
}
|
||||
var items = '';
|
||||
$.each(searchResults[section], function() {
|
||||
items += getItemHtml(this);
|
||||
});
|
||||
var html = JK.fillTemplate(
|
||||
searchSectionTemplate,
|
||||
{ section: section, items: items });
|
||||
return html;
|
||||
}
|
||||
|
||||
function getItemHtml(item) {
|
||||
var replacements = {
|
||||
id: item.id,
|
||||
name: item.first_name + " " + item.last_name,
|
||||
image: item.photo_url,
|
||||
subtext: item.location
|
||||
};
|
||||
return JK.fillTemplate(
|
||||
searchItemTemplate, replacements);
|
||||
}
|
||||
|
||||
function positionResultsDiv() {
|
||||
var bodyOffset = $('body').offset();
|
||||
var inputOffset = $('.searchtextinput').offset();
|
||||
var inputHeight = $('.searchtextinput').outerHeight();
|
||||
var resultsTop = bodyOffset.top + inputOffset.top + inputHeight;
|
||||
var resultsLeft = bodyOffset.left + inputOffset.left;
|
||||
$('.searchresults').css({
|
||||
top: resultsTop + 'px',
|
||||
left: resultsLeft + 'px'});
|
||||
}
|
||||
|
||||
this.initialize = function() {
|
||||
events();
|
||||
templates();
|
||||
};
|
||||
};
|
||||
|
||||
})(window,jQuery);
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/* Styles used by things related to search */
|
||||
@import "client/common.css.scss";
|
||||
|
||||
/* Container for the search input */
|
||||
.header .search {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -125px;
|
||||
top: 26px;
|
||||
}
|
||||
|
||||
.searchtextinput {
|
||||
border: 1px solid #fff;
|
||||
background:none;
|
||||
color:#fff;
|
||||
font-size: 120%;
|
||||
line-height: 120%;
|
||||
width: 250px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.searchresults {
|
||||
background-color:$color8;
|
||||
border:1px solid #000;
|
||||
color:#000;
|
||||
}
|
||||
|
||||
.searchresults h2 {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
background-color: shade($color8, 10%);
|
||||
}
|
||||
|
||||
.searchresults li {
|
||||
clear:both;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.searchresults img {
|
||||
float:left;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 1px solid #333;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.searchresults .text {
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.searchresults .subtext {
|
||||
display:block;
|
||||
color: #000;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
class ApiBandsController < ApplicationController
|
||||
|
||||
before_filter :signed_in_user, only: [:index, :show, :create, :update,
|
||||
before_filter :api_signed_in_user, only: [:index, :show, :create, :update,
|
||||
:following_create, :following_destroy]
|
||||
|
||||
respond_to :json
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
class ApiGenresController < ApiController
|
||||
|
||||
# have to be signed in currently to see this screen
|
||||
before_filter :signed_in_user
|
||||
before_filter :api_signed_in_user
|
||||
|
||||
respond_to :json
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
class ApiInstrumentsController < ApiController
|
||||
|
||||
# have to be signed in currently to see this screen
|
||||
before_filter :signed_in_user
|
||||
before_filter :api_signed_in_user
|
||||
|
||||
respond_to :json
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
class ApiInvitationsController < ApiController
|
||||
|
||||
# have to be signed in currently to see this screen
|
||||
before_filter :signed_in_user
|
||||
before_filter :api_signed_in_user
|
||||
|
||||
respond_to :json
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
class ApiMusicSessionsController < ApiController
|
||||
|
||||
# have to be signed in currently to see this screen
|
||||
before_filter :signed_in_user
|
||||
before_filter :api_signed_in_user
|
||||
|
||||
respond_to :json
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
class ApiSearchController < ApiController
|
||||
|
||||
# have to be signed in currently to see this screen
|
||||
before_filter :signed_in_user
|
||||
before_filter :api_signed_in_user
|
||||
|
||||
respond_to :json
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
class ApiUsersController < ApplicationController
|
||||
class ApiUsersController < ApiController
|
||||
|
||||
before_filter :signed_in_user, only: [:index, :edit, :update, :delete,
|
||||
before_filter :api_signed_in_user, only: [:index, :show, :edit, :update, :delete,
|
||||
:friend_request_index, :friend_request_show,
|
||||
:friend_request_create, :friend_request_update,
|
||||
:friend_index, :friend_destroy]
|
||||
|
|
@ -8,24 +8,48 @@ class ApiUsersController < ApplicationController
|
|||
respond_to :json
|
||||
|
||||
def index
|
||||
@users = User.paginate(page: params[:page])
|
||||
# don't return users that aren't yet confirmed
|
||||
@users = User.where('email_confirmed=TRUE').paginate(page: params[:page])
|
||||
end
|
||||
|
||||
def show
|
||||
@user = User.find(params[:id])
|
||||
# don't return users that aren't yet confirmed
|
||||
@user = User.where('email_confirmed=TRUE').find(params[:id])
|
||||
end
|
||||
|
||||
# this API call is disabled by virtue of it being commented out in routes.rb
|
||||
# the reason is that it has no captcha, and is therefore a bit abuseable
|
||||
# if someone wants to use it, please add in captcha or some other bot-protector
|
||||
def create
|
||||
@user = User.save(params)
|
||||
|
||||
# check for errors
|
||||
if @user.errors.nil? || @user.errors.size == 0
|
||||
respond_with @user, responder: ApiResponder, :location => api_user_detail_url(@user)
|
||||
# sends email to email account for confirmation
|
||||
@user = UserManager.new.signup(params[:first_name],
|
||||
params[:last_name],
|
||||
params[:email],
|
||||
params[:password],
|
||||
params[:password_confirmation],
|
||||
params[:city],
|
||||
params[:state],
|
||||
params[:country],
|
||||
params[:instruments],
|
||||
ApplicationHelper.base_uri(request) + "/confirm")
|
||||
|
||||
# check for errors
|
||||
unless @user.errors.any?
|
||||
render :json => {}, :status => :ok # an empty response, but 200 OK
|
||||
else
|
||||
raise ActiveRecord::Rollback
|
||||
response.status = :unprocessable_entity
|
||||
respond_with @user
|
||||
respond_with @user, responder: ApiResponder
|
||||
end
|
||||
end
|
||||
|
||||
def signup_confirm
|
||||
@user = UserManager.new.signup_confirm(params[:signup_token])
|
||||
|
||||
unless @user.errors.any?
|
||||
respond_with @user, responder: ApiResponder, :location => api_user_detail_url(@user)
|
||||
else
|
||||
response.status = :unprocessable_entity
|
||||
respond_with @user, responder: ApiResponder
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -138,4 +162,21 @@ class ApiUsersController < ApplicationController
|
|||
respond_with responder: ApiResponder
|
||||
end
|
||||
|
||||
def auth_session_create
|
||||
@user = User.authenticate(params[:email], params[:password])
|
||||
|
||||
if @user.nil?
|
||||
render :json => { :success => false }, :status => 404
|
||||
else
|
||||
sign_in @user
|
||||
render :json => { :success => true }, :status => 200
|
||||
end
|
||||
end
|
||||
|
||||
def auth_session_delete
|
||||
sign_out
|
||||
render :json => { :success => true }, :status => 200
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
@ -8,12 +8,13 @@ class SessionsController < ApplicationController
|
|||
# http://net.tutsplus.com/tutorials/ruby/how-to-use-omniauth-to-authenticate-your-users/
|
||||
|
||||
def create
|
||||
user = User.find_by_email(params[:session][:email])
|
||||
if user && user.authenticate(params[:session][:password])
|
||||
complete_sign_in user
|
||||
else
|
||||
user = User.authenticate(params[:session][:email], params[:session][:password])
|
||||
|
||||
if user.nil?
|
||||
flash.now[:error] = 'Invalid email/password combination'
|
||||
render 'new'
|
||||
else
|
||||
complete_sign_in user
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -30,9 +31,26 @@ class SessionsController < ApplicationController
|
|||
#
|
||||
# For debugging - to see what all is there:
|
||||
# render :text => auth_hash.to_yaml
|
||||
user = User.new :name => auth_hash["info"]["name"], :email => auth_hash["info"]["email"]
|
||||
user.authorizations.build :provider => auth_hash["provider"], :uid => auth_hash["uid"],
|
||||
:token => auth_hash["credentials"]["token"], :token_expiration => auth_hash["credentials"]["expires_at"]
|
||||
#FbGraph.debug!
|
||||
#app = FbGraph::Application.new '468555793186398', :secret => '546a5b253972f3e2e8b36d9a3dd5a06e'
|
||||
token = auth_hash[:credentials][:token]
|
||||
|
||||
# FIXME:
|
||||
# This should probably be in a transaction somehow, meaning the user
|
||||
# create and the authorization create. Concern is UserManager.new.signup sends
|
||||
# an email and whatnot.
|
||||
user = UserManager.new.signup(auth_hash[:info][:first_name],
|
||||
auth_hash[:info][:last_name],
|
||||
auth_hash[:info][:email],
|
||||
nil,
|
||||
nil,
|
||||
auth_hash[:info][:location],
|
||||
nil, # state
|
||||
nil, # @country
|
||||
nil,
|
||||
nil)
|
||||
user.user_authorizations.build :provider => auth_hash[:provider], :uid => auth_hash[:uid],
|
||||
:token => auth_hash[:credentials][:token], :token_expiration => auth_hash[:credentials][:expires_at]
|
||||
user.save
|
||||
complete_sign_in user
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
class UsersController < ApplicationController
|
||||
before_filter :signed_in_user,
|
||||
before_filter :signed_in_user,
|
||||
only: [:index, :edit, :update, :destroy]
|
||||
before_filter :correct_user, only: [:edit, :update]
|
||||
before_filter :admin_user, only: :destroy
|
||||
|
||||
|
||||
def index
|
||||
@users = User.paginate(page: params[:page])
|
||||
end
|
||||
|
|
@ -17,12 +18,49 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
@user = User.new(params[:jam_ruby_user])
|
||||
if @user.save
|
||||
sign_in @user, :new => true
|
||||
else
|
||||
@user = User.new
|
||||
|
||||
# check recaptcha; if any errors seen, contribute it to the model
|
||||
unless verify_recaptcha(:model => @user, :message => "recaptcha")
|
||||
render 'new'
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@user = UserManager.new.signup(params[:jam_ruby_user][:name],
|
||||
params[:jam_ruby_user][:email],
|
||||
params[:jam_ruby_user][:password],
|
||||
params[:jam_ruby_user][:password_confirmation],
|
||||
params[:jam_ruby_user][:city],
|
||||
params[:jam_ruby_user][:state],
|
||||
params[:jam_ruby_user][:country],
|
||||
params[:jam_ruby_user][:instruments],
|
||||
ApplicationHelper.base_uri(request) + "/confirm")
|
||||
|
||||
# check for errors
|
||||
if @user.errors.any?
|
||||
# render any @user.errors on error
|
||||
render 'new'
|
||||
else
|
||||
# if success, redirect to 'email_sent' page
|
||||
flash[:success] = "Please check your email and confirm your signup"
|
||||
redirect_to :email_sent
|
||||
end
|
||||
end
|
||||
|
||||
def email_sent
|
||||
|
||||
end
|
||||
|
||||
def signup_confirm
|
||||
@user = UserManager.new.signup_confirm(params[:signup_token])
|
||||
|
||||
unless @user.nil? || @user.errors.any?
|
||||
sign_in @user
|
||||
redirect_to :client
|
||||
end
|
||||
|
||||
# let errors fall through to signup_confirm.html.erb
|
||||
end
|
||||
|
||||
def edit
|
||||
|
|
|
|||
|
|
@ -9,4 +9,8 @@ module ApplicationHelper
|
|||
"#{base_title} | #{page_title}"
|
||||
end
|
||||
end
|
||||
|
||||
def self.base_uri(request)
|
||||
(request.ssl? ? "https://" : "http://") + request.host_with_port
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
module SessionsHelper
|
||||
|
||||
def sign_in(user)
|
||||
if (:new was set to true)
|
||||
flash[:success] = "Welcome to Jamkazam!"
|
||||
redirect_to user
|
||||
end
|
||||
cookies.permanent[:remember_token] = user.remember_token
|
||||
self.current_user = user
|
||||
end
|
||||
|
|
@ -32,6 +28,13 @@ module SessionsHelper
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
def api_signed_in_user
|
||||
unless signed_in?
|
||||
render :json => {}, :status => 403
|
||||
end
|
||||
end
|
||||
|
||||
def sign_out
|
||||
current_user = nil
|
||||
cookies.delete(:remember_token)
|
||||
|
|
|
|||
|
|
@ -10,10 +10,6 @@ node :last_name do |follower|
|
|||
follower.user.last_name
|
||||
end
|
||||
|
||||
node :name do |follower|
|
||||
follower.user.name
|
||||
end
|
||||
|
||||
node :city do |follower|
|
||||
follower.user.city
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ attributes :id, :name, :city, :state, :country, :website, :biography, :photo_url
|
|||
|
||||
unless @band.users.nil? || @band.users.size == 0
|
||||
child :users => :musicians do
|
||||
attributes :id, :first_name, :last_name, :name, :photo_url
|
||||
attributes :id, :first_name, :last_name, :photo_url
|
||||
|
||||
# TODO: figure out how to omit empty arrays
|
||||
node :instruments do |user|
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ child(:bands => :bands) {
|
|||
}
|
||||
|
||||
child(:musicians => :musicians) {
|
||||
attributes :id, :first_name, :last_name :location, :photo_url
|
||||
attributes :id, :first_name, :last_name, :location, :photo_url
|
||||
}
|
||||
|
||||
child(:fans => :fans) {
|
||||
|
|
@ -14,4 +14,4 @@ child(:fans => :fans) {
|
|||
|
||||
child(:recordings => :recordings) {
|
||||
attributes :id, :name
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,6 @@ node :last_name do |follower|
|
|||
follower.user.last_name
|
||||
end
|
||||
|
||||
node :name do |follower|
|
||||
follower.user.name
|
||||
end
|
||||
|
||||
node :city do |follower|
|
||||
follower.user.city
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,10 +10,6 @@ node :last_name do |following|
|
|||
following.user.last_name
|
||||
end
|
||||
|
||||
node :name do |follower|
|
||||
follower.user.name
|
||||
end
|
||||
|
||||
node :city do |following|
|
||||
following.user.city
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
object @user.friends
|
||||
|
||||
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :email, :online
|
||||
attributes :id, :first_name, :last_name, :city, :state, :country, :email, :online
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
collection @users
|
||||
|
||||
# do not retrieve all child collections when showing a list of users
|
||||
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :email, :online, :musician, :photo_url
|
||||
attributes :id, :first_name, :last_name, :city, :state, :country, :email, :online, :musician, :photo_url
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
object @user
|
||||
|
||||
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :email, :online, :photo_url, :friend_count, :follower_count, :following_count
|
||||
attributes :id, :first_name, :last_name, :city, :state, :country, :online, :photo_url, :gender, :birth_date, :internet_service_provider, :friend_count, :follower_count, :following_count
|
||||
|
||||
unless @user.friends.nil? || @user.friends.size == 0
|
||||
child :friends => :friends do
|
||||
attributes :id, :first_name, :last_name, :name, :online
|
||||
attributes :id, :first_name, :last_name, :online
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
object @user
|
||||
|
||||
extends "api_users/show"
|
||||
|
|
@ -1,6 +1,32 @@
|
|||
<div class="curtain"></div>
|
||||
<div layout="header" class="header">
|
||||
<h1>JamKazam</h1>
|
||||
<div class="search">
|
||||
<input type="text" class="searchtextinput" placeholder="Search for Bands, Musicians and Fans"/>
|
||||
</div>
|
||||
|
||||
<script type="text/template" id="template-search-section">
|
||||
<h2>{section}</h2>
|
||||
<ul>
|
||||
{items}
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-search-noresults">
|
||||
<h2 class="emptyresult">No Matches</h2>
|
||||
<p>No results returned</p>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-search-item">
|
||||
<li>
|
||||
<a>
|
||||
<img src="{image}"/>
|
||||
<span class="text">{name}</span>
|
||||
<span class="subtext">{subtext}</span>
|
||||
</a>
|
||||
</li>
|
||||
</script>
|
||||
|
||||
<div class="userinfo">
|
||||
<%= gravatar_for current_user, size: 52, hclass: "avatar medium" %>
|
||||
<div class="username">
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
<![endif]-->
|
||||
<%= stylesheet_link_tag "client/ie", media: "all" %>
|
||||
<%= stylesheet_link_tag "client/jamkazam", media: "all" %>
|
||||
<%= stylesheet_link_tag "client/search", media: "all" %>
|
||||
<%= stylesheet_link_tag "client/lato", media: "all" %>
|
||||
<%= include_gon %>
|
||||
<%= javascript_include_tag "application" %>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
<% provide(:title, 'Confirmation Email Sent') %>
|
||||
<h1>Confirm Email Next</h1>
|
||||
|
||||
<div class="row">
|
||||
<div class="span6 offset3">
|
||||
Do it.
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -17,12 +17,23 @@
|
|||
<%= f.label :email %>
|
||||
<%= f.text_field :email %>
|
||||
|
||||
<%= f.label :city %>
|
||||
<%= f.text_field :city %>
|
||||
|
||||
<%= f.label :state %>
|
||||
<%= f.text_field :state %>
|
||||
|
||||
<%= f.label :country %>
|
||||
<%= f.text_field :country %>
|
||||
|
||||
<%= f.label :password %>
|
||||
<%= f.password_field :password %>
|
||||
|
||||
<%= f.label :password_confirmation, "Confirmation" %>
|
||||
<%= f.password_field :password_confirmation %>
|
||||
|
||||
<%= recaptcha_tags %>
|
||||
|
||||
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
<% provide(:title, 'Signup Confirmation') %>
|
||||
<h1>Signup Confirmation Failure</h1>
|
||||
|
||||
<div class="row">
|
||||
<div class="span6 offset3">
|
||||
Unable to confirm registration email
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -26,6 +26,7 @@ module SampleApp
|
|||
|
||||
# Custom directories with classes and modules you want to be autoloadable.
|
||||
# config.autoload_paths += %W(#{config.root}/extras)
|
||||
config.autoload_paths += %W(#{config.root}/lib/managers)
|
||||
|
||||
# Only load the plugins named here, in the order given (default is alphabetical).
|
||||
# :all can be used as a placeholder for all plugins not explicitly named.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
ActionMailer::Base.raise_delivery_errors = true
|
||||
ActionMailer::Base.delivery_method = Rails.env == "test" ? :test : :smtp
|
||||
ActionMailer::Base.smtp_settings = {
|
||||
:address => "smtp.sendgrid.net",
|
||||
:port => 587,
|
||||
:domain => "www.jamkazam.com",
|
||||
:authentication => :plain,
|
||||
:user_name => "jamkazam",
|
||||
:password => "jamjamblueberryjam",
|
||||
:enable_starttls_auto => true
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
Rails.application.config.middleware.use OmniAuth::Builder do
|
||||
provider :facebook, '468555793186398', '546a5b253972f3e2e8b36d9a3dd5a06e'
|
||||
provider :facebook, '468555793186398', '546a5b253972f3e2e8b36d9a3dd5a06e', {:scope => 'email,user_location'}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# this gem turns recaptcha verification off during tests by default.
|
||||
# The public key/private keys shown below valid for all jamkazam.com domains
|
||||
# note that all recaptcha keys work on localhost/127.0.0.1
|
||||
# the keys are created at https://www.google.com/recaptcha/admin/create
|
||||
Recaptcha.configure do |config|
|
||||
# created using seth@jamkazam.com; can't see way to delegate
|
||||
config.public_key = '6Let8dgSAAAAAFheKGWrs6iaq_hIlPOZ2f3Bb56B'
|
||||
config.private_key = '6Let8dgSAAAAAJzFxL9w2QR5auxjk0ol1_xAtOGO'
|
||||
|
||||
# other config options available with this gem:
|
||||
#nonssl_api_server_url,
|
||||
#ssl_api_server_url,
|
||||
#verify_url,
|
||||
#skip_verify_env,
|
||||
#proxy,
|
||||
#handle_timeouts_gracefully
|
||||
end
|
||||
|
|
@ -14,6 +14,7 @@ SampleApp::Application.routes.draw do
|
|||
root to: 'static_pages#home'
|
||||
|
||||
match '/signup', to: 'users#new'
|
||||
match '/email_sent', to: 'users#email_sent'
|
||||
match '/signin', to: 'sessions#new'
|
||||
match '/signout', to: 'sessions#destroy', via: :delete
|
||||
# oauth
|
||||
|
|
@ -26,6 +27,8 @@ SampleApp::Application.routes.draw do
|
|||
|
||||
match '/client', to: 'clients#index'
|
||||
|
||||
match '/confirm/:signup_token', to: 'users#signup_confirm'
|
||||
|
||||
scope '/api' do
|
||||
# music sessions
|
||||
match '/sessions/:id/participants' => 'api_music_sessions#participant_create', :via => :post
|
||||
|
|
@ -42,9 +45,14 @@ SampleApp::Application.routes.draw do
|
|||
# users
|
||||
match '/users' => 'api_users#index', :via => :get
|
||||
match '/users/:id' => 'api_users#show', :via => :get, :as => 'api_user_detail'
|
||||
match '/users' => 'api_users#create', :via => :post
|
||||
#match '/users' => 'api_users#create', :via => :post
|
||||
match '/users/:id' => 'api_users#update', :via => :post
|
||||
match '/users/:id' => 'api_users#destroy', :via => :delete
|
||||
match '/users/confirm/:signup_token' => 'api_users#signup_confirm', :via => :post, :as => 'api_signup_confirmation'
|
||||
|
||||
# login/logout
|
||||
match '/auth_sessions' => 'api_users#auth_session_create', :via => :post
|
||||
match '/auth_sessions' => 'api_users#auth_session_delete', :via => :delete
|
||||
|
||||
# friend requests
|
||||
match '/users/:id/friend_requests' => 'api_users#friend_request_index', :via => :get
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
require 'recaptcha'
|
||||
class UserManager < BaseManager
|
||||
|
||||
include Recaptcha::Verify
|
||||
|
||||
def initialize(options={})
|
||||
super(options)
|
||||
@log = Logging.logger[self]
|
||||
end
|
||||
|
||||
def signup(first_name, last_name, email, password, password_confirmation,
|
||||
city, state, country, instruments, signup_confirm_url)
|
||||
|
||||
@user = User.new
|
||||
|
||||
# TODO: figure out why can't user verify_recaptcha here
|
||||
# ALSO: make sure we dont do the recaptcha stuff if used facebook.
|
||||
|
||||
# check recaptcha; if any errors seen, contribute it to the model
|
||||
#unless verify_recaptcha(:model => @user, :message => "recaptcha")
|
||||
# return @user # @user.errors.any? is true now
|
||||
#else
|
||||
# sends email to email account for confirmation
|
||||
@user = User.signup(first_name, last_name, email, password, password_confirmation,
|
||||
city, state, country, instruments, signup_confirm_url)
|
||||
|
||||
return @user
|
||||
#end
|
||||
end
|
||||
|
||||
def signup_confirm(signup_token)
|
||||
begin
|
||||
@user = User.signup_confirm(signup_token)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
@user = nil
|
||||
end
|
||||
|
||||
return @user
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -4,6 +4,7 @@ FactoryGirl.define do
|
|||
sequence(:email) { |n| "person_#{n}@example.com"}
|
||||
password "foobar"
|
||||
password_confirmation "foobar"
|
||||
email_confirmed true
|
||||
|
||||
factory :admin do
|
||||
admin true
|
||||
|
|
@ -26,4 +27,8 @@ FactoryGirl.define do
|
|||
factory :invitation, :class => JamRuby::Invitation do
|
||||
|
||||
end
|
||||
|
||||
factory :band, :class => JamRuby::Band do
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
<!-- Fixtures for Jasmine Tests for searcher.js -->
|
||||
<input type="text" class="searchtextinput" placeholder="Search for Magical Things" />
|
||||
|
||||
<script type="text/template" id="template-search-section">
|
||||
<h2>{section}</h2>
|
||||
<ul>
|
||||
{items}
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-search-noresults">
|
||||
<h2 class="emptyresult">No Matches</h2>
|
||||
<p>No results returned</p>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-search-item">
|
||||
<li>
|
||||
<a>
|
||||
<img src="{image}"/>
|
||||
<span class="text">{name}</span>
|
||||
<span class="subtext">{subtext}</span>
|
||||
</a>
|
||||
</li>
|
||||
</script>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
window.TestResponses = {
|
||||
search : {
|
||||
bands: [ ],
|
||||
musicians: [ ],
|
||||
fans: [
|
||||
{
|
||||
id: "1",
|
||||
first_name: "Test",
|
||||
last_name: "User",
|
||||
location: "Austin, TX",
|
||||
photo_url: "http://www.jamkazam.com/images/users/photos/1.gif"
|
||||
}
|
||||
],
|
||||
recordings: [ ]
|
||||
},
|
||||
|
||||
emptySearch: {
|
||||
bands: [],
|
||||
musicians: [],
|
||||
fans: [],
|
||||
recordings: []
|
||||
},
|
||||
|
||||
fullSearch: {
|
||||
bands: [
|
||||
{
|
||||
id: "1",
|
||||
first_name: "Test",
|
||||
last_name: "User",
|
||||
location: "Austin, TX",
|
||||
photo_url: "http://www.jamkazam.com/images/users/photos/1.gif"
|
||||
}
|
||||
],
|
||||
musicians: [
|
||||
{
|
||||
id: "1",
|
||||
first_name: "Test",
|
||||
last_name: "User",
|
||||
location: "Austin, TX",
|
||||
photo_url: "http://www.jamkazam.com/images/users/photos/1.gif"
|
||||
}
|
||||
],
|
||||
fans: [
|
||||
{
|
||||
id: "1",
|
||||
first_name: "Test",
|
||||
last_name: "User",
|
||||
location: "Austin, TX",
|
||||
photo_url: "http://www.jamkazam.com/images/users/photos/1.gif"
|
||||
}
|
||||
],
|
||||
recordings: [
|
||||
{
|
||||
id: "1",
|
||||
first_name: "Test",
|
||||
last_name: "User",
|
||||
location: "Austin, TX",
|
||||
photo_url: "http://www.jamkazam.com/images/users/photos/1.gif"
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
(function(context) {
|
||||
|
||||
describe("searcher.js tests", function() {
|
||||
|
||||
describe("Empty Search", function() {
|
||||
|
||||
// See the markup in fixtures/searcher.htm
|
||||
|
||||
var searcher;
|
||||
var ajaxSpy;
|
||||
|
||||
var fakeApp = {
|
||||
ajaxError: function() {
|
||||
console.debug("ajaxError");
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
loadFixtures('searcher.htm');
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success(TestResponses.emptySearch);
|
||||
});
|
||||
searcher = new JK.Searcher(fakeApp);
|
||||
searcher.initialize();
|
||||
});
|
||||
|
||||
it("No Results message shown", function() {
|
||||
// Workaround for key events not being reflected in val() calls
|
||||
$('.searchtextinput').val('AA');
|
||||
var e = jQuery.Event("keyup");
|
||||
e.which = 65; // "a"
|
||||
$('.searchtextinput').focus();
|
||||
$('.searchtextinput').trigger(e);
|
||||
$('.searchtextinput').trigger(e);
|
||||
|
||||
expect($('.searchresults .emptyresult').length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Full Search", function() {
|
||||
|
||||
// See the markup in fixtures/searcher.htm
|
||||
|
||||
var searcher;
|
||||
var ajaxSpy;
|
||||
|
||||
var fakeApp = {
|
||||
ajaxError: function() {
|
||||
console.debug("ajaxError");
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
loadFixtures('searcher.htm');
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success(TestResponses.fullSearch);
|
||||
});
|
||||
searcher = new JK.Searcher(fakeApp);
|
||||
searcher.initialize();
|
||||
});
|
||||
|
||||
it("No Results message shown", function() {
|
||||
// Workaround for key events not being reflected in val() calls
|
||||
$('.searchtextinput').val('AA');
|
||||
var e = jQuery.Event("keyup");
|
||||
e.which = 65; // "a"
|
||||
$('.searchtextinput').focus();
|
||||
$('.searchtextinput').trigger(e);
|
||||
$('.searchtextinput').trigger(e);
|
||||
|
||||
expect($('.searchresults h2').length).toEqual(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Search Tests", function() {
|
||||
|
||||
// See the markup in fixtures/searcher.htm
|
||||
|
||||
var searcher;
|
||||
var ajaxSpy;
|
||||
|
||||
var fakeApp = {
|
||||
ajaxError: function() {
|
||||
console.debug("ajaxError");
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
loadFixtures('searcher.htm');
|
||||
spyOn($, "ajax").andCallFake(function(opts) {
|
||||
opts.success(TestResponses.search);
|
||||
});
|
||||
searcher = new JK.Searcher(fakeApp);
|
||||
searcher.initialize();
|
||||
});
|
||||
|
||||
it("first keypress should not search", function() {
|
||||
// Workaround for key events not being reflected in val() calls
|
||||
$('.searchtextinput').val('A');
|
||||
var e = jQuery.Event("keyup");
|
||||
e.which = 65; // "a"
|
||||
$('.searchtextinput').focus();
|
||||
$('.searchtextinput').trigger(e);
|
||||
expect($.ajax.wasCalled).toBe(false);
|
||||
});
|
||||
|
||||
it("second keypress should search", function() {
|
||||
$('.searchtextinput').val('AA');
|
||||
$('.searchtextinput').focus();
|
||||
var e = jQuery.Event("keyup");
|
||||
e.which = 65; // "a"
|
||||
$('.searchtextinput').trigger(e);
|
||||
// trigger again
|
||||
$('.searchtextinput').trigger(e);
|
||||
|
||||
expect($.ajax).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("response div is absolute position", function() {
|
||||
$('.searchtextinput').val('AA');
|
||||
$('.searchtextinput').focus();
|
||||
var e = jQuery.Event("keyup");
|
||||
e.which = 65; // "a"
|
||||
$('.searchtextinput').trigger(e);
|
||||
$('.searchtextinput').trigger(e);
|
||||
expect($('.searchresults').css('position')).toEqual('absolute');
|
||||
});
|
||||
|
||||
it("response displayed in results", function() {
|
||||
$('.searchtextinput').val('AA');
|
||||
$('.searchtextinput').focus();
|
||||
var e = jQuery.Event("keyup");
|
||||
e.which = 65; // "a"
|
||||
$('.searchtextinput').trigger(e);
|
||||
$('.searchtextinput').trigger(e);
|
||||
|
||||
expect($('.searchresults').length).toEqual(1);
|
||||
expect($('.searchresults h2').length).toEqual(1);
|
||||
expect($('.searchresults li').length).toEqual(1);
|
||||
expect($('.searchresults li img').length).toEqual(1);
|
||||
expect($('.searchresults li span.text').length).toEqual(1);
|
||||
expect($('.searchresults li span.subtext').length).toEqual(1);
|
||||
});
|
||||
|
||||
|
||||
it("response positioned under input", function() {
|
||||
$('.searchtextinput').val('AA');
|
||||
$('.searchtextinput').focus();
|
||||
var e = jQuery.Event("keyup");
|
||||
e.which = 65; // "a"
|
||||
$('.searchtextinput').trigger(e);
|
||||
$('.searchtextinput').trigger(e);
|
||||
|
||||
expect($('.searchresults').length).toEqual(1);
|
||||
var bodyOffset = $('body').offset();
|
||||
var inputOffset = $('.searchtextinput').offset();
|
||||
var inputHeight = $('.searchtextinput').outerHeight();
|
||||
var expectedTop = bodyOffset.top + inputOffset.top + inputHeight;
|
||||
var expectedLeft = bodyOffset.left + inputOffset.left;
|
||||
|
||||
var searchResultOffset = $('.searchresults').offset();
|
||||
expect(searchResultOffset.top).toEqual(expectedTop);
|
||||
expect(searchResultOffset.left).toEqual(expectedLeft);
|
||||
});
|
||||
|
||||
it("search results are visible", function() {
|
||||
$('.searchtextinput').val('AA');
|
||||
$('.searchtextinput').focus();
|
||||
var e = jQuery.Event("keyup");
|
||||
e.which = 65; // "a"
|
||||
$('.searchtextinput').trigger(e);
|
||||
$('.searchtextinput').trigger(e);
|
||||
|
||||
var visible = $('.searchresults').is(':visible');
|
||||
expect(visible).toBe(true);
|
||||
});
|
||||
|
||||
it("escape key hides search results", function() {
|
||||
$('.searchtextinput').val('AA');
|
||||
$('.searchtextinput').focus();
|
||||
var e = jQuery.Event("keyup");
|
||||
e.which = 65; // "a"
|
||||
$('.searchtextinput').trigger(e);
|
||||
$('.searchtextinput').trigger(e);
|
||||
|
||||
e = jQuery.Event("keyup");
|
||||
e.which = 27; // ESCAPE
|
||||
$('.searchtextinput').trigger(e);
|
||||
|
||||
var visible = $('.searchresults').is(':visible');
|
||||
expect(visible).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
})(window);
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
require 'spec_helper'
|
||||
|
||||
# these tests avoid the use of ActiveRecord and FactoryGirl to do blackbox, non test-instrumented tests
|
||||
describe UserManager do
|
||||
|
||||
|
||||
before(:each) do
|
||||
@user_manager = UserManager.new(:conn => @conn)
|
||||
UserMailer.deliveries.clear
|
||||
end
|
||||
|
||||
describe "signup" do
|
||||
it "signup successfully" do
|
||||
@user = @user_manager.signup("bob", "smith", "bob@jamkazam.com", "foobar", "foobar", "Austin", "TX", "USA", nil, "http://localhost:3000/confirm" )
|
||||
|
||||
@user.errors.any?.should be_false
|
||||
@user.first_name.should == "bob"
|
||||
@user.last_name.should == "smith"
|
||||
@user.email.should == "bob@jamkazam.com"
|
||||
@user.email_confirmed.should be_false
|
||||
@user.city.should == "Austin"
|
||||
@user.state.should == "TX"
|
||||
@user.country.should == "USA"
|
||||
@user.instruments.length.should == 0
|
||||
@user.signup_token.should_not be_nil
|
||||
|
||||
UserMailer.deliveries.length.should == 1
|
||||
end
|
||||
|
||||
it "signup successfully with instruments" do
|
||||
@user = @user_manager.signup("bob", "smith", "bob@jamkazam.com", "foobar", "foobar", "Austin", "TX", "USA",
|
||||
[{ :instrument_id => "electric guitar", :proficiency_level => 3, :priority => 0}], "http://localhost:3000/confirm" )
|
||||
|
||||
@user.errors.any?.should be_false
|
||||
@user.instruments.length.should == 1
|
||||
musician_instrument = @user.musician_instruments[0]
|
||||
musician_instrument.instrument.should == Instrument.find("electric guitar")
|
||||
musician_instrument.proficiency_level.should == 3
|
||||
end
|
||||
|
||||
it "duplicate signup failure" do
|
||||
@user = @user_manager.signup("bob", "smith", "bob@jamkazam.com", "foobar", "foobar", "Austin", "TX", "USA", nil, "http://localhost:3000/confirm" )
|
||||
UserMailer.deliveries.length.should == 1
|
||||
@user.errors.any?.should be_false
|
||||
|
||||
# exactly the same parameters; should dup on email, and send no email
|
||||
@user = @user_manager.signup("bob", "smith", "bob@jamkazam.com", "foobar", "foobar", "Austin", "TX", "USA", nil, "http://localhost:3000/confirm" )
|
||||
UserMailer.deliveries.length.should == 1
|
||||
@user.errors.any?.should be_true
|
||||
@user.errors[:email][0].should == "has already been taken"
|
||||
|
||||
# change email so that name appears dupped
|
||||
@user = @user_manager.signup("bob", "smith", "bobbie@jamkazam.com", "foobar", "foobar", "Austin", "TX", "USA", nil, "http://localhost:3000/confirm" )
|
||||
UserMailer.deliveries.length.should == 1
|
||||
@user.errors.any?.should be_true
|
||||
@user.errors[:name][0].should == "has already been taken"
|
||||
end
|
||||
|
||||
it "fail on no username" do
|
||||
@user = @user_manager.signup("", "", "bob@jamkazam.com", "foobar", "foobar", "Austin", "TX", "USA", nil, "http://localhost:3000/confirm" )
|
||||
UserMailer.deliveries.length.should == 0
|
||||
@user.errors.any?.should be_true
|
||||
@user.errors[:first_name][0].should == "can't be blank"
|
||||
end
|
||||
|
||||
it "fail on no username" do
|
||||
@user = @user_manager.signup("murp", "", "foobar", "foobar", "Austin", "TX", "USA", nil, "http://localhost:3000/confirm" )
|
||||
UserMailer.deliveries.length.should == 0
|
||||
@user.errors.any?.should be_true
|
||||
@user.errors[:email][0].should == "can't be blank"
|
||||
end
|
||||
end
|
||||
|
||||
describe "signup_confirm" do
|
||||
it "fail on no username" do
|
||||
@user = @user_manager.signup("bob", "smith", "bob@jamkazam.com", "foobar", "foobar", "Austin", "TX", "USA", nil, "http://localhost:3000/confirm" )
|
||||
@user = @user_manager.signup_confirm(@user.signup_token)
|
||||
@user.email_confirmed.should be_true
|
||||
end
|
||||
|
||||
it "fail to confirm bogus signup token" do
|
||||
@user_manager.signup_confirm("murp").should be_nil
|
||||
end
|
||||
|
||||
it "fail to confirm empty signup token" do
|
||||
@user_manager.signup_confirm("").should be_nil
|
||||
end
|
||||
|
||||
it "fail to confirm nil signup token" do
|
||||
@user_manager.signup_confirm(nil).should be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -28,10 +28,8 @@ describe "Search API ", :type => :api do
|
|||
it "simple search" do
|
||||
User.delete_search_index # so that the user created before the test and logged in doesn't show up
|
||||
User.create_search_index
|
||||
@musician = User.save(name: "Peach", email: "user@example.com",
|
||||
password: "foobar", password_confirmation: "foobar", musician: true)
|
||||
@fan = User.save(name: "Peach Peach", email: "fan@example.com",
|
||||
password: "foobar", password_confirmation: "foobar", musician: false)
|
||||
@musician = FactoryGirl.create(:user, first_name: "Peach", last_name: "Nothing", name: "peach1", email: "user@example.com", musician: true)
|
||||
@fan = FactoryGirl.create(:user, first_name: "Peach Peach", last_name: "Grovery", name: "peach2", email: "fan@example.com", musician: false)
|
||||
@band = Band.save(name: "Peach pit", website: "www.bands.com", biography: "zomg we rock")
|
||||
@band2 = Band.save(name: "Peach", website: "www.bands2.com", biography: "zomg we rock")
|
||||
User.search_index.refresh
|
||||
|
|
|
|||
|
|
@ -114,6 +114,9 @@ describe "User pages" do
|
|||
before do
|
||||
fill_in "Name", with: "Example User"
|
||||
fill_in "Email", with: "user@example.com"
|
||||
fill_in "City", with: "Austin"
|
||||
fill_in "State", with: "TX"
|
||||
fill_in "Country", with: "USA"
|
||||
fill_in "Password", with: "foobar"
|
||||
fill_in "Confirmation", with: "foobar"
|
||||
end
|
||||
|
|
@ -127,9 +130,8 @@ describe "User pages" do
|
|||
|
||||
let(:user) { User.find_by_email('user@example.com') }
|
||||
|
||||
it { should have_selector('title', text: user.name) }
|
||||
it { should have_selector('div.alert.alert-success', text: 'Welcome') }
|
||||
it { should have_link('Sign out') }
|
||||
it { should have_selector('title', text: "Confirmation Email Sent") }
|
||||
it { should have_selector('div.alert.alert-success', text: 'check your email') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "User API ", :type => :api do
|
||||
|
||||
include Rack::Test::Methods
|
||||
|
||||
subject { page }
|
||||
|
||||
describe "profile page" do
|
||||
let(:user) { FactoryGirl.create(:user) }
|
||||
|
||||
before(:each) do
|
||||
UserMailer.deliveries.clear
|
||||
end
|
||||
|
||||
|
||||
it "successful login" do
|
||||
# can't access most apis; not logged in yet!'
|
||||
get '/api/users.json', "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should == 403
|
||||
|
||||
# login
|
||||
post '/api/auth_sessions.json', { :email => user.email, :password => user.password }.to_json, "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should == 200
|
||||
JSON.parse(last_response.body).should == { "success" => true }
|
||||
|
||||
# can now login
|
||||
get '/api/users.json', "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should == 200
|
||||
|
||||
# log back out
|
||||
delete '/api/auth_sessions.json', "CONTENT_TYPE" => 'application/json'
|
||||
|
||||
# can't access most apis; not logged in yet!'
|
||||
get '/api/users.json', "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should == 403
|
||||
end
|
||||
|
||||
it "bad login" do
|
||||
# login
|
||||
post '/api/auth_sessions.json', { :email => "nothing", :password => "mur" }.to_json, "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should == 404
|
||||
JSON.parse(last_response.body).should == { "success" => false }
|
||||
|
||||
# can't access most apis; not logged in yet!'
|
||||
get '/api/users.json', "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should == 403
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -4,11 +4,15 @@ require 'spork'
|
|||
#require 'spork/ext/ruby-debug'
|
||||
|
||||
require 'active_record'
|
||||
require 'action_mailer'
|
||||
require 'jam_db'
|
||||
require 'spec_db'
|
||||
|
||||
include JamRuby
|
||||
|
||||
# put ActionMailer into test mode
|
||||
ActionMailer::Base.delivery_method = :test
|
||||
|
||||
# recreate test database and migrate it
|
||||
db_config = YAML::load(File.open('config/database.yml'))["test"]
|
||||
SpecDb::recreate_database(db_config)
|
||||
|
|
|
|||
Loading…
Reference in New Issue