def register_internal(username, fullname, password): user = User(username=username, fullname=fullname, password=password) if not username: user.username = None db.session.add(user) user_registered.send(user) return user
def register_internal(username, fullname, password): user = User(username=username, fullname=fullname, password=password) if not username: user.username = None if user.username: # We can only use failsafe_add when a unique identifier like username is present user = failsafe_add(db.session, user, username=user.username) else: db.session.add(user) user_registered.send(user) return user
def lookup_current_user(): """ If there's a userid in the session, retrieve the user object and add to the request namespace object g. """ g.user = None g.usersession = None if 'sessionid' in session: usersession = UserSession.authenticate(buid=session['sessionid']) g.usersession = usersession if usersession: usersession.access() db.session.commit() # Save access g.user = usersession.user else: session.pop('sessionid', None) # Transition users with 'userid' to 'sessionid' if 'userid' in session: if not g.usersession: user = User.get(userid=session['userid']) if user: usersession = UserSession(user=user) usersession.access() db.session.commit() # Save access g.usersession = usersession g.user = user session['sessionid'] = usersession.buid session.pop('userid', None) # This will be set to True downstream by the requires_login decorator g.login_required = False
def user_get_by_userid(): """ Returns user or organization with the given userid (Lastuser internal userid) """ userid = request.values.get('userid') if not userid: return api_result('error', error='no_userid_provided') user = User.get(userid=userid, defercols=True) if user: return api_result('ok', type='user', userid=user.userid, buid=user.userid, name=user.username, title=user.fullname, label=user.pickername, timezone=user.timezone, oldids=[o.userid for o in user.oldids]) else: org = Organization.get(userid=userid, defercols=True) if org: return api_result('ok', type='organization', userid=org.userid, buid=org.userid, name=org.name, title=org.title, label=org.pickername) return api_result('error', error='not_found')
def permission_user_delete(client, kwargs): if client.user: user = User.get(buid=kwargs['buid']) if not user: abort(404) permassign = UserClientPermissions.query.filter_by( user=user, client=client).first_or_404() return render_delete_sqla( permassign, db, title=_(u"Confirm delete"), message= _(u"Remove all permissions assigned to user {pname} for app ‘{title}’?" ).format(pname=user.pickername, title=client.title), success=_(u"You have revoked permisions for user {pname}").format( pname=user.pickername), next=url_for('.client_info', key=client.key)) else: team = Team.get(buid=kwargs['buid']) if not team: abort(404) permassign = TeamClientPermissions.query.filter_by( team=team, client=client).first_or_404() return render_delete_sqla( permassign, db, title=_(u"Confirm delete"), message= _(u"Remove all permissions assigned to team ‘{pname}’ for app ‘{title}’?" ).format(pname=team.title, title=client.title), success=_(u"You have revoked permisions for team {title}").format( title=team.title), next=url_for('.client_info', key=client.key))
def user_get_by_userids(userid): """ Returns users and organizations with the given userids (Lastuser internal userid). This is identical to get_by_userid but accepts multiple userids and returns a list of matching users and organizations """ if not userid: return api_result('error', error='no_userid_provided') users = User.all(userids=userid) orgs = Organization.all(userids=userid) return api_result('ok', results=[ {'type': 'user', 'buid': u.userid, 'userid': u.userid, 'name': u.username, 'title': u.fullname, 'label': u.pickername, 'timezone': u.timezone, 'oldids': [o.userid for o in u.oldids]} for u in users] + [ {'type': 'organization', 'buid': o.userid, 'userid': o.userid, 'name': o.name, 'title': o.fullname, 'label': o.pickername} for o in orgs] )
def user_get_by_userids(userid): """ Returns users and organizations with the given userids (Lastuser internal userid). This is identical to get_by_userid but accepts multiple userids and returns a list of matching users and organizations """ if not userid: return api_result('error', error='no_userid_provided', _jsonp=True) users = User.all(buids=userid) orgs = Organization.all(buids=userid) return api_result( 'ok', _jsonp=True, results=[{ 'type': 'user', 'buid': u.buid, 'userid': u.buid, 'uuid': u.uuid, 'name': u.username, 'title': u.fullname, 'label': u.pickername, 'timezone': u.timezone, 'oldids': [o.buid for o in u.oldids], 'olduuids': [o.uuid for o in u.oldids], } for u in users] + [{ 'type': 'organization', 'buid': o.buid, 'userid': o.buid, 'uuid': o.uuid, 'name': o.name, 'title': o.fullname, 'label': o.pickername, } for o in orgs], )
def account_merge(): if 'merge_buid' not in session: return redirect(get_next_url(), code=302) other_user = User.get(buid=session['merge_buid']) if other_user is None: session.pop('merge_buid', None) return redirect(get_next_url(), code=302) form = ProfileMergeForm() if form.validate_on_submit(): if 'merge' in request.form: new_user = merge_users(current_auth.user, other_user) login_internal(new_user) flash(_("Your accounts have been merged"), 'success') session.pop('merge_buid', None) db.session.commit() user_data_changed.send(new_user, changes=['merge']) return redirect(get_next_url(), code=303) else: session.pop('merge_buid', None) return redirect(get_next_url(), code=303) return render_template( 'merge.html.jinja2', form=form, user=current_auth.user, other_user=other_user, login_registry=login_registry, )
def permission_user_edit(client, kwargs): if client.user: user = User.get(userid=kwargs['userid']) if not user: abort(404) available_perms = Permission.query.filter( db.or_(Permission.allusers == True, Permission.user == g.user)).order_by('name').all() permassign = UserClientPermissions.query.filter_by( user=user, client=client).first_or_404() elif client.org: team = Team.get(userid=kwargs['userid']) if not team: abort(404) available_perms = Permission.query.filter( db.or_(Permission.allusers == True, Permission.org == client.org)).order_by('name').all() permassign = TeamClientPermissions.query.filter_by( team=team, client=client).first_or_404() form = PermissionEditForm() form.perms.choices = [(ap.name, u"{name} – {title}".format(name=ap.name, title=ap.title)) for ap in available_perms] if request.method == 'GET': if permassign: form.perms.data = permassign.access_permissions.split(u' ') if form.validate_on_submit(): form.perms.data.sort() perms = u' '.join(form.perms.data) if not perms: db.session.delete(permassign) else: permassign.access_permissions = perms db.session.commit() if perms: if client.user: flash( u"Permissions have been updated for user {pname}".format( pname=user.pickername), 'success') else: flash( u"Permissions have been updated for team {title}".format( title=team.title), 'success') else: if client.user: flash( u"All permissions have been revoked for user {pname}". format(pname=user.pickername), 'success') else: flash( u"All permissions have been revoked for team {title}". format(title=team.title), 'success') return render_redirect(url_for('.client_info', key=client.key), code=303) return render_form(form=form, title="Edit permissions", formid="perm_edit", submit="Save changes", ajax=True)
def lookup_current_user(): """ If there's a userid in the session, retrieve the user object and add to the request namespace object g. """ g.user = None if 'userid' in session: g.user = User.get(userid=session['userid'])
def validate_username(self, field): if field.data in current_app.config['RESERVED_USERNAMES']: raise wtforms.ValidationError, "This name is reserved" if not valid_username(field.data): raise wtforms.ValidationError(u"Invalid characters in name. Names must be made of ‘a-z’, ‘0-9’ and ‘-’, without trailing dashes") existing = User.get(username=field.data) if existing is not None: raise wtforms.ValidationError("This username is taken")
def validate_username(self, field): if field.data in current_app.config['RESERVED_USERNAMES']: raise wtforms.ValidationError, "That name is reserved" if not valid_username(field.data): raise wtforms.ValidationError(u"Invalid characters in name. Names must be made of ‘a-z’, ‘0-9’ and ‘-’, without trailing dashes") existing = User.get(username=field.data) if existing is not None: raise wtforms.ValidationError("That username is taken")
def lookup_current_user(): """ If there's a userid in the session, retrieve the user object and add to the request namespace object g. """ g.user = None if "userid" in session: g.user = User.get(userid=session["userid"])
def _load_user(self): """ If there's a buid in the session, retrieve the user object and add to the request namespace object g. """ add_auth_attribute('user', None) add_auth_attribute('session', None) lastuser_cookie = {} lastuser_cookie_headers = { } # Ignored for now, intended for future changes # Migrate data from Flask cookie session if 'sessionid' in session: lastuser_cookie['sessionid'] = session.pop('sessionid') if 'userid' in session: lastuser_cookie['userid'] = session.pop('userid') if 'lastuser' in request.cookies: try: lastuser_cookie, lastuser_cookie_headers = lastuser_oauth.serializer.loads( request.cookies['lastuser'], return_header=True) except itsdangerous.BadSignature: lastuser_cookie = {} if 'sessionid' in lastuser_cookie: add_auth_attribute( 'session', UserSession.authenticate(buid=lastuser_cookie['sessionid'])) if current_auth.session: current_auth.session.access() db.session.commit() # Save access add_auth_attribute('user', current_auth.session.user) # Transition users with 'userid' to 'sessionid' if not current_auth.session and 'userid' in lastuser_cookie: add_auth_attribute('user', User.get(buid=lastuser_cookie['userid'])) if current_auth.is_authenticated: add_auth_attribute('session', UserSession(user=current_auth.user)) current_auth.session.access() db.session.commit() # Save access if current_auth.session: lastuser_cookie['sessionid'] = current_auth.session.buid else: lastuser_cookie.pop('sessionid', None) if current_auth.is_authenticated: lastuser_cookie['userid'] = current_auth.user.buid else: lastuser_cookie.pop('userid', None) lastuser_cookie['updated_at'] = utcnow().isoformat() add_auth_attribute('cookie', lastuser_cookie) # This will be set to True downstream by the requires_login decorator add_auth_attribute('login_required', False)
def validate_name(self, field): if not valid_username(field.data): raise wtforms.ValidationError("Invalid characters in name") if field.data in current_app.config['RESERVED_USERNAMES']: raise wtforms.ValidationError("That name is reserved") existing = User.get(username=field.data) if existing is not None: raise wtforms.ValidationError("That name is taken") existing = Organization.get(name=field.data) if existing is not None and existing.id != self.edit_id: raise wtforms.ValidationError("That name is taken")
def lookup_current_user(): """ If there's a buid in the session, retrieve the user object and add to the request namespace object g. """ g.user = None g.usersession = None lastuser_cookie = {} lastuser_cookie_headers = { } # Ignored for now, intended for future changes # Migrate data from Flask cookie session if 'sessionid' in session: lastuser_cookie['sessionid'] = session.pop('sessionid') if 'userid' in session: lastuser_cookie['userid'] = session.pop('userid') if 'lastuser' in request.cookies: try: lastuser_cookie, lastuser_cookie_headers = lastuser_oauth.serializer.loads( request.cookies['lastuser'], return_header=True) except itsdangerous.BadSignature: lastuser_cookie = {} if 'sessionid' in lastuser_cookie: g.usersession = UserSession.authenticate( buid=lastuser_cookie['sessionid']) if g.usersession: g.usersession.access() db.session.commit() # Save access g.user = g.usersession.user # Transition users with 'userid' to 'sessionid' if not g.usersession and 'userid' in lastuser_cookie: g.user = User.get(buid=lastuser_cookie['userid']) if g.user: g.usersession = UserSession(user=g.user) g.usersession.access() db.session.commit() # Save access if g.usersession: lastuser_cookie['sessionid'] = g.usersession.buid else: lastuser_cookie.pop('sessionid', None) if g.user: lastuser_cookie['userid'] = g.user.buid else: lastuser_cookie.pop('userid', None) g.lastuser_cookie = lastuser_cookie # This will be set to True downstream by the requires_login decorator g.login_required = False
def lookup_current_user(): """ If there's a userid in the session, retrieve the user object and add to the request namespace object g. """ g.user = None g.usersession = None lastuser_cookie = {} lastuser_cookie_headers = {} # Ignored for now, intended for future changes # Migrate data from Flask cookie session if 'sessionid' in session: lastuser_cookie['sessionid'] = session.pop('sessionid') if 'userid' in session: lastuser_cookie['userid'] = session.pop('userid') if 'lastuser' in request.cookies: try: lastuser_cookie, lastuser_cookie_headers = lastuser_oauth.serializer.loads( request.cookies['lastuser'], return_header=True) except itsdangerous.BadSignature: lastuser_cookie = {} if 'sessionid' in lastuser_cookie: g.usersession = UserSession.authenticate(buid=lastuser_cookie['sessionid']) if g.usersession: g.usersession.access() db.session.commit() # Save access g.user = g.usersession.user # Transition users with 'userid' to 'sessionid' if not g.usersession and 'userid' in lastuser_cookie: g.user = User.get(userid=lastuser_cookie['userid']) if g.user: g.usersession = UserSession(user=g.user) g.usersession.access() db.session.commit() # Save access if g.usersession: lastuser_cookie['sessionid'] = g.usersession.buid else: lastuser_cookie.pop('sessionid', None) if g.user: lastuser_cookie['userid'] = g.user.userid else: lastuser_cookie.pop('userid', None) g.lastuser_cookie = lastuser_cookie # This will be set to True downstream by the requires_login decorator g.login_required = False
def _load_user(self): """ If there's a buid in the session, retrieve the user object and add to the request namespace object g. """ add_auth_attribute('user', None) add_auth_attribute('session', None) lastuser_cookie = {} lastuser_cookie_headers = {} # Ignored for now, intended for future changes # Migrate data from Flask cookie session if 'sessionid' in session: lastuser_cookie['sessionid'] = session.pop('sessionid') if 'userid' in session: lastuser_cookie['userid'] = session.pop('userid') if 'lastuser' in request.cookies: try: lastuser_cookie, lastuser_cookie_headers = lastuser_oauth.serializer.loads( request.cookies['lastuser'], return_header=True) except itsdangerous.BadSignature: lastuser_cookie = {} if 'sessionid' in lastuser_cookie: add_auth_attribute('session', UserSession.authenticate(buid=lastuser_cookie['sessionid'])) if current_auth.session: current_auth.session.access() db.session.commit() # Save access add_auth_attribute('user', current_auth.session.user) # Transition users with 'userid' to 'sessionid' if not current_auth.session and 'userid' in lastuser_cookie: add_auth_attribute('user', User.get(buid=lastuser_cookie['userid'])) if current_auth.is_authenticated: add_auth_attribute('session', UserSession(user=current_auth.user)) current_auth.session.access() db.session.commit() # Save access if current_auth.session: lastuser_cookie['sessionid'] = current_auth.session.buid else: lastuser_cookie.pop('sessionid', None) if current_auth.is_authenticated: lastuser_cookie['userid'] = current_auth.user.buid else: lastuser_cookie.pop('userid', None) add_auth_attribute('cookie', lastuser_cookie) # This will be set to True downstream by the requires_login decorator add_auth_attribute('login_required', False)
def user_autocomplete(): """ Returns users (userid, username, fullname, twitter, github or email) matching the search term. """ q = request.values.get('q', '') if not q: return api_result('error', error='no_query_provided') users = User.autocomplete(q) result = [{ 'userid': u.userid, 'buid': u.userid, 'name': u.username, 'title': u.fullname, 'label': u.pickername} for u in users] return api_result('ok', users=result)
def validate_name(self, field): if not valid_username(field.data): raise forms.ValidationError(_("Invalid characters in name")) if field.data in current_app.config['RESERVED_USERNAMES']: raise forms.ValidationError(_("This name is reserved")) existing = User.get(username=field.data) if existing is not None: if existing == current_auth.user: raise forms.ValidationError(Markup(_(u"This is <em>your</em> current username. " u'You must change it first from <a href="{profile}">your profile</a> ' u"before you can assign it to an organization").format( profile=url_for('profile')))) else: raise forms.ValidationError(_("This name is taken")) existing = Organization.get(name=field.data) if existing is not None and existing.id != self.edit_id: raise forms.ValidationError(_("This name is taken"))
def permission_user_delete(client, kwargs): if client.user: user = User.get(userid=kwargs['userid']) if not user: abort(404) permassign = UserClientPermissions.query.filter_by(user=user, client=client).first_or_404() return render_delete_sqla(permassign, db, title=u"Confirm delete", message=u"Remove all permissions assigned to user {pname} for app ‘{title}’?".format( pname=user.pickername, title=client.title), success=u"You have revoked permisions for user {pname}".format(pname=user.pickername), next=url_for('.client_info', key=client.key)) else: team = Team.get(userid=kwargs['userid']) if not team: abort(404) permassign = TeamClientPermissions.query.filter_by(team=team, client=client).first_or_404() return render_delete_sqla(permassign, db, title=u"Confirm delete", message=u"Remove all permissions assigned to team ‘{pname}’ for app ‘{title}’?".format( pname=team.title, title=client.title), success=u"You have revoked permisions for team {title}".format(title=team.title), next=url_for('.client_info', key=client.key))
def permission_user_edit(client, kwargs): if client.user: user = User.get(userid=kwargs['userid']) if not user: abort(404) available_perms = Permission.query.filter(db.or_( Permission.allusers == True, Permission.user == g.user)).order_by('name').all() permassign = UserClientPermissions.query.filter_by(user=user, client=client).first_or_404() elif client.org: team = Team.get(userid=kwargs['userid']) if not team: abort(404) available_perms = Permission.query.filter(db.or_( Permission.allusers == True, Permission.org == client.org)).order_by('name').all() permassign = TeamClientPermissions.query.filter_by(team=team, client=client).first_or_404() form = PermissionEditForm() form.perms.choices = [(ap.name, u"{name} – {title}".format(name=ap.name, title=ap.title)) for ap in available_perms] if request.method == 'GET': if permassign: form.perms.data = permassign.access_permissions.split(u' ') if form.validate_on_submit(): form.perms.data.sort() perms = u' '.join(form.perms.data) if not perms: db.session.delete(permassign) else: permassign.access_permissions = perms db.session.commit() if perms: if client.user: flash(u"Permissions have been updated for user {pname}".format(pname=user.pickername), 'success') else: flash(u"Permissions have been updated for team {title}".format(title=team.title), 'success') else: if client.user: flash(u"All permissions have been revoked for user {pname}".format(pname=user.pickername), 'success') else: flash(u"All permissions have been revoked for team {title}".format(title=team.title), 'success') return render_redirect(url_for('.client_info', key=client.key), code=303) return render_form(form=form, title="Edit permissions", formid="perm_edit", submit="Save changes", ajax=True)
def dashboard(): user_count = User.active_user_count() mau = ( db.session.query('mau') .from_statement( db.text( ''' SELECT COUNT(DISTINCT(user_session.user_id)) AS mau FROM user_session, "user" WHERE user_session.user_id = "user".id AND "user".status = :status AND user_session.accessed_at >= NOW() - INTERVAL '30 days' ''' ) ) .params(status=USER_STATUS.ACTIVE) .scalar() ) return render_template('dashboard.html.jinja2', user_count=user_count, mau=mau)
def profile_merge(): if "merge_userid" not in session: return redirect(get_next_url(), code=302) other_user = User.get(userid=session["merge_userid"]) if other_user is None: session.pop("merge_userid", None) return redirect(get_next_url(), code=302) form = ProfileMergeForm() if form.validate_on_submit(): if "merge" in request.form: new_user = merge_users(g.user, other_user) login_internal(new_user) user_data_changed.send(new_user, changes=["merge"]) flash(_("Your accounts have been merged"), "success") session.pop("merge_userid", None) db.session.commit() return redirect(get_next_url(), code=303) else: session.pop("merge_userid", None) return redirect(get_next_url(), code=303) return render_template("merge.html", form=form, user=g.user, other_user=other_user, login_registry=login_registry)
def account_merge(): if 'merge_buid' not in session: return redirect(get_next_url(), code=302) other_user = User.get(buid=session['merge_buid']) if other_user is None: session.pop('merge_buid', None) return redirect(get_next_url(), code=302) form = ProfileMergeForm() if form.validate_on_submit(): if 'merge' in request.form: new_user = merge_users(current_auth.user, other_user) login_internal(new_user) flash(_("Your accounts have been merged"), 'success') session.pop('merge_buid', None) db.session.commit() user_data_changed.send(new_user, changes=['merge']) return redirect(get_next_url(), code=303) else: session.pop('merge_buid', None) return redirect(get_next_url(), code=303) return render_template('merge.html.jinja2', form=form, user=current_auth.user, other_user=other_user, login_registry=login_registry)
def permission_user_delete(auth_client, kwargs): if auth_client.user: user = User.get(buid=kwargs['buid']) if not user: abort(404) permassign = AuthClientUserPermissions.get(auth_client=auth_client, user=user) if not permassign: abort(404) return render_delete_sqla( permassign, db, title=_("Confirm delete"), message= _("Remove all permissions assigned to user {pname} for app ‘{title}’?" ).format(pname=user.pickername, title=auth_client.title), success=_("You have revoked permisions for user {pname}").format( pname=user.pickername), next=url_for('.client_info', key=auth_client.buid), ) else: team = Team.get(buid=kwargs['buid']) if not team: abort(404) permassign = AuthClientTeamPermissions.get(auth_client=auth_client, team=team) if not permassign: abort(404) return render_delete_sqla( permassign, db, title=_("Confirm delete"), message= _("Remove all permissions assigned to team ‘{pname}’ for app ‘{title}’?" ).format(pname=team.title, title=auth_client.title), success=_("You have revoked permisions for team {title}").format( title=team.title), next=url_for('.client_info', key=auth_client.buid), )
def profile_merge(): if 'merge_userid' not in session: return redirect(get_next_url(), code=302) other_user = User.get(userid=session['merge_userid']) if other_user is None: session.pop('merge_userid', None) return redirect(get_next_url(), code=302) form = ProfileMergeForm() if form.validate_on_submit(): if 'merge' in request.form: new_user = merge_users(g.user, other_user) login_internal(new_user) user_data_changed.send(new_user, changes=['merge']) flash("Your accounts have been merged.", 'success') session.pop('merge_userid', None) return redirect(get_next_url(), code=303) else: session.pop('merge_userid', None) return redirect(get_next_url(), code=303) return render_template("merge.html", form=form, user=g.user, other_user=other_user, login_registry=login_registry)
def then_user_registered(context): user = User.get(username=context.test_user['username']) assert user is not None assert len(user.emailclaims) == 1
def permission_user_edit(auth_client, kwargs): if auth_client.user: user = User.get(buid=kwargs['buid']) if not user: abort(404) permassign = AuthClientUserPermissions.get(auth_client=auth_client, user=user) if not permassign: abort(404) elif auth_client.organization: team = Team.get(buid=kwargs['buid']) if not team: abort(404) permassign = AuthClientTeamPermissions.get(auth_client=auth_client, team=team) if not permassign: abort(404) form = PermissionEditForm() if request.method == 'GET': if permassign: form.perms.data = permassign.access_permissions if form.validate_on_submit(): perms = ' '.join(sorted(form.perms.data.split())) if not perms: db.session.delete(permassign) else: permassign.access_permissions = perms db.session.commit() if perms: if auth_client.user: flash( _("Permissions have been updated for user {pname}").format( pname=user.pickername), 'success', ) else: flash( _("Permissions have been updated for team {title}").format( title=team.title), 'success', ) else: if auth_client.user: flash( _("All permissions have been revoked for user {pname}"). format(pname=user.pickername), 'success', ) else: flash( _("All permissions have been revoked for team {title}"). format(title=team.title), 'success', ) return render_redirect(url_for('.client_info', key=auth_client.buid), code=303) return render_form( form=form, title=_("Edit permissions"), formid='perm_edit', submit=_("Save changes"), ajax=True, )
#!/usr/bin/env python # -*- coding: utf-8 -*- from lastuser_core.models import AuthClient, Organization, User # isort:skip from lastuserapp import app, db # incase data exists from previously run tests db.drop_all() # create schema again db.create_all() # Add fixtures for test app # user for CRUD workflow: creating client app gustav = User( username="******", fullname="Gustav 'world' Dachshund", password='******' ) # org for associating with client # client for CRUD workflow of defining perms *in* client # spare user for CRUD workflow of assigning permissions oakley = User(username="******", fullname="Oakley 'huh' Dachshund") dachsunited = Organization(name="dachsunited", title="Dachs United") dachsunited.owners.users.append(gustav) dachshundworld = AuthClient( title="Dachshund World", org=dachsunited, confidential=True, website="http://gustavsdachshundworld.com", ) db.session.add(gustav) db.session.add(oakley)
def then_user_registered(context): # just one user exists, the first one user = User.get(username=context.test_user['username']) assert user is not None
def then_user_registered(context): user = User.get(username=context.test_user['username']) assert user is not None assert len(user.emailclaims) is 1
def oauth_token(): """ OAuth2 server -- token endpoint (confidential clients only) """ # Always required parameters grant_type = request.form.get('grant_type') client = g.client # Provided by @requires_client_login scope = request.form.get('scope', u'').split(u' ') # if grant_type == 'authorization_code' (POST) code = request.form.get('code') redirect_uri = request.form.get('redirect_uri') # if grant_type == 'password' (POST) username = request.form.get('username') password = request.form.get('password') # if grant_type == 'client_credentials' userid = request.form.get('userid') # Validations 1: Required parameters if not grant_type: return oauth_token_error('invalid_request', _("Missing grant_type")) # grant_type == 'refresh_token' is not supported. All tokens are permanent unless revoked if grant_type not in ['authorization_code', 'client_credentials', 'password']: return oauth_token_error('unsupported_grant_type') # Validations 2: client scope if grant_type == 'client_credentials': # Client data; user isn't part of it OR trusted client and automatic scope try: # FIXME: What is this verifyscope doing? That this scope is valid or that this client has access? verifyscope(scope, client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', unicode(scopeex)) if userid: if client.trusted: user = User.get(userid=userid) if user: token = oauth_make_token(user=user, client=client, scope=client.scope) return oauth_token_success(token, userinfo=get_userinfo( user=token.user, client=client, scope=token.scope)) else: return oauth_token_error('invalid_grant', _("Unknown user")) else: return oauth_token_error('invalid_grant', _("Untrusted client")) else: token = oauth_make_token(user=None, client=client, scope=scope) return oauth_token_success(token) # Validations 3: auth code elif grant_type == 'authorization_code': authcode = AuthCode.query.filter_by(code=code, client=client).first() if not authcode: return oauth_token_error('invalid_grant', _("Unknown auth code")) if not authcode.is_valid(): db.session.delete(authcode) db.session.commit() return oauth_token_error('invalid_grant', _("Expired auth code")) # Validations 3.1: scope in authcode if not scope or scope[0] == '': return oauth_token_error('invalid_scope', _("Scope is blank")) if not set(scope).issubset(set(authcode.scope)): return oauth_token_error('invalid_scope', _("Scope expanded")) else: # Scope not provided. Use whatever the authcode allows scope = authcode.scope if redirect_uri != authcode.redirect_uri: return oauth_token_error('invalid_client', _("redirect_uri does not match")) token = oauth_make_token(user=authcode.user, client=client, scope=scope) db.session.delete(authcode) return oauth_token_success(token, userinfo=get_userinfo( user=authcode.user, client=client, scope=token.scope, session=authcode.session)) elif grant_type == 'password': # Validations 4.1: password grant_type is only for trusted clients if not client.trusted: # Refuse to untrusted clients return oauth_token_error('unauthorized_client', _("Client is not trusted for password grant_type")) # Validations 4.2: Are username and password provided and correct? if not username or not password: return oauth_token_error('invalid_request', _("Username or password not provided")) user = getuser(username) if not user: return oauth_token_error('invalid_client', _("No such user")) # XXX: invalid_client doesn't seem right if not user.password_is(password): return oauth_token_error('invalid_client', _("Password mismatch")) # Validations 4.3: verify scope try: verifyscope(scope, client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', unicode(scopeex)) # All good. Grant access token = oauth_make_token(user=user, client=client, scope=scope) return oauth_token_success(token, userinfo=get_userinfo(user=user, client=client, scope=scope))
def oauth_token(): """ OAuth2 server -- token endpoint (confidential clients only) """ # Always required parameters grant_type = request.form.get('grant_type') auth_client = current_auth.auth_client # Provided by @requires_client_login scope = request.form.get('scope', '').split(' ') # if grant_type == 'authorization_code' (POST) code = request.form.get('code') redirect_uri = request.form.get('redirect_uri') # if grant_type == 'password' (POST) username = request.form.get('username') password = request.form.get('password') # if grant_type == 'client_credentials' buid = request.form.get('buid') or request.form.get( 'userid') # XXX: Deprecated userid parameter # Validations 1: Required parameters if not grant_type: return oauth_token_error('invalid_request', _("Missing grant_type")) # grant_type == 'refresh_token' is not supported. All tokens are permanent unless revoked if grant_type not in [ 'authorization_code', 'client_credentials', 'password' ]: return oauth_token_error('unsupported_grant_type') # Validations 2: client scope if grant_type == 'client_credentials': # AuthClient data; user isn't part of it OR trusted client and automatic scope try: # Confirm the client has access to the scope it wants verifyscope(scope, auth_client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', str(scopeex)) if buid: if auth_client.trusted: user = User.get(buid=buid) if user: # This client is trusted and can receive a user access token. # However, don't grant it the scope it wants as the user's # permission was not obtained. Instead, the client's # pre-approved scope will be used for the token's effective scope. token = oauth_make_token(user=user, auth_client=auth_client, scope=[]) return oauth_token_success( token, userinfo=get_userinfo( user=token.user, auth_client=auth_client, scope=token.effective_scope, ), ) else: return oauth_token_error('invalid_grant', _("Unknown user")) else: return oauth_token_error('invalid_grant', _("Untrusted client app")) else: token = oauth_make_token(user=None, auth_client=auth_client, scope=scope) return oauth_token_success(token) # Validations 3: auth code elif grant_type == 'authorization_code': authcode = AuthCode.get_for_client(auth_client=auth_client, code=code) if not authcode: return oauth_token_error('invalid_grant', _("Unknown auth code")) if not authcode.is_valid(): db.session.delete(authcode) db.session.commit() return oauth_token_error('invalid_grant', _("Expired auth code")) # Validations 3.1: scope in authcode if not scope or scope[0] == '': return oauth_token_error('invalid_scope', _("Scope is blank")) if not set(scope).issubset(set(authcode.scope)): return oauth_token_error('invalid_scope', _("Scope expanded")) else: # Scope not provided. Use whatever the authcode allows scope = authcode.scope if redirect_uri != authcode.redirect_uri: return oauth_token_error('invalid_client', _("redirect_uri does not match")) token = oauth_make_token(user=authcode.user, auth_client=auth_client, scope=scope) db.session.delete(authcode) return oauth_token_success( token, userinfo=get_userinfo( user=authcode.user, auth_client=auth_client, scope=token.effective_scope, user_session=authcode.user_session, ), ) elif grant_type == 'password': # Validations 4.1: password grant_type is only for trusted clients if not auth_client.trusted: # Refuse to untrusted clients return oauth_token_error( 'unauthorized_client', _("AuthClient is not trusted for password grant_type"), ) # Validations 4.2: Are username and password provided and correct? if not username or not password: return oauth_token_error('invalid_request', _("Username or password not provided")) user = getuser(username) if not user: return oauth_token_error( 'invalid_client', _("No such user")) # XXX: invalid_client doesn't seem right if not user.password_is(password): return oauth_token_error('invalid_client', _("Password mismatch")) # Validations 4.3: verify scope try: verifyscope(scope, auth_client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', str(scopeex)) # All good. Grant access token = oauth_make_token(user=user, auth_client=auth_client, scope=scope) return oauth_token_success( token, userinfo=get_userinfo(user=user, auth_client=auth_client, scope=scope), )
def oauth_token(): """ OAuth2 server -- token endpoint (confidential clients only) """ # Always required parameters grant_type = request.form.get('grant_type') client = g.client # Provided by @requires_client_login scope = request.form.get('scope', u'').split(u' ') # if grant_type == 'authorization_code' (POST) code = request.form.get('code') redirect_uri = request.form.get('redirect_uri') # if grant_type == 'password' (POST) username = request.form.get('username') password = request.form.get('password') # if grant_type == 'client_credentials' buid = request.form.get('buid') or request.form.get('userid') # XXX: Deprecated userid parameter # Validations 1: Required parameters if not grant_type: return oauth_token_error('invalid_request', _("Missing grant_type")) # grant_type == 'refresh_token' is not supported. All tokens are permanent unless revoked if grant_type not in ['authorization_code', 'client_credentials', 'password']: return oauth_token_error('unsupported_grant_type') # Validations 2: client scope if grant_type == 'client_credentials': # Client data; user isn't part of it OR trusted client and automatic scope try: # FIXME: What is this verifyscope doing? That this scope is valid or that this client has access? verifyscope(scope, client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', unicode(scopeex)) if buid: if client.trusted: user = User.get(buid=buid) if user: token = oauth_make_token(user=user, client=client, scope=[]) return oauth_token_success( token, userinfo=get_userinfo( user=token.user, client=client, scope=token.effective_scope)) else: return oauth_token_error('invalid_grant', _("Unknown user")) else: return oauth_token_error('invalid_grant', _("Untrusted client")) else: token = oauth_make_token(user=None, client=client, scope=scope) return oauth_token_success(token) # Validations 3: auth code elif grant_type == 'authorization_code': authcode = AuthCode.query.filter_by(code=code, client=client).first() if not authcode: return oauth_token_error('invalid_grant', _("Unknown auth code")) if not authcode.is_valid(): db.session.delete(authcode) db.session.commit() return oauth_token_error('invalid_grant', _("Expired auth code")) # Validations 3.1: scope in authcode if not scope or scope[0] == '': return oauth_token_error('invalid_scope', _("Scope is blank")) if not set(scope).issubset(set(authcode.scope)): return oauth_token_error('invalid_scope', _("Scope expanded")) else: # Scope not provided. Use whatever the authcode allows scope = authcode.scope if redirect_uri != authcode.redirect_uri: return oauth_token_error('invalid_client', _("redirect_uri does not match")) token = oauth_make_token(user=authcode.user, client=client, scope=scope) db.session.delete(authcode) return oauth_token_success(token, userinfo=get_userinfo( user=authcode.user, client=client, scope=token.effective_scope, session=authcode.session)) elif grant_type == 'password': # Validations 4.1: password grant_type is only for trusted clients if not client.trusted: # Refuse to untrusted clients return oauth_token_error('unauthorized_client', _("Client is not trusted for password grant_type")) # Validations 4.2: Are username and password provided and correct? if not username or not password: return oauth_token_error('invalid_request', _("Username or password not provided")) user = getuser(username) if not user: return oauth_token_error('invalid_client', _("No such user")) # XXX: invalid_client doesn't seem right if not user.password_is(password): return oauth_token_error('invalid_client', _("Password mismatch")) # Validations 4.3: verify scope try: verifyscope(scope, client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', unicode(scopeex)) # All good. Grant access token = oauth_make_token(user=user, client=client, scope=scope) return oauth_token_success(token, userinfo=get_userinfo(user=user, client=client, scope=scope))
def make_fixtures(self): """ Create users, attach them to organizations. Create test client app, add test resource, action and message. """ crusoe = User(username="******", fullname="Crusoe Celebrity Dachshund") oakley = User(username="******") piglet = User(username="******") nameless = User(fullname="Nameless") db.session.add_all([crusoe, oakley, piglet, nameless]) self.crusoe = crusoe self.oakley = oakley self.piglet = piglet self.nameless = nameless crusoe_email = UserEmail( email="*****@*****.**", user=crusoe, primary=True ) crusoe_phone = UserPhone(phone="+8080808080", user=crusoe, primary=True) oakley_email = UserEmail(email="*****@*****.**", user=oakley) db.session.add_all([crusoe_email, crusoe_phone, oakley_email]) self.crusoe_email = crusoe_email self.crusoe_phone = crusoe_phone batdog = Organization(name='batdog', title='Batdog') batdog.owners.users.append(crusoe) db.session.add(batdog) self.batdog = batdog specialdachs = Organization(name="specialdachs", title="Special Dachshunds") specialdachs.owners.users.append(oakley) db.session.add(specialdachs) self.specialdachs = specialdachs auth_client = AuthClient( title="Batdog Adventures", organization=batdog, confidential=True, namespace='fun.batdogadventures.com', website="http://batdogadventures.com", ) db.session.add(auth_client) self.auth_client = auth_client dachshunds = Team(title="Dachshunds", organization=batdog) db.session.add(dachshunds) self.dachshunds = dachshunds auth_client_team_permissions = AuthClientTeamPermissions( team=dachshunds, auth_client=auth_client, access_permissions="admin" ) self.auth_client_team_permissions = auth_client_team_permissions db.session.add(auth_client_team_permissions) auth_client_user_permissions = AuthClientUserPermissions( user=crusoe, auth_client=auth_client ) db.session.add(auth_client_user_permissions) self.auth_client_user_permissions = auth_client_user_permissions message = SMSMessage( phone_number=crusoe_phone.phone, transactionid="Ruff" * 5, message="Wuff Wuff", ) db.session.add(message) db.session.commit() self.message = message
def make_fixtures(self): """ Create users, attach them to organizations. Create test client app, add test resource, action and message. """ crusoe = User(username=u"crusoe", fullname=u"Crusoe Celebrity Dachshund") oakley = User(username=u"oakley") piglet = User(username=u"piglet") nameless = User(fullname="Nameless") db.session.add_all([crusoe, oakley, piglet, nameless]) self.crusoe = crusoe self.oakley = oakley self.piglet = piglet self.nameless = nameless crusoe_email = UserEmail(email=u"*****@*****.**", primary=True, user=crusoe) crusoe_phone = UserPhone(phone=u"+8080808080", primary=True, user=crusoe) oakley_email = UserEmail(email=u"*****@*****.**", user=oakley) db.session.add_all([crusoe_email, crusoe_phone, oakley_email]) self.crusoe_email = crusoe_email self.crusoe_phone = crusoe_phone batdog = Organization(name=u'batdog', title=u'Batdog') batdog.owners.users.append(crusoe) batdog.members.users.append(oakley) db.session.add(batdog) self.batdog = batdog specialdachs = Organization(name=u"specialdachs", title=u"Special Dachshunds") specialdachs.owners.users.append(oakley) specialdachs.members.users.append(piglet) db.session.add(specialdachs) self.specialdachs = specialdachs client = Client(title=u"Batdog Adventures", org=batdog, confidential=True, namespace=u'fun.batdogadventures.com', website=u"http://batdogadventures.com") db.session.add(client) self.client = client dachshunds = Team(title=u"Dachshunds", org=batdog) db.session.add(dachshunds) self.dachshunds = dachshunds team_client_permission = TeamClientPermissions( team=dachshunds, client=client, access_permissions=u"admin") self.team_client_permission = team_client_permission db.session.add(team_client_permission) client_team_access = ClientTeamAccess( org=batdog, client=client, access_level=CLIENT_TEAM_ACCESS.ALL) db.session.add(client_team_access) bdfl = Permission(name=u"bdfl", title=u"BDFL", user=crusoe) db.session.add(bdfl) self.bdfl = bdfl user_client_permissions = UserClientPermissions(user=crusoe, client=client) db.session.add(user_client_permissions) self.user_client_permissions = user_client_permissions resource = Resource(name=u"test_resource", title=u"Test Resource", client=client) db.session.add(resource) self.resource = resource resource_action = ResourceAction(name=u'Fun', resource=resource, title=u'fun') db.session.add(resource_action) self.resource_action = resource_action action = ResourceAction(name=u"read", title=u"Read", resource=resource) db.session.add(action) self.action = action message = SMSMessage(phone_number=crusoe_phone.phone, transaction_id=u"Ruff" * 5, message=u"Wuff Wuff") db.session.add(message) db.session.commit() self.message = message