Exemplo n.º 1
0
    def test_user_password(self, testapp):
        """ Test password hashing and checking """

        admin = User('admin', 'supersafepassword')

        assert admin.username == 'admin'
        assert admin.check_password('supersafepassword')
Exemplo n.º 2
0
    def test_user_save(self, testapp):
        """ Test Saving the user model to the database """

        admin = User('admin', 'supersafepassword')
        db.session.add(admin)
        db.session.commit()

        user = User.query.filter_by(username="******").first()
        assert user is not None
Exemplo n.º 3
0
    def get(self):
        redirect_uri = request.url
        flow = get_auth_flow(redirect_uri=redirect_uri)
        response = flow.step2_exchange(request.args['code'])

        scopes = response.token_response['scope'].split(',')

        if 'user:email' not in scopes:
            raise NotImplementedError

        identity_config = {
            'access_token': response.access_token,
            'refresh_token': response.refresh_token,
            'scopes': scopes,
        }

        # fetch user details
        response = requests.get(
            'https://api.github.com/user', params={'access_token': identity_config['access_token']}
        )
        response.raise_for_status()
        user_data = response.json()

        with db.session.begin_nested():
            existing_identity = Identity.query.filter(
                Identity.external_id == str(user_data['id']),
                Identity.provider == 'github',
            ).first()
            if not existing_identity:
                user = User(
                    email=user_data['email'],
                )
                db.session.add(user)
                identity = Identity(
                    user=user,
                    external_id=str(user_data['id']),
                    provider='github',
                    config=identity_config,
                )
                db.session.add(identity)
            else:
                user = User.query.filter(
                    Identity.external_id == str(user_data['id']),
                    Identity.provider == 'github',
                    Identity.user_id == User.id,
                ).first()
                Identity.query.filter(
                    Identity.external_id == str(user_data['id']),
                    Identity.provider == 'github',
                ).update({
                    'config': identity_config,
                })

        session['uid'] = user.id.hex

        return redirect(url_for(self.complete_url))
Exemplo n.º 4
0
    def get(self):
        redirect_uri = request.url
        flow = get_auth_flow(redirect_uri=redirect_uri)
        try:
            oauth_response = flow.step2_exchange(request.args['code'])
        except FlowExchangeError:
            return redirect('/?auth_error=true')

        scopes = oauth_response.token_response['scope'].split(',')

        if 'user:email' not in scopes:
            raise NotImplementedError

        # fetch user details
        response = requests.get(
            'https://api.github.com/user',
            params={'access_token': oauth_response.access_token})
        response.raise_for_status()
        user_data = response.json()

        identity_config = {
            'access_token': oauth_response.access_token,
            'refresh_token': oauth_response.refresh_token,
            'scopes': scopes,
            'login': user_data['login'],
        }

        try:
            with db.session.begin_nested():
                user = User(email=user_data['email'], )
                db.session.add(user)
                identity = Identity(
                    user=user,
                    external_id=str(user_data['id']),
                    provider='github',
                    config=identity_config,
                )
                db.session.add(identity)
            user_id = user.id
        except IntegrityError:
            identity = Identity.query.filter(
                Identity.external_id == str(user_data['id']),
                Identity.provider == 'github',
            ).first()
            identity.config = identity_config
            db.session.add(identity)
            user_id = identity.user_id

        db.session.commit()

        session['uid'] = user_id

        return redirect(url_for(self.complete_url))
Exemplo n.º 5
0
def testapp(request):
    app = create_app('zeus.settings.TestConfig')
    client = app.test_client()

    db.app = app
    db.create_all()

    if getattr(request.module, "create_user", True):
        admin = User('admin', 'supersafepassword')
        db.session.add(admin)
        db.session.commit()

    def teardown():
        db.session.remove()
        db.drop_all()

    request.addfinalizer(teardown)

    return client
Exemplo n.º 6
0
    def get(self):
        redirect_uri = request.url
        flow = get_auth_flow(redirect_uri=redirect_uri)
        try:
            oauth_response = flow.step2_exchange(request.args['code'])
        except FlowExchangeError:
            return redirect('/?auth_error=true')

        scopes = oauth_response.token_response['scope'].split(',')

        if 'user:email' not in scopes:
            raise NotImplementedError

        # fetch user details
        github = GitHubClient(token=oauth_response.access_token)
        user_data = github.get('/user')

        identity_config = {
            'access_token': oauth_response.access_token,
            'refresh_token': oauth_response.refresh_token,
            'scopes': scopes,
            'login': user_data['login'],
        }

        email = user_data.get('email')
        # no primary/public email specified
        if not email:
            emails = github.get('/user/emails')
            email = next((
                e['email'] for e in emails
                if e['verified'] and e['primary']
            ))
        try:
            with db.session.begin_nested():
                user = User(
                    email=email,
                )
                db.session.add(user)
                identity = Identity(
                    user=user,
                    external_id=str(user_data['id']),
                    provider='github',
                    config=identity_config,
                )
                db.session.add(identity)
            user_id = user.id
        except IntegrityError:
            identity = Identity.query.filter(
                Identity.external_id == str(user_data['id']),
                Identity.provider == 'github',
            ).first()
            identity.config = identity_config
            db.session.add(identity)
            user_id = identity.user_id

        db.session.commit()

        # forcefully expire a session after permanent_session_lifetime
        # Note: this is enforced in zeus.auth
        auth.login_user(user_id)

        return redirect(url_for(self.complete_url))
Exemplo n.º 7
0
    def get(self):
        # TODO(dcramer): handle errors
        oauth = get_oauth_session(state=session.pop("oauth_state", None))
        try:
            resp = oauth.fetch_token(
                GITHUB_TOKEN_URI,
                client_secret=current_app.config["GITHUB_CLIENT_SECRET"],
                authorization_response=request.url,
            )
        except OAuth2Error:
            current_app.logger.exception("oauth.error")
            # redirect, as this is likely temporary based on server data
            return redirect(auth.get_redirect_target(clear=True) or "/")

        if resp is None or resp.get("access_token") is None:
            return Response("Access denied: reason=%s error=%s resp=%s" %
                            (request.args["error"],
                             request.args["error_description"], resp))

        assert resp.get("token_type") == "bearer"

        scopes = resp["scope"][0].split(",")
        if "user:email" not in scopes:
            raise NotImplementedError

        # fetch user details
        client = GitHubClient(token=resp["access_token"])
        user_data = client.get("/user")

        identity_config = {
            "access_token": resp["access_token"],
            "refresh_token": resp.get("refresh_token"),
            "login": user_data["login"],
        }

        email_list = client.get("/user/emails")
        email_list.append({
            "email":
            "{}@users.noreply.github.com".format(user_data["login"]),
            "verified":
            True,
        })

        primary_email = user_data.get("email")
        # HACK(dcramer): capture github's anonymous email addresses when they're not listed
        # (we haven't actually confirmed they're not listed)
        if not primary_email:
            primary_email = next((e["email"] for e in email_list
                                  if e["verified"] and e["primary"]))

        try:
            # we first attempt to create a new user + identity
            with db.session.begin_nested():
                user = User(email=primary_email)
                db.session.add(user)
                identity = Identity(
                    user=user,
                    external_id=str(user_data["id"]),
                    provider="github",
                    scopes=scopes,
                    config=identity_config,
                )
                db.session.add(identity)
            user_id = user.id
            new_user = True
        except IntegrityError:
            # if that fails, assume the identity exists
            identity = Identity.query.filter(
                Identity.external_id == str(user_data["id"]),
                Identity.provider == "github",
            ).first()

            # and if it doesnt, attempt to find a matching user,
            # as it means the failure above was due to that
            if not identity:
                user = User.query.filter(User.email == primary_email).first()
                assert (
                    user
                )  # this should not be possible unless we've got a race condition
                identity = Identity(
                    user=user,
                    external_id=str(user_data["id"]),
                    provider="github",
                    scopes=scopes,
                    config=identity_config,
                )
                db.session.add(identity)
                user_id = user.id
            else:
                identity.config = identity_config
                identity.scopes = scopes
                db.session.add(identity)
                user_id = identity.user_id
            new_user = False
        db.session.flush()

        for email in email_list:
            try:
                with db.session.begin_nested():
                    db.session.add(
                        Email(
                            user_id=user_id,
                            email=email["email"],
                            verified=email["verified"],
                        ))
            except IntegrityError:
                pass

        db.session.commit()

        # forcefully expire a session after permanent_session_lifetime
        # Note: this is enforced in zeus.auth
        auth.login_user(user_id)

        user = auth.get_current_user()
        if new_user:
            # update synchronously so the new user has a better experience
            sync_github_access(user_id=user.id)
        else:
            sync_github_access.delay(user_id=user.id)

        next_uri = auth.get_redirect_target(clear=True) or "/"
        if "/login" in next_uri or "/auth/github" in next_uri:
            next_uri = "/"
        return redirect(next_uri)
Exemplo n.º 8
0
    def get(self):
        redirect_uri = request.url
        flow = get_auth_flow(redirect_uri=redirect_uri)
        try:
            oauth_response = flow.step2_exchange(request.args['code'])
        except FlowExchangeError:
            return redirect('/?auth_error=true')

        scopes = oauth_response.token_response['scope'].split(',')

        if 'user:email' not in scopes:
            raise NotImplementedError

        # fetch user details
        github = GitHubClient(token=oauth_response.access_token)
        user_data = github.get('/user')

        identity_config = {
            'access_token': oauth_response.access_token,
            'refresh_token': oauth_response.refresh_token,
            'login': user_data['login'],
        }

        email_list = github.get('/user/emails')
        email_list.append({
            'email':
            '{}@users.noreply.github.com'.format(user_data['login']),
            'verified':
            True,
        })

        primary_email = user_data.get('email')
        # HACK(dcramer): capture github's anonymous email addresses when they're not listed
        # (we haven't actually confirmed they're not listed)
        if not primary_email:
            primary_email = next((e['email'] for e in email_list
                                  if e['verified'] and e['primary']))

        try:
            # we first attempt to create a new user + identity
            with db.session.begin_nested():
                user = User(email=primary_email, )
                db.session.add(user)
                identity = Identity(
                    user=user,
                    external_id=str(user_data['id']),
                    provider='github',
                    scopes=scopes,
                    config=identity_config,
                )
                db.session.add(identity)
            user_id = user.id
        except IntegrityError:
            # if that fails, assume the identity exists
            identity = Identity.query.filter(
                Identity.external_id == str(user_data['id']),
                Identity.provider == 'github',
            ).first()

            # and if it doesnt, attempt to find a matching user,
            # as it means the failure above was due to that
            if not identity:
                user = User.query.filter(User.email == primary_email).first()
                assert user  # this should not be possible unless we've got a race condition
                identity = Identity(
                    user=user,
                    external_id=str(user_data['id']),
                    provider='github',
                    scopes=scopes,
                    config=identity_config,
                )
                db.session.add(identity)
                user_id = user.id
            else:
                identity.config = identity_config
                identity.scopes = scopes
                db.session.add(identity)
                user_id = identity.user_id

        db.session.flush()

        for email in email_list:
            try:
                with db.session.begin_nested():
                    db.session.add(
                        Email(
                            user_id=user_id,
                            email=email['email'],
                            verified=email['verified'],
                        ))
            except IntegrityError:
                pass

        db.session.commit()

        # forcefully expire a session after permanent_session_lifetime
        # Note: this is enforced in zeus.auth
        auth.login_user(user_id)

        # now lets try to update the repos they have access to based on whats
        # enabled
        user = auth.get_current_user()
        grant_access_to_existing_repos(user)

        return redirect(auth.get_redirect_target(clear=True) or '/')