Skip to content

Commit

Permalink
Merge pull request #1 from emedvedev/oauth
Browse files Browse the repository at this point in the history
Replace the `chatops_id` string with `nicknames` dict
  • Loading branch information
tonybaloney authored Sep 26, 2016
2 parents 9c90b80 + 7c7f386 commit 0a9d45a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 9 deletions.
18 changes: 16 additions & 2 deletions st2auth/st2auth/controllers/v1/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

from st2common.exceptions.auth import TokenNotFoundError, TokenExpiredError
from st2common.exceptions.auth import TTLTooLargeException, UserNotFoundError
from st2common.exceptions.auth import NoNicknameOriginProvidedError, AmbiguousUserError
from st2common.models.api.base import jsexpose
from st2common.models.api.auth import TokenAPI
from st2common.persistence.auth import User
Expand Down Expand Up @@ -131,15 +132,28 @@ def _handle_standalone_auth(self, request, **kwargs):
username = impersonate_user
else:
impersonate_user = getattr(request, 'impersonate_user', None)
nickname_origin = getattr(request, 'nickname_origin', None)
if impersonate_user is not None:
try:
username = User.get_by_chatops_id(impersonate_user).username
username = User.get_by_nickname(impersonate_user, nickname_origin).username
except UserNotFoundError:
message = "Could not locate user with chatops_id '%s'" % \
message = "Could not locate user %s@%s" % \
(impersonate_user, nickname_origin)
self._abort_request(status_code=http_client.BAD_REQUEST,
message=message)
return
except NoNicknameOriginProvidedError:
message = "Nickname origin is not provided for nickname '%s'" % \
impersonate_user
self._abort_request(status_code=http_client.BAD_REQUEST,
message=message)
return
except AmbiguousUserError:
message = "%s@%s matched more than one username" % \
(impersonate_user, nickname_origin)
self._abort_request(status_code=http_client.BAD_REQUEST,
message=message)
return
try:
token = self._create_token_for_user(username=username, ttl=ttl)
return self._process_successful_response(token=token)
Expand Down
12 changes: 11 additions & 1 deletion st2common/st2common/exceptions/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
'ApiKeyNotFoundError',
'MultipleAuthSourcesError',
'NoAuthSourceProvidedError',
'UserNotFoundError'
'NoNicknameOriginProvidedError',
'UserNotFoundError',
'AmbiguousUserError',
]


Expand Down Expand Up @@ -65,5 +67,13 @@ class NoAuthSourceProvidedError(StackStormBaseException):
pass


class NoNicknameOriginProvidedError(StackStormBaseException):
pass


class UserNotFoundError(StackStormBaseException):
pass


class AmbiguousUserError(StackStormBaseException):
pass
3 changes: 2 additions & 1 deletion st2common/st2common/models/db/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
class UserDB(stormbase.StormFoundationDB):
name = me.StringField(required=True, unique=True)
is_service = me.BooleanField(required=True, default=False)
chatops_id = me.StringField(required=False, unique=True)
nicknames = me.DictField(required=False,
help_text='"Nickname + origin" pairs for ChatOps auth')

def get_roles(self):
"""
Expand Down
16 changes: 11 additions & 5 deletions st2common/st2common/persistence/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
# limitations under the License.

from st2common.exceptions.auth import (TokenNotFoundError, ApiKeyNotFoundError,
UserNotFoundError)
UserNotFoundError, AmbiguousUserError,
NoNicknameOriginProvidedError)
from st2common.models.db import MongoDBAccess
from st2common.models.db.auth import UserDB, TokenDB, ApiKeyDB
from st2common.persistence.base import Access
Expand All @@ -29,13 +30,18 @@ def get(cls, username):
return cls.get_by_name(username)

@classmethod
def get_by_chatops_id(cls, value):
result = cls.query(chatops_id=value).first()
def get_by_nickname(cls, nickname, origin):
if not origin:
raise NoNicknameOriginProvidedError()

if not result:
result = cls.query(**{('nickname__%s' % origin): nickname})

if not result.first():
raise UserNotFoundError()
if result.count() > 1:
raise AmbiguousUserError()

return result
return result.first()

@classmethod
def _get_impl(cls):
Expand Down

0 comments on commit 0a9d45a

Please sign in to comment.