Skip to content

Instantly share code, notes, and snippets.

@max-power
Last active August 29, 2015 13:57
Show Gist options
  • Save max-power/9384148 to your computer and use it in GitHub Desktop.
Save max-power/9384148 to your computer and use it in GitHub Desktop.
Doorkeeper + Guestlist
Gem::Specification.new do |s|
s.name = 'disco'
s.version = '0.0.1'
s.platform = Gem::Platform::RUBY
s.author = 'Kevin Melchert'
s.email = '[email protected]'
s.summary = 'MongoDB + Omniauth = Guestlist + Doorkeeper.'
s.description = 'MongoDB + Omniauth = Guestlist + Doorkeeper.'
s.files = ['disco.rb']
s.require_path = '.'
end
# 1. A user has never used your site before. They have no User model and no Identities either.
# 2. A user is logged out but they have logged into your site with a provider previously.
# They are now signing in with the same one again.
# 3. Just as above but they are now signing in with a different provider.
# 4. A user is logged in with a provider but they try to login with the same provider again.
# 5. A user is logged in but they try to login with a different provider.
module Disco
class Doorkeeper
def initialize(guestlist, omniauth, known_id=nil)
@guestlist = guestlist
@omniauth = omniauth
@known_id = known_id
end
def grant_access?
!!user
end
def user
@user ||= @guestlist.register(@known_id, token, info)
end
def token
{ p: @omniauth["provider"], u: @omniauth["uid"] }
end
def info
@omniauth["info"]
end
end
class Guestlist
def initialize(collection, field: 'auth')
@list, @field = collection, field
@list.ensure_index(@field => 1)
end
def find(user_id)
@list.find_one(_id: user_id) if user_id
end
# returns a user record
def register(*args)
@list.find_and_modify(Query.build(@field, *args).to_mongo)
end
end
class Query
def self.build(field, user_id, token, info={})
(user_id ? KnownUserQuery : UnknownUserQuery).new(field, user_id, token, info)
end
def initialize(field, user_id, token, info={})
@field, @token, @user_id, @info = field, token, user_id, info
end
def to_mongo
{ query: selector, update: params, new: true }
end
end
# on create it will set tokens array with the supplied token
# on update it will set the last login timestamp
class UnknownUserQuery < Query
def selector
{ @field => @token }
end
def params
{
"$setOnInsert" => { @field => [@token] }.merge(@info),
"$set" => { last_login: Time.now.utc }
}
end
def to_mongo
super.merge(upsert: true)
end
end
# just adds the token to an existing record of a logged in user
class KnownUserQuery < Query
def selector
{ _id: @user_id }
end
def params
{ "$addToSet" => { @field => @token } }
end
end
end
#user_collection = Mongo::Collection...
guestlist = Guestlist.new(user_collection)
doorkeeper = Doorkeeper.new(guestlist, request.params["omniauth.auth"], session[:user_id])
if doorkeeper.grant_access?
session[:user_id] = doorkeeper.user["_id"]
redirect_to "/"
else
redirect_to "/login"
end
def current_user
guestlist.find(session[:user_id])
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment