Esempio n. 1
0
def test_sqla_backend(app, db, blueprint, request):
    class User(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80))

    class OAuth(OAuthConsumerMixin, db.Model):
        user_id = db.Column(db.Integer, db.ForeignKey(User.id))
        user = db.relationship(User)

    db.create_all()

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

    request.addfinalizer(done)

    # for now, we'll assume that Alice is the only user
    alice = User(name="Alice")
    db.session.add(alice)
    db.session.commit()
    # load alice's ID -- this issues a database query
    alice.id

    blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=alice)

    with record_queries(db.engine) as queries:
        with app.test_client() as client:
            # reset the session before the request
            with client.session_transaction() as sess:
                sess["test-service_oauth_state"] = "random-string"
            # make the request
            resp = client.get(
                "/login/test-service/authorized?code=secret-code&state=random-string",
                base_url="https://a.b.c",
            )
            # check that we redirected the client
            assert resp.status_code == 302
            assert resp.headers["Location"] == "https://a.b.c/oauth_done"

    assert len(queries) == 3

    # check the database
    alice = User.query.first()
    authorizations = OAuth.query.all()
    assert len(authorizations) == 1
    oauth = authorizations[0]
    assert oauth.user_id == alice.id
    assert oauth.provider == "test-service"
    assert isinstance(oauth.token, dict)
    assert oauth.token == {
        "access_token": "foobar",
        "token_type": "bearer",
        "scope": [""],
    }
Esempio n. 2
0
def test_sqla_overwrite_token(app, db, blueprint, request):
    class OAuth(OAuthConsumerMixin, db.Model):
        pass

    blueprint.backend = SQLAlchemyBackend(OAuth, db.session)

    db.create_all()

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

    request.addfinalizer(done)

    # Create an existing OAuth token for the service
    existing = OAuth(
        provider="test-service",
        token={
            "access_token": "something",
            "token_type": "bearer",
            "scope": ["blah"],
        },
    )
    db.session.add(existing)
    db.session.commit()
    assert len(OAuth.query.all()) == 1

    with record_queries(db.engine) as queries:
        with app.test_client() as client:
            # reset the session before the request
            with client.session_transaction() as sess:
                sess["test-service_oauth_state"] = "random-string"
            # make the request
            resp = client.get(
                "/login/test-service/authorized?code=secret-code&state=random-string",
                base_url="https://a.b.c",
            )
            # check that we redirected the client
            assert resp.status_code == 302
            assert resp.headers["Location"] == "https://a.b.c/oauth_done"

    assert len(queries) == 2

    # check that the database record was overwritten
    authorizations = OAuth.query.all()
    assert len(authorizations) == 1
    oauth = authorizations[0]
    assert oauth.provider == "test-service"
    assert isinstance(oauth.token, dict)
    assert oauth.token == {
        "access_token": "foobar",
        "token_type": "bearer",
        "scope": [""],
    }
Esempio n. 3
0
def test_sqla_flask_login_misconfigured(app, db, blueprint, request):
    login_manager = LoginManager(app)

    class User(db.Model, UserMixin):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80))

    class OAuth(OAuthConsumerMixin, db.Model):
        user_id = db.Column(db.Integer, db.ForeignKey(User.id))
        user = db.relationship(User)

    blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)

    db.create_all()

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

    request.addfinalizer(done)

    # configure login manager
    @login_manager.user_loader
    def load_user(userid):
        return User.query.get(userid)

    calls = []

    def callback(*args, **kwargs):
        calls.append((args, kwargs))

    oauth_error.connect(callback)
    request.addfinalizer(lambda: oauth_error.disconnect(callback))

    with app.test_client() as client:
        # reset the session before the request
        with client.session_transaction() as sess:
            sess["test-service_oauth_state"] = "random-string"
        # make the request
        resp = client.get(
            "/login/test-service/authorized?code=secret-code&state=random-string",
            base_url="https://a.b.c",
        )
        # check that we redirected the client
        assert resp.status_code == 302
        assert resp.headers["Location"] == "https://a.b.c/oauth_done"

    assert len(calls) == 1
    assert calls[0][0] == (blueprint, )
    error = calls[0][1]['error']
    assert isinstance(error, ValueError)
    assert str(error) == 'Cannot set OAuth token without an associated user'
Esempio n. 4
0
def create_app():
    ''' Initialise the application with necessary extensions '''
    app = Flask(__name__)
    app.config.from_object(Config)
    app.app_context().push()

    bootstrap.init_app(app)

    db.init_app(app)

    login_manager.init_app(app)

    app.register_blueprint(main)
    app.register_blueprint(auth)
    app.register_blueprint(jinja_templates)
    app.register_blueprint(errors)

    github_blueprint = make_github_blueprint(
        client_id=Config.client_id, client_secret=Config.client_secret)
    github_blueprint.backend = SQLAlchemyBackend(OAuth,
                                                 db.session,
                                                 user=current_user,
                                                 user_required=False)
    app.register_blueprint(github_blueprint, url_prefix='/login')

    @login_manager.user_loader
    def load_user(user_id):
        return User.query.get(int(user_id))

    @oauth_authorized.connect_via(github_blueprint)
    def github_logged_in(blueprint, token):
        account_info = blueprint.session.get('/user')

        if account_info.ok:
            account_info_json = account_info.json()
            username = account_info_json['login']

            query = User.query.filter_by(username=username)

            try:
                user = query.one()
            except NoResultFound:
                user = User(username=username)
                db.session.add(user)
                db.session.commit()

            login_user(user)
            flash("Successfully signed in with GitHub.", 'success')

    return app
Esempio n. 5
0
def test_sqla_flask_login_no_user_required(app, db, blueprint, request):
    # need a URL to hit, so that tokens will be loaded, but result is irrelevant
    responses.add(
        responses.GET,
        "https://example.com/noop",
    )

    login_manager = LoginManager(app)

    class User(db.Model, UserMixin):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80))

    class OAuth(OAuthConsumerMixin, db.Model):
        user_id = db.Column(db.Integer, db.ForeignKey(User.id))
        user = db.relationship(User)

    blueprint.backend = SQLAlchemyBackend(
        OAuth,
        db.session,
        user=current_user,
        user_required=False,
    )

    db.create_all()

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

    request.addfinalizer(done)

    # configure login manager
    @login_manager.user_loader
    def load_user(userid):
        return User.query.get(userid)

    # create a simple view
    @app.route("/")
    def index():
        return "success"

    with app.test_request_context("/"):
        # no one is logged in -- this is an anonymous user
        logout_user()
        # this should *not* raise an error
        blueprint.session.get("/noop")
        assert blueprint.session.token == None
Esempio n. 6
0
def register_facebook_blueprint(app):
    # Facebook
    client_id = app.config.get('OAUTH_CONFIG')['FACEBOOK']['client_id']
    client_secret = app.config.get('OAUTH_CONFIG')['FACEBOOK']['client_secret']

    facebook_blueprint = make_facebook_blueprint(
        client_id=client_id,
        client_secret=client_secret,
        scope=["public_profile", "email"])
    facebook_blueprint.backend = SQLAlchemyBackend(OAuth,
                                                   db.session,
                                                   user=current_user)
    app_token = get_facebook_app_token(app)
    if app_token:
        app.register_blueprint(facebook_blueprint, url_prefix="/login")
    else:
        print(
            "Facebook app token not found in config. Facebook blueprint not configured."
        )

    # create/login local user on successful OAuth login
    @oauth_authorized.connect_via(facebook_blueprint)
    def facebook_logged_in(blueprint, token):
        if not token:
            flash("Failed to log in with {name}".format(name=blueprint.name))
            return
        # figure out who the user is
        resp = blueprint.session.get("/me?fields=email,name")
        if resp.ok:
            print(f"Response from facebook: {resp.json()}")
            username = resp.json()["email"]
            query = User.query.filter_by(username=username)
            try:
                user = query.one()
            except NoResultFound:
                # create a user
                user = User()
                user.username = username
                user.save()
            login_user(user)
            flash("Successfully signed in with Facebook", "success")
        else:
            print(resp.text)
            msg = "Failed to fetch user info from {name}".format(
                name=blueprint.name)
            flash(msg, category="error")
Esempio n. 7
0
def create_app(config_class=Config):
    app = Flask(__name__)
    app.config.from_object(Config)

    db.init_app(app)
    login_manager.init_app(app)
    login_manager.login_view = 'main.login'

    app.register_blueprint(google_auth_bp, url_prefix='/auth')

    from app.main import bp as main_blueprint
    app.register_blueprint(main_blueprint)

    # Setup SQLAlchemy flask-dance backend
    google_auth_bp.backend = SQLAlchemyBackend(models.OAuth,
                                               db.session,
                                               user=current_user)

    return app
Esempio n. 8
0
def register_google_blueprint(app):
    # Google
    """
    Registers the google blueprint implemented by flask dance.
    :param app:
    :return:
    """
    client_id = app.config.get('OAUTH_CONFIG')['GOOGLE']['client_id']
    client_secret = app.config.get('OAUTH_CONFIG')['GOOGLE']['client_secret']
    google_blueprint = make_google_blueprint(
        client_id=client_id,
        client_secret=client_secret,
        scope=["openid", "profile", "email"])
    google_blueprint.backend = SQLAlchemyBackend(OAuth,
                                                 db.session,
                                                 user=current_user)
    app.register_blueprint(google_blueprint, url_prefix="/login")

    # create/login local user on successful OAuth login
    @oauth_authorized.connect_via(google_blueprint)
    def google_logged_in(blueprint, token):
        if not token:
            flash("Failed to log in with {name}".format(name=blueprint.name))
            return
        # figure out who the user is
        resp = blueprint.session.get("/oauth2/v2/userinfo")
        if resp.ok:
            username = resp.json()["email"]
            query = User.query.filter_by(username=username)
            try:
                user = query.one()
            except NoResultFound:
                # create a user
                user = User()
                user.username = username
                user.save()
            login_user(user)
            flash("Successfully signed in with Google", "success")
        else:
            msg = "Failed to fetch user info from {name}".format(
                name=blueprint.name)
            flash(msg, category="error")
Esempio n. 9
0
    def instantiate(cls, app):
        """Instantiate shared data"""
        cls.db = SQLAlchemy()
        importlib.import_module('src.models.Action')
        importlib.import_module('src.models.Answer')
        importlib.import_module('src.models.Application')
        OAuth = importlib.import_module('src.models.OAuth').OAuth
        importlib.import_module('src.models.Question')
        importlib.import_module('src.models.Settings')
        importlib.import_module('src.models.User')
        cls.db.init_app(app)
        with app.app_context():
            cls.db.create_all()

        cls.google = make_google_blueprint(client_id=app.config.get('GOOGLE_CLIENT_ID'),
                                           client_secret=app.config.get('GOOGLE_CLIENT_SECRET'),
                                           scope=app.config.get('GOOGLE_SCOPES'))
        cls.google.backend = SQLAlchemyBackend(OAuth, cls.db.session, user=current_user)
        app.register_blueprint(cls.google)

        cls.login_manager = LoginManager()
        cls.login_manager.init_app(app)
        cls.login_manager.login_view = 'google.login'
        cls.login_manager.session_protection = 'strong'
Esempio n. 10
0
                                                  **kwargs)
        self.last_response = resp
        if resp.status_code == 403 and resp.headers.get(
                "X-RateLimit-Remaining"):
            rl_remaining = int(resp.headers["X-RateLimit-Remaining"])
            if rl_remaining < 1:
                raise RateLimited(response=resp)
        return resp


github_bp = make_github_blueprint(
    scope="admin:repo_hook",
    redirect_to="ui.index",
    session_class=GithubSession,
)
github_bp.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)


@oauth_authorized.connect_via(github_bp)
def github_logged_in(blueprint, token):
    if not token:
        flash("Failed to log in with Github")
    if "error_reason" in token:
        msg = "Access denied. Reason={reason} error={error}".format(
            reason=request.args["error_reason"],
            error=request.args["error_description"],
        )
        flash(msg)
    else:
        # figure out who the user is
        try:
Esempio n. 11
0
def google_auth(app):
    """ Hook up google oauth authentication """
    app.register_blueprint(blueprint, url_prefix='/login')
    blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
Esempio n. 12
0
from flask_dance.contrib.jira import make_jira_blueprint
from flask_dance.consumer import oauth_authorized, oauth_error
from flask_dance.consumer.backend.sqla import SQLAlchemyBackend
from openedx_webhooks import db
from openedx_webhooks.models import OAuth

## JIRA ##

jira_bp = make_jira_blueprint(
    # this *should* pick up the client_key and rsa_key from app.config,
    # but it doesn't seem to be doing so... :(
    consumer_key=os.environ.get("JIRA_OAUTH_CONSUMER_KEY"),
    rsa_key=os.environ.get("JIRA_OAUTH_RSA_KEY"),
    # these are actually necessary
    base_url="https://openedx.atlassian.net",
    backend=SQLAlchemyBackend(OAuth, db.session),
)


@oauth_authorized.connect_via(jira_bp)
def jira_logged_in(blueprint, token):
    if token:
        flash("Successfully signed in with JIRA")
    else:
        flash("You denied the request to sign in with JIRA")


@oauth_error.connect_via(jira_bp)
def jira_error(blueprint, message, response=None):
    flash(message, category="error")
Esempio n. 13
0
def authinit(app):
    userauth = Blueprint('userauth', __name__)

    google_blueprint = make_google_blueprint(
        client_id=app.config['globalConfig'].Config.get(
            "OAuth", "GOOGLE_CLIENT_ID"),
        client_secret=app.config['globalConfig'].Config.get(
            "OAuth", "GOOGLE_CLIENT_SECRET"),
        scope=[  #"https://www.googleapis.com/auth/plus.me",
            "https://www.googleapis.com/auth/userinfo.email"
        ],
        offline=True)

    google_blueprint.backend = SQLAlchemyBackend(OAuth,
                                                 db.session,
                                                 user=current_user,
                                                 user_required=True)

    user_manager = UserManager(app, db, Member)
    user_manager.USER_ENABLE_AUTH0 = True
    user_manager.unauthenticated_view = our_login
    login_manager = LoginManager()
    login_manager.login_view = "google.login"
    login_manager.init_app(app)
    login_manager.anonymous_user = AnonymousMember

    @login_manager.user_loader
    def load_user(user_id):
        if not user_id.lower().endswith("@makeitlabs.com"):
            logger.error("User {0} invalid for login".format(user_id))
            return None
        mid = user_id.split("@")[0]
        mr = Member.query.filter(Member.member == mid).one_or_none()
        if not mr:
            logger.error("User {0} Found no member record".format(user_id))
        logger.debug("User {0} loaded".format(user_id))
        return mr
        #return Member.get(user_id)

    @userauth.route("/google_login")
    def google_login():
        if not google.authorized:
            logger.debug("Not google authorized")
            session['next_url'] = request.args.get('next')
            return redirect(url_for("google.login"))
        resp = google.get(SCOPE)
        assert resp.ok, resp.text
        return resp.text

    @oauth_authorized.connect_via(google_blueprint)
    def google_logged_in(blueprint, token):
        resp = google.get("/oauth2/v2/userinfo")
        #print "RESP",dir(resp)
        #print "HEADERS",resp.headers
        #print "REASON",resp.reason
        #print "TEXT",resp.text
        #print "NEXT",resp.next
        #print "LINKS",resp.links
        #print "URL",resp.url
        #print "IS_REDIRECT",resp.is_redirect
        if resp.ok:
            account_info_json = resp.json()
            email = account_info_json['email']
            member = email.split("@")[0]
            logger.debug("Google auth RESP for {0} {1}".format(email, member))
            if not email.endswith("@makeitlabs.com"):
                flash(
                    "Not a MakeIt Labs account - You must log in with your @makeitlabs.com email address",
                    'warning')
                logger.error("Not a MakeIt Labs account " + str(email))
                return redirect(url_for('empty'))
            #query = Member.query.filter_by(Member.member.ilike(member))
            #if not query:
            query = Member.query.filter(Member.email.ilike(email))

            try:
                user = query.all()
                if len(user) > 1:
                    flash(
                        "Error - Multiple accounts with same email - please seek assistance",
                        'warning')
                    logger.error("%s has multiple account (GUI Login)" % email)
                    return redirect(url_for('empty'))

                if len(user) == 0:
                    flash("Error - No account found - please seek assistance",
                          'warning')
                    logger.error("No account matching %s for GUI login" %
                                 email)
                    return redirect(url_for('empty'))

                user = user[0]
                sub = quickSubscriptionCheck(member_id=user.id)
                #print "UserID %s SUB IS %s" % (user.id,sub)
                if sub == "Active" or sub == "Grace Period":
                    if (UserRoles.query.filter(
                            UserRoles.member_id == user.id).count() >= 1):
                        login_user(user, remember=True)
                        flash("Welcome!")
                        return redirect(url_for('index'))
                    logintype = app.config['globalConfig'].Config.get(
                        'General', 'Logins')
                    if logintype == "resource":
                        if (AccessByMember.query.filter(
                                AccessByMember.member_id == user.id,
                                AccessByMember.level >=
                                AccessByMember.LEVEL_TRAINER).count() == 0):
                            flash("Only resource managers may log in")
                            logger.error("Only resource managers may log in " +
                                         str(email))
                        else:
                            login_user(user, remember=True)
                    else:
                        flash("Welcome!")
                        login_user(user, remember=True)
                        return redirect(url_for('index'))
                else:
                    flash("Login Denied - " + str(sub), 'danger')
                    logger.error("Login Denied - " + str(email) + " is " +
                                 str(sub))
                return redirect(url_for('empty'))
            except NoResultFound:
                flash(
                    "Email adddress " + str(email) +
                    " not found in member database", "warning")
                logger.error("Email adddress " + str(email) +
                             " not found in member database")
                return redirect(url_for('empty'))
        else:
            logger.error("Google auth RESP is NOT okay")

    @userauth.route('/google_logout')
    def google_logout():
        """Revokes token and empties session."""
        if google.authorized:
            try:
                google.get(
                    'https://accounts.google.com/o/oauth2/revoke',
                    params={'token': google.token['access_token']},
                )
            except InvalidClientIdError:  # token expiration
                del google.token
                flash("OAuth error: Invalid Client ID", 'danger')
                redirect(url_for('main.index'))
        session.clear()
        logout_user()
        return redirect(url_for('main.index'))

    app.register_blueprint(google_blueprint, url_prefix="/google_login")
Esempio n. 14
0
# ----------------------------------------------------------------------------------------------- #
# -------------------------------------- Database setup ----------------------------------------- #
db = SQLAlchemy(app)


class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(250), unique=True)


class OAuth(OAuthConsumerMixin, db.Model):
    user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    user = db.relationship(User)


GITHUB_BLUEPRINT.backend = SQLAlchemyBackend(
    OAuth, db.session, user=current_user, user_required=False)  ##in_production
# GITHUB_BLUEPRINT.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
# ----------------------------------------------------------------------------------------------- #

# ----------------------------------------------------------------------------------------------- #
# --------------------------------- Setting up login manager ------------------------------------ #
login_manager = LoginManager(app)


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


# ----------------------------------------------------------------------------------------------- #
Esempio n. 15
0
    user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    user = db.relationship(User)


class UserSchema(ma.ModelSchema):
    class Meta:
        model = User


class TodoSchema(ma.ModelSchema):
    class Meta:
        model = Todo


twitter_blueprint.backend = SQLAlchemyBackend(OAuth,
                                              db.session,
                                              user=current_user,
                                              user_required=False)


@app.route('/twitter')
def twitter_login():

    if not twitter.authorized:
        print('\x1b[6;30;42m' + 'sdsdsds' + '\x1b[0m')
        return redirect(url_for('twitter.login'))

    account_info = twitter.get('account/settings.json')
    account_info_json = account_info.json()

    return '<h1>Your Twitter name is @{}'.format(
        account_info_json['screen_name'])
Esempio n. 16
0
from flask_login import UserMixin, current_user
from flask_dance.consumer.backend.sqla import OAuthConsumerMixin, SQLAlchemyBackend
from oauth_app import db, login_manager, bp_github, bp_google, bp_twitter

@login_manager.user_loader
def load_user(id):
    return User.query.get(int(id))

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(256), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)

class OAuth(OAuthConsumerMixin, db.Model):
    provider_user_id = db.Column(db.String(256), unique=True)
    user_id = db.Column(db.Integer, db.ForeignKey(User.id))
    user = db.relationship(User)

# setup SQLAlchemy backend
bp_github.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
bp_google.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
bp_twitter.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
Esempio n. 17
0
        db.session.add(owner)
        db.session.add(transaction)
        db.session.commit()
        return transaction

class Transaction(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    item = db.Column(db.String)
    amount = db.Column(db.Integer)
    price = db.Column(db.Integer)
    timestamp = db.Column(db.DateTime)
    ownerId = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False)
    owner = db.relationship(User, foreign_keys=(ownerId,))
    targetId = db.Column(db.Integer, db.ForeignKey(User.id))
    target = db.relationship(User, foreign_keys=(targetId,))

    def __repr__(self):
        return '<Transaction {0.id} by {0.ownerId}: {0.amount} {0.item} for {0.price} per pcs, {0.timestamp}>'.format(self)

    @classmethod
    def fromOffer(cls, offer):
        result = cls()
        for key in ('item', 'amount', 'price', 'ownerId', 'targetId'):
            val = getattr(offer, key)
            setattr(result, key, val)
        result.timestamp = datetime.now()
        return result

# TODO: use cache as per https://flask-dance.readthedocs.io/en/latest/backends.html#sqlalchemy
danceAlchemyBackend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
Esempio n. 18
0
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_dance.consumer.backend.sqla import SQLAlchemyBackend
from flask_dance.contrib.github import make_github_blueprint
from flask_login import LoginManager
from werkzeug.contrib.fixers import ProxyFix


app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app)
app.config.from_object(Config)

db = SQLAlchemy(app)
migrate = Migrate(app, db)


github_blueprint = make_github_blueprint(
    client_id="674925257692ed46a38b",
    client_secret="319fb87ac542c68085927440429a968f0bf55dbf",
)

app.register_blueprint(github_blueprint, url_prefix="/login")

login_manager = LoginManager()
login_manager.init_app(app)

from app import routes, models

github_blueprint.backend = SQLAlchemyBackend(models.OAuth, db.session)
Esempio n. 19
0
def test_sqla_load_token_for_user(app, db, blueprint, request):

    class User(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80))

    class OAuth(db.Model, OAuthConsumerMixin):
        user_id = db.Column(db.Integer, db.ForeignKey(User.id))
        user = db.relationship(User)

    db.create_all()
    def done():
        db.session.remove()
        db.drop_all()
    request.addfinalizer(done)

    # set token storage
    blueprint.backend = SQLAlchemyBackend(OAuth, db.session)

    # make users and OAuth tokens for several people
    alice = User(name="Alice")
    alice_token = {"access_token": "alice123", "token_type": "bearer"}
    alice_oauth = OAuth(user=alice, token=alice_token, provider="test-service")
    bob = User(name="Bob")
    bob_token = {"access_token": "bob456", "token_type": "bearer"}
    bob_oauth = OAuth(user=bob, token=bob_token, provider="test-service")
    sue = User(name="Sue")
    sue_token = {"access_token": "sue789", "token_type": "bearer"}
    sue_oauth = OAuth(user=sue, token=sue_token, provider="test-service")
    db.session.add_all([alice, bob, sue, alice_oauth, bob_oauth, sue_oauth])
    db.session.commit()

    # by default, we should not have a token for anyone
    sess = blueprint.session
    assert not sess.token
    assert not blueprint.token

    # load token for various users
    blueprint.config["user"] = alice
    assert sess.token == alice_token
    assert blueprint.token == alice_token

    blueprint.config["user"] = bob
    assert sess.token == bob_token
    assert blueprint.token == bob_token

    blueprint.config["user"] = alice
    assert sess.token == alice_token
    assert blueprint.token == alice_token

    blueprint.config["user"] = sue
    assert sess.token == sue_token
    assert blueprint.token == sue_token

    # load for user ID as well
    del blueprint.config["user"]
    blueprint.config["user_id"] = bob.id
    assert sess.token == bob_token
    assert blueprint.token == bob_token

    # try deleting user tokens
    del blueprint.token
    assert sess.token == None
    assert blueprint.token == None

    # shouldn't affect alice's token
    blueprint.config["user_id"] = alice.id
    assert sess.token == alice_token
    assert blueprint.token == alice_token
Esempio n. 20
0
    submit = SubmitField('Update')


# setup login manager
login_manager = LoginManager(app)
login_manager.login_view = 'github.login'
login_manager.login_message_category = 'info'


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


# setup SQLAlchemy backend
blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)


# create/login local user on successful OAuth login
# the following 2 functions are taken from
# the homepage of flask-dance extention
# with some edits to fit the project
@oauth_authorized.connect_via(blueprint)
def github_logged_in(blueprint, token):
    if not token:
        flash("Failed to log in with GitHub.", category="error")
        return False

    resp = blueprint.session.get("/user")
    if not resp.ok:
        msg = "Failed to fetch user info from GitHub."
Esempio n. 21
0
google_blueprint = make_google_blueprint(
    client_id=app.config.get('GOOGLE_ID'),
    client_secret=app.config.get('GOOGLE_SECRET'),
    scope=["profile", "email"])

twitter_blueprint = make_twitter_blueprint(
    api_key=app.config.get('TWITTER_API_KEY'),
    api_secret=app.config.get('TWITTER_API_SECRET'))

facebook_blueprint = make_facebook_blueprint(
    client_id=app.config.get('FACEBOOK_APP_ID'),
    client_secret=app.config.get('FACEBOOK_APP_SECRET'))

# setup SQLAlchemy backend
github_blueprint.backend = SQLAlchemyBackend(models.OAuth,
                                             db.session,
                                             user=current_user)
google_blueprint.backend = SQLAlchemyBackend(models.OAuth,
                                             db.session,
                                             user=current_user)
twitter_blueprint.backend = SQLAlchemyBackend(models.OAuth,
                                              db.session,
                                              user=current_user,
                                              user_required=False)
facebook_blueprint.backend = SQLAlchemyBackend(models.OAuth,
                                               db.session,
                                               user=current_user)


# create/login local user on successful OAuth login
@oauth_authorized.connect_via(github_blueprint)
Esempio n. 22
0
def test_sqla_flask_login_preload_logged_in_user(app, db, blueprint, request):
    # need a URL to hit, so that tokens will be loaded, but result is irrelevant
    responses.add(
        responses.GET,
        "https://example.com/noop",
    )

    login_manager = LoginManager(app)

    class User(db.Model, UserMixin):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80))

    class OAuth(db.Model, OAuthConsumerMixin):
        user_id = db.Column(db.Integer, db.ForeignKey(User.id))
        user = db.relationship(User)

    blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)

    db.create_all()
    def done():
        db.session.remove()
        db.drop_all()
    request.addfinalizer(done)

    # create some users, and tokens for some of them
    alice = User(name="Alice")
    alice_token = {"access_token": "alice123", "token_type": "bearer"}
    alice_oauth = OAuth(user=alice, token=alice_token, provider="test-service")
    bob = User(name="Bob")
    bob_token = {"access_token": "bob456", "token_type": "bearer"}
    bob_oauth = OAuth(user=bob, token=bob_token, provider="test-service")
    chuck = User(name="Chuck")
    # chuck doesn't get a token
    db.session.add_all([alice, alice_oauth, bob, bob_oauth, chuck])
    db.session.commit()

    # configure login manager
    @login_manager.user_loader
    def load_user(userid):
        return User.query.get(userid)

    # create a simple view
    @app.route("/")
    def index():
        return "success"

    with app.test_request_context("/"):
        login_user(alice)
        # hit /noop to load tokens
        blueprint.session.get("/noop")
        # now the flask-dance session should have Alice's token loaded
        assert blueprint.session.token == alice_token

    with app.test_request_context("/"):
        # set bob as the logged in user
        login_user(bob)
        # hit /noop to load tokens
        blueprint.session.get("/noop")
        # now the flask-dance session should have Bob's token loaded
        assert blueprint.session.token == bob_token

    with app.test_request_context("/"):
        # now let's try chuck
        login_user(chuck)
        blueprint.session.get("/noop")
        assert blueprint.session.token == None

    with app.test_request_context("/"):
        # no one is logged in -- this is an anonymous user
        logout_user()
        blueprint.session.get("/noop")
        assert blueprint.session.token == None
Esempio n. 23
0
def test_sqla_flask_login_anon_to_authed(app, db, blueprint, request):
    login_manager = LoginManager(app)

    class User(db.Model, UserMixin):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80))

    class OAuth(db.Model, OAuthConsumerMixin):
        user_id = db.Column(db.Integer, db.ForeignKey(User.id))
        user = db.relationship(User)

    blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)

    db.create_all()
    def done():
        db.session.remove()
        db.drop_all()
    request.addfinalizer(done)

    # configure login manager
    @login_manager.user_loader
    def load_user(userid):
        return User.query.get(userid)

    # create a user object when OAuth succeeds
    def logged_in(sender, token):
        assert token
        assert blueprint == sender
        resp = sender.session.get("/user")
        user = User(name=resp.json()["name"])
        login_user(user)
        db.session.add(user)
        db.session.commit()
        flask.flash("Signed in successfully")

    oauth_authorized.connect(logged_in, blueprint)
    request.addfinalizer(lambda: oauth_authorized.disconnect(logged_in, blueprint))

    # mock out the `/user` API call
    responses.add(
        responses.GET,
        "https://example.com/user",
        body='{"name":"josephine"}',
    )

    with record_queries(db.engine) as queries:
        with app.test_client() as client:
            with client.session_transaction() as sess:
                sess["test-service_oauth_state"] = "random-string"
            # make the request
            resp = client.get(
                "/login/test-service/authorized?code=secret-code&state=random-string",
                base_url="https://a.b.c",
            )
            # check that we redirected the client
            assert resp.status_code == 302
            assert resp.headers["Location"] == "https://a.b.c/oauth_done"

    assert len(queries) == 5

    # check the database
    users = User.query.all()
    assert len(users) == 1
    user = users[0]
    assert user.name == "josephine"

    authorizations = OAuth.query.all()
    assert len(authorizations) == 1
    oauth = authorizations[0]
    assert oauth.provider == "test-service"
    assert oauth.token == {
        "access_token": "foobar",
        "token_type": "bearer",
        "scope": [""],
    }
    assert oauth.user_id == user.id
Esempio n. 24
0
def test_sqla_flask_login(app, db, blueprint, request):
    login_manager = LoginManager(app)

    class User(db.Model, UserMixin):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80))

    class OAuth(db.Model, OAuthConsumerMixin):
        user_id = db.Column(db.Integer, db.ForeignKey(User.id))
        user = db.relationship(User)

    blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)

    db.create_all()
    def done():
        db.session.remove()
        db.drop_all()
    request.addfinalizer(done)

    # create some users
    u1 = User(name="Alice")
    u2 = User(name="Bob")
    u3 = User(name="Chuck")
    db.session.add_all([u1, u2, u3])
    db.session.commit()

    # configure login manager
    @login_manager.user_loader
    def load_user(userid):
        return User.query.get(userid)

    with record_queries(db.engine) as queries:
        with app.test_client() as client:
            # reset the session before the request
            with client.session_transaction() as sess:
                sess["test-service_oauth_state"] = "random-string"
                # set alice as the logged in user
                sess["user_id"] = u1.id
            # make the request
            resp = client.get(
                "/login/test-service/authorized?code=secret-code&state=random-string",
                base_url="https://a.b.c",
            )
            # check that we redirected the client
            assert resp.status_code == 302
            assert resp.headers["Location"] == "https://a.b.c/oauth_done"

    assert len(queries) == 4

    # lets do it again, with Bob as the logged in user -- he gets a different token
    responses.reset()
    responses.add(
        responses.POST,
        "https://example.com/oauth/access_token",
        body='{"access_token":"abcdef","token_type":"bearer","scope":"bob"}',
    )
    with record_queries(db.engine) as queries:
        with app.test_client() as client:
            # reset the session before the request
            with client.session_transaction() as sess:
                sess["test-service_oauth_state"] = "random-string"
                # set bob as the logged in user
                sess["user_id"] = u2.id
            # make the request
            resp = client.get(
                "/login/test-service/authorized?code=secret-code&state=random-string",
                base_url="https://a.b.c",
            )
            # check that we redirected the client
            assert resp.status_code == 302
            assert resp.headers["Location"] == "https://a.b.c/oauth_done"

    assert len(queries) == 4

    # check the database
    authorizations = OAuth.query.all()
    assert len(authorizations) == 2
    u1_oauth = OAuth.query.filter_by(user=u1).one()
    assert u1_oauth.provider == "test-service"
    assert u1_oauth.token == {
        "access_token": "foobar",
        "token_type": "bearer",
        "scope": [""],
    }
    u2_oauth = OAuth.query.filter_by(user=u2).one()
    assert u2_oauth.provider == "test-service"
    assert u2_oauth.token == {
        "access_token": "abcdef",
        "token_type": "bearer",
        "scope": ["bob"],
    }
    u3_oauth = OAuth.query.filter_by(user=u3).all()
    assert len(u3_oauth) == 0
Esempio n. 25
0
    return render_template('user_posts.html', posts=posts, user=user)


userauth = Blueprint('userauth', __name__)

app.secret_key = app.config['GOOGLE_OAUTH_CLIENT_SECRET']

google_blueprint = make_google_blueprint(
    client_id=app.config['GOOGLE_OAUTH_CLIENT_ID'],
    client_secret=app.secret_key,
    scope=app.config['GOOGLE_OAUTH_CLIENT_SCOPE'],
    offline=True
    )

google_blueprint.backend = SQLAlchemyBackend(UserAuth, db.session,
                                             user=current_user,
                                             user_required=False)

app.register_blueprint(google_blueprint, url_prefix="/google_login")


@userauth.route("/google_login")
def google_login():
    """redirect to Google to initiate oAuth2.0 dance"""
    if not google.authorized:
        return redirect(url_for("google.login"))
    resp = google.get("/oauth2/v2/userinfo")
    assert resp.ok, resp.text
    return resp.text

Esempio n. 26
0
def create_app(config_name):
    from app.models import BlogPost, User, Role, OAuth
    from app.resources import Post, PostList, UserResource, UserList, Like

    app = Flask(__name__, instance_relative_config=True)
    app.config.from_object(app_config[config_name])
    app.config.from_pyfile("config.py")
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
    app.config["SECRET_KEY"] = "super-secret"

    db.init_app(app)
    # Setup Flask Migration
    migrate = Migrate(app, db)

    # Setup Flask restful API
    api = Api(app)
    api.add_resource(Post, "/posts/<int:post_id>")
    api.add_resource(PostList, "/posts")
    api.add_resource(UserResource, "/users/<int:user_id>")
    api.add_resource(UserList, "/users")
    api.add_resource(Like, "/posts/<int:post_id>/like")

    # Setup Flask-Security
    user_datastore = SQLAlchemyUserDatastore(db, User, Role)
    security = Security(app, user_datastore)

    login_manager = LoginManager(app)
    login_manager.login_view = "my_login"

    @login_manager.user_loader
    def load_user(user_id):
        return User.query.get(int(user_id))

    google_blueprint = make_google_blueprint(
        client_id=app.config['GOOGLE_API_CLIENT_ID'],
        client_secret=app.config['GOOGLE_API_CLIENT_ID'],
        scope=["profile", "email"]
    )
    google_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
    google_blueprint.backend.user_required = False
    app.register_blueprint(google_blueprint, url_prefix="/google_login")

    @app.route("/google")
    def google_login():
        if not google.authorized:
            return redirect(url_for("google.login"))
        account_info = google.get("/oauth2/v2/userinfo")
        account_info_json = account_info.json()
        app.logger.info("User with email %s logged in successfully" % account_info_json['email'])
        user = current_user
        response = jsonify({
            "status": "ok",
            "message": "User %s has been logged in successfully" % account_info_json['email'],
            "data": {
                "user": {
                    "id": user.id,
                    "email": user.email,
                    "registration_completed": user.registration_completed(),
                    "type": user.type.code,
                    "phone": user.phone,
                    "name": user.name,
                    "occupation": user.occupation
                }
            }
        })
        response.status_code = 200
        return response

    @oauth_authorized.connect_via(google_blueprint)
    def google_logged_in(blueprint, token):
        if not token:
            app.logger.error("Failed to log in with Google.")
            return False

        account_info = blueprint.session.get("/oauth2/v2/userinfo")
        if not account_info.ok:
            app.logger.error("Failed to fetch user info from Google.")
            return False

        else:
            account_info_json = account_info.json()
            email = account_info_json["email"]

            query = User.query.filter_by(email=email)

            try:
                user = query.one()
                # If user is google user we log him in, if not we return False and redirect him to Facebook login page.
                if user.type == "facebook":
                    app.logger.info("User with email %s trying to sign in using Google account" % (email))
                    response = jsonify({
                        "status": "error",
                        "message": "The user with the same email has been registered with a Facebook account."
                                   " Please use Facebook to login!",
                        "data": {
                            "facebook_login_url": url_for("facebook_login"),
                            "google_login_url": url_for("google_login"),
                        }
                    })
                    response.status_code = 200
                    return response
            except NoResultFound:
                # If no user with existing email found, we create new user, mark him as Google user
                user = User(email=email, type="google", active=True)
                db.session.add(user)
                db.session.commit()

            login_user(user)
            app.logger.info("User with email %s logged in successfully" % account_info_json['email'])
            user = current_user
            response = jsonify({
                "status": "ok",
                "message": "User %s has been logged in successfully" % account_info_json['email'],
                "data": {
                    "user": {
                        "id": user.id,
                        "email": user.email,
                        "registration_completed": user.registration_completed(),
                        "type": user.type.code,
                        "phone": user.phone,
                        "name": user.name,
                        "occupation": user.occupation
                    }
                }
            })
            response.status_code = 200
            return response

    facebook_blueprint = make_facebook_blueprint(
        client_id=app.config['FACEBOOK_API_CLIENT_ID'],
        client_secret=app.config['FACEBOOK_API_CLIENT_SECRETE'],
        scope=["public_profile", "email"]
    )
    facebook_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
    facebook_blueprint.backend.user_required = False
    app.register_blueprint(facebook_blueprint, url_prefix="/facebook_login")

    @app.route("/facebook")
    def facebook_login():
        if not facebook.authorized:
            return redirect(url_for("facebook.login"))
        account_info = facebook.get("/me?fields=id,name,email")
        account_info_json = account_info.json()
        app.logger.info("User with email %s logged in successfully" % account_info_json['email'])
        user = current_user
        response = jsonify({
            "status": "ok",
            "message": "User %s has been logged in successfully" % account_info_json['email'],
            "data": {
                "user": {
                    "id": user.id,
                    "email": user.email,
                    "registration_completed": user.registration_completed(),
                    "type": user.type.code,
                    "phone": user.phone,
                    "name": user.name,
                    "occupation": user.occupation
                }
            }
        })
        response.status_code = 200
        return response

    @oauth_authorized.connect_via(facebook_blueprint)
    def facebook_logged_in(blueprint, token):
        if not token:
            app.logger.error("Failed to log in with Facebook.")
            return False

        account_info = blueprint.session.get("/me?fields=id,name,email")
        if not account_info.ok:
            app.logger.error("Failed to fetch user info from Facebook.")
            return False

        else:
            account_info_json = account_info.json()
            email = account_info_json["email"]

            query = User.query.filter_by(email=email)

            try:
                user = query.one()
                # If user is facebook user we log him in, if not we return False and return error response.
                if user.type == "google":
                    app.logger.info("User with email %s trying to sign in using Facebook account" % (email))
                    response = jsonify({
                        "status": "error",
                        "message": "The user with the same email has been registered with a Google account."
                                   " Please use Google to login!",
                        "data": {
                            "facebook_login_url": url_for("facebook_login"),
                            "google_login_url": url_for("google_login"),
                        }
                    })
                    response.status_code = 200
                    return response

            except NoResultFound:
                # If no user with existing email found, we create new user, mark him as Facebook user
                user = User(email=email, type="facebook", active=True)
                db.session.add(user)
                db.session.commit()
        login_user(user)
        app.logger.info("User with email %s logged in successfully" % account_info_json['email'])
        user = current_user
        response = jsonify({
            "status": "ok",
            "message": "User %s has been logged in successfully" % account_info_json['email'],
            "data": {
                "user": {
                    "id": user.id,
                    "email": user.email,
                    "registration_completed": user.registration_completed(),
                    "type": user.type.code,
                    "phone": user.phone,
                    "name": user.name,
                    "occupation": user.occupation
                }
            }
        })
        response.status_code = 200
        return response

    # Views
    @app.route("/")
    @login_required
    def home():
        posts = BlogPost.get_all()
        results = []

        for post in posts:
            obj = {
                "id": post.id,
                "title": post.title,
                "content": post.content,
                "date_created": post.date_created,
                "date_modified": post.date_modified
            }
            results.append(obj)
        response = jsonify(results)
        response.status_code = 200
        return response

    @app.route("/my_login")
    def my_login():
        response = jsonify({
            "status": "error",
            "message": "Login Required",
            "data": {

                "facebook_login_url": url_for("facebook_login"),
                "google_login_url": url_for("google_login"),
            }
        })
        response.status_code = 403
        return response

    @app.route("/logout")
    @login_required
    def logout():
        logout_user()
        return redirect(url_for("home"))

    return app
Esempio n. 27
0
from instance.settings import TWITTER_API_KEY, TWITTER_API_SECRET
from winejournal.data_models.oauth import Oauth
from winejournal.data_models.tastingnotes import TastingNote
from winejournal.data_models.users import User
from winejournal.data_models.wines import Wine
from winejournal.extensions import db
from winejournal.extensions import login_manager

staticPages = Blueprint('static_pages', __name__, template_folder='templates')

twitter_blueprint = make_twitter_blueprint(
    api_key=TWITTER_API_KEY,
    api_secret=TWITTER_API_SECRET)

twitter_blueprint.backend = SQLAlchemyBackend(
    Oauth, db.session,
    user=current_user,
    user_required=False)

google_blueprint = make_google_blueprint(
    client_id=GOOGLE_CLIENT_ID,
    client_secret=GOOGLE_CLIENT_SECRETS,
    scope=['profile', 'email'])

google_blueprint.backend = SQLAlchemyBackend(
    Oauth, db.session,
    user=current_user,
    user_required=False)

facebook_blueprint = make_facebook_blueprint(
    client_id=FACEBOOK_OAUTH_CLIENT_ID,
    client_secret=FACEBOOK_OAUTH_CLIENT_SECRET,
Esempio n. 28
0
# Initialize Flask-Dance blueprints
google_blueprint = make_google_blueprint(
    client_id=app.config.get('GOOGLE_CLIENT_ID'),
    client_secret=app.config.get('GOOGLE_CLIENT_SECRET'),
    scope=["profile", "email"],
    redirect_url="/token/google")

facebook_blueprint = make_facebook_blueprint(
    client_id=app.config.get('FACEBOOK_APP_ID'),
    client_secret=app.config.get('FACEBOOK_APP_SECRET'),
    scope=["public_profile", "email"],
    redirect_url="/token/facebook")

# Setup sqlalchemy backend for blueprints
google_blueprint.backend = SQLAlchemyBackend(OAuth,
                                             db.session,
                                             user=current_user)

facebook_blueprint.backend = SQLAlchemyBackend(OAuth,
                                               db.session,
                                               user=current_user)


@oauth_authorized.connect_via(google_blueprint)
def google_logged_in(blueprint, token):
    """Log in user on successful Google authorization."""
    # If user doesn't have valid oauth token, flash error
    if not token:
        flash("Failed to log in {name}".format(name=blueprint.name))
        return
Esempio n. 29
0
from flask_dance.consumer import oauth_authorized, oauth_error
from flask_dance.consumer.backend.sqla import SQLAlchemyBackend
from flask_dance.contrib.facebook import make_facebook_blueprint
from flask_dance.contrib.github import make_github_blueprint
from flask_dance.contrib.twitter import make_twitter_blueprint
from flask_login import current_user

from project.utils.login import general_logged_in, general_error

from project.models import OAuth, db

facebook_blueprint = make_facebook_blueprint(
    backend=SQLAlchemyBackend(OAuth, db.session, user=current_user, user_required=False)
)

twitter_blueprint = make_twitter_blueprint(
    backend=SQLAlchemyBackend(OAuth, db.session, user=current_user, user_required=False)
)

github_blueprint = make_github_blueprint(
    backend=SQLAlchemyBackend(OAuth, db.session, user=current_user, user_required=False)
)


@oauth_authorized.connect_via(twitter_blueprint)
def twitter_logged_in(blueprint, token):
    return general_logged_in(blueprint, token, 'account/settings.json')


@oauth_error.connect_via(twitter_blueprint)
def twitter_error(blueprint, error, error_description=None, error_uri=None):
Esempio n. 30
0
    'binarne',
    'soli',
    'baze',
    'kisline',
    'kh',
    'hs',
    'vislice',
}

login_manager = LoginManager(app)
login_manager.init_app(app)
login_manager.login_view = 'login'
login_manager.login_message = u"Za dostop do te strani se morate prijaviti!"
login_manager.login_message_category = "error"

fb.backend = SQLAlchemyBackend(models.OAuth, db.session, user=current_user)


@login_manager.user_loader
def load_user(user_id):
    return models.User.query.get(int(user_id))


@app.context_processor
def utility_processor():
    def its_type(obj):
        return type(obj)

    return dict(type=its_type)