コード例 #1
0
ファイル: app.py プロジェクト: albagon/ny-diner-app
def create_app(test_config=None):
    # Load environment variables from dot env file.
    load_dotenv()

    app = Flask(__name__)
    app.secret_key = os.getenv("AUTH0_CLIENT_SECRET")
    if type(test_config) == dict:
        app.db = setup_db(app, **test_config)
    else:
        app.db = setup_db(app)

    # Allow CORS for all domains on all routes
    CORS(app)

    '''
    Auth0 settings
    '''
    oauth = OAuth(app)

    auth0 = oauth.register(
        'auth0',
        client_id = os.getenv("AUTH0_CLIENT_ID"),
        client_secret = os.getenv("AUTH0_CLIENT_SECRET"),
        api_base_url = 'https://full.eu.auth0.com',
        access_token_url = 'https://full.eu.auth0.com/oauth/token',
        authorize_url = 'https://full.eu.auth0.com/authorize',
        client_kwargs = {
            'scope': 'openid profile email',
        },
    )

    '''
    Auth0 routes
    '''
    # Auth0 redirects the user to this route after they have authenticated.
    @app.route('/callback')
    def callback_handling():
        # Handles response from token endpoint
        auth0.authorize_access_token()
        resp = auth0.get('userinfo')
        userinfo = resp.json()

        # Store the user information in flask session.
        session['jwt_payload'] = userinfo
        session['profile'] = {
            'user_id': userinfo['sub'],
            'name': userinfo['name'],
            'picture': userinfo['picture']
        }
        return redirect('/restaurants')

    # This route uses the Authlib client instance to redirect the user to the login page.
    @app.route('/login')
    def login():
        uri = os.getenv("AUTH0_CALLBACK_URL")
        return auth0.authorize_redirect(redirect_uri=uri)

    # Decorator that checks if the user has authenticated.
    def requires_auth(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            if 'profile' not in session:
                # Redirect to Login page here
                return redirect('/')
            return f(*args, **kwargs)

        return decorated

    # This route renders once the user has logged out.
    @app.route('/')
    def home():
        return render_template('home.html')

    # Log the user out and clear the data from the session.
    @app.route('/logout')
    def logout():
        # Clear session stored data
        session.clear()
        # Redirect user to logout endpoint
        params = {'returnTo': url_for('home', _external=True), 'client_id': os.getenv("AUTH0_CLIENT_ID")}
        return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))

    '''
    ENDPOINTS for Restaurants and Reviews
    '''

    '''
    GET /restaurants
        It requires authentication.
        It should contain only the Restaurant.short() data representation.
        On success, this endpoint returns status code 200 and the list of
        restaurants. On failure, it aborts with a 404 error code.
        This route also returns the user information stored in the Flask session.
    '''
    @app.route('/restaurants')
    @requires_auth
    def get_restaurants():
        try:
            restaurants = Restaurant.query.all()
            restaurants_short = []
            if len(restaurants) != 0:
                any_restaurants = True
                for restaurant in restaurants:
                    restaurants_short.append(restaurant.short())
            return render_template('dashboard.html',
                                       userinfo=session['profile'],
                                       userinfo_pretty=json.dumps(session['jwt_payload'], indent=4),
                                       success=True,
                                       restaurants=restaurants_short)
        except Exception:
            abort(404)

    '''
    GET /restaurants/<id>
        It should be a public endpoint.
        It should contain the Restaurant.long() data representation.
        On success, this endpoint returns status code 200, the restaurant data,
        and a list of reviews on that restaurant.
        On failure, it aborts with a 404 error code.
        This route also returns the user information stored in the Flask session.
    '''
    @app.route('/restaurants/<int:id>')
    @requires_auth
    def get_restaurant(id):
        try:
            restaurant = Restaurant.query.filter(Restaurant.id == id).one_or_none()
            if restaurant != None:
                reviews = Review.query.filter(Review.restaurant_id == id).all()
                if len(reviews) != 0:
                    reviews_format = []
                    for review in reviews:
                        reviews_format.append(review.format())
                else:
                    reviews_format = False
                return render_template('restaurant.html',
                                           success=True,
                                           userinfo=session['profile'],
                                           restaurant=restaurant.long(),
                                           reviews=reviews_format,
                                           form=restaurant.to_form())
        except Exception:
            abort(404)

    '''
    GET /restaurants/<id>/new_reviews
        Renders the template associated with the new_review form.
    '''
    @app.route('/restaurants/<int:id>/new_reviews', methods=['GET'])
    @requires_auth
    def create_review_form(id):
        try:
            restaurant = Restaurant.query.filter(Restaurant.id == id).one_or_none()
            if restaurant != None:
                form = ReviewForm()
                return render_template('forms/new_review.html',
                                         userinfo=session['profile'],
                                         restaurant=restaurant,
                                         form=form)
            else:
                abort(404)
        except Exception:
            abort(404)

    '''
    POST /restaurants/<id>/new_reviews
        Post a new review in db.
    '''
    @app.route('/restaurants/<int:id>/new_reviews', methods=['POST'])
    @requires_auth
    def create_review_submission(id):
        error = False
        body = {}
        try:
            form = request.form
            review = Review(
                restaurant_id = id,
                name = form['name'],
                date = datetime.now(),
                rating = form['rating'],
                comments = form['comments']
            )
            review.insert()
            body['name'] = form['name']
        except:
            error = True
            db.session.rollback()
            print(sys.exc_info())
        finally:
            db.session.close()
        if not error:
            # on successful db insert, flash success
            flash('Thank you ' + body['name'] + ' for your review.', 'success')
        else:
            flash('An error occurred. Review could not be listed.', 'error')
        return redirect('/restaurants/'+str(id)+'/new_reviews')

    '''
    GET /new_restaurants
        Renders the template associated with the new_restaurant form.
    '''
    @app.route('/new_restaurants', methods=['GET'])
    @requires_auth
    def create_restaurant_form():
        try:
            form = RestaurantForm()
            return render_template('forms/new_restaurant.html',
                                     userinfo=session['profile'],
                                     form=form)
        except Exception:
            abort(404)

    '''
    POST /new_restaurants
        Post a new restaurant in db.
    '''
    @app.route('/new_restaurants', methods=['POST'])
    @requires_auth
    def create_restaurant_submission():
        error = False
        try:
            form = RestaurantForm(request.form)
            if form.validate_on_submit():
                op_hours = format_operating_hours(form)
                if op_hours['success']:
                    restaurant = Restaurant(
                        name = form.name.data,
                        borough = form.borough.data,
                        photograph = form.photograph.data,
                        img_description = form.img_description.data,
                        address = form.address.data,
                        latlng = [float(form.lat.data), float(form.lng.data)],
                        cuisine = form.cuisine.data,
                        operating_hours = op_hours['week_hours']
                        )
                    restaurant.insert()
                else:
                    error = True
                    message = 'Wrong formating of operating hours.'
            else:
                error = True
                message = 'The form contains invalid data.'
        except:
            error = True
            message = 'The restaurant could not be listed.'
            db.session.rollback()
            print(sys.exc_info())
        finally:
            db.session.close()
        if not error:
            flash(form.name.data + ' was successfully listed.', 'success')
            return redirect('/new_restaurants')
        else:
            flash('An error occurred. ' + message, 'error')
            return render_template('forms/new_restaurant.html',
                                     userinfo=session['profile'],
                                     form=form)

    '''
    PATCH /restaurants/<id>
        Where <id> is the existing model id.
        It should respond with a 404 error if <id> is not found.
        It should update the corresponding row for <id>
        It should require the 'patch:restaurants' permission.
        It should contain the restaurant.long() data representation.
    '''
    @app.route('/restaurants/<int:id>', methods=['PATCH'])
    @requires_auth
    def update_restaurant(id):
        error = False
        try:
            form = RestaurantForm(request.form)
            restaurant = Restaurant.query.filter(Restaurant.id == id).one_or_none()
            if restaurant != None:
                if form.validate_on_submit():
                    op_hours = format_operating_hours(form)
                    if op_hours['success']:
                        restaurant.name = form.name.data
                        restaurant.borough = form.borough.data
                        restaurant.photograph = form.photograph.data
                        restaurant.img_description = form.img_description.data
                        restaurant.address = form.address.data
                        restaurant.latlng = [float(form.lat.data), float(form.lng.data)]
                        restaurant.cuisine = form.cuisine.data
                        restaurant.operating_hours = op_hours['week_hours']
                        restaurant.update()
                    else:
                        error = True
                        message = 'Wrong formating of operating hours.'
                else:
                    error = True
                    message = 'The form contains invalid data.'
            else:
                abort(404)
        except Exception:
            error = True
            message = 'The restaurant could not be updated.'
            db.session.rollback()
            print(sys.exc_info())
        if not error:
            flash(form.name.data + ' was successfully updated.', 'success')
            return jsonify({
                        "success": True,
                        "restaurant": restaurant.long()
                    })
        else:
            flash('An error occurred. ' + message, 'error')
            if form.errors:
                for field, f_errors in form.errors.items():
                    if f_errors:
                        for error in f_errors:
                            flash(field + ': ' + error, 'error')
            abort(404)

    '''
    DELETE /restaurants/<id>
        Where <id> is the existing model id.
        It should respond with a 404 error if <id> is not found.
        It should delete the corresponding row for <id>
        It should require the 'delete:restaurants' permission.
        Returns status code 200 and json {"success": True, "delete": id,
        "name": restaurant.name} where id is the id of the deleted record or
        appropriate status code indicating reason for failure.
    '''
    @app.route('/restaurants/<int:id>', methods=['DELETE'])
    @requires_auth
    def delete_restaurant(id):
        try:
            restaurant = Restaurant.query.filter(Restaurant.id == id).one_or_none()
            if restaurant != None:
                reviews = Review.query.filter(Review.restaurant_id == id).all()
                if len(reviews) != 0:
                    for review in reviews:
                        review.delete()

                restaurant.delete()
                flash(restaurant.name + ' was successfully deleted.', 'success')
                return jsonify({
                        "success": True,
                        "delete": id,
                        "name": restaurant.name
                    })
        except Exception:
            db.session.rollback()
            print(sys.exc_info())
            flash('An error occurred. The restaurant could not be deleted.', 'error')
        return abort(404)

    # Error handler for 401
    @app.errorhandler(401)
    def unauthorized(error):
        return jsonify({
                        "success": False,
                        "error": 401,
                        "message": "unauthorized"
                        }), 401

    # Error handler for 404
    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
                        "success": False,
                        "error": 404,
                        "message": "resource not found"
                        }), 404

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
                        "success": False,
                        "error": 422,
                        "message": "unprocessable"
                        }), 422

    @app.errorhandler(500)
    def server_error(error):
        return jsonify({
                        "success": False,
                        "error": 500,
                        "message": "internal server error"
                        }), 500

    return app
コード例 #2
0
ファイル: oauth2.py プロジェクト: r202-coe-psu/nokkhum
    return token.to_dict()


def update_token(name, token):
    item = models.OAuth2Token(name=name,
                              user=current_user._get_current_object()).first()
    item.token_type = token.get("token_type", "Bearer")
    item.access_token = token.get("access_token")
    item.refresh_token = token.get("refresh_token")
    item.expires = datetime.datetime.utcfromtimestamp(token.get("expires_at"))

    item.save()
    return item


oauth2_client = OAuth()


def handle_authorize_google(remote, token, user_info):

    if not user_info:
        return redirect(url_for("accounts.login"))

    user = models.User.objects(
        me.Q(username=user_info.get("name"))
        | me.Q(email=user_info.get("email"))).first()
    if not user:
        user = models.User(
            username=user_info.get("name"),
            email=user_info.get("email"),
            first_name=user_info.get("given_name"),
コード例 #3
0
def create_authenticated_app(test_config=None):
    # Create and Configure OKIT Web Designer App
    app = Flask(__name__, instance_relative_config=True)

    # Load Config
    if test_config is None:
        app.config.from_pyfile('config.py', silent=True)
    else:
        app.config.from_mapping(test_config)

    # Ensure if instance folder exists
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    # Add Upload location
    app.config['UPLOADS_FOLDER'] = '/okit/uploads'

    # The secret key must be static to be the same for all gunicorn workers
    app.secret_key = '8980ffsd675747jjjh'
    idcs_metadata_url = app.config[
        'IDCS_API_BASE_URL'] + '/.well-known/openid-configuration'
    oauth = OAuth(app)
    idcs = oauth.register(name='idcs',
                          server_metadata_url=idcs_metadata_url,
                          client_kwargs={'scope': 'openid email profile'})
    if 'OKIT_SERVER_BASE' not in app.config:
        app.config['OKIT_SERVER_BASE'] = 'http://' + socket.getfqdn()

    @app.route('/favicon.ico')
    def favicon():
        return send_from_directory(os.path.join(app.root_path, 'static'),
                                   'favicon.ico',
                                   mimetype='image/vnd.microsoft.icon')

    from . import okitWebDesigner

    # Login Step 1 - Redirect to IDCS
    @okitWebDesigner.bp.route('/login', methods=(['GET', 'POST']))
    def login():
        return idcs.authorize_redirect(app.config['OKIT_SERVER_BASE'] +
                                       url_for('okit.postlogin'))

    # Login Step 2 - Local local token handling
    @okitWebDesigner.bp.route('/postlogin', methods=(['GET', 'POST']))
    def postlogin():
        token = idcs.authorize_access_token()
        userinfo = idcs.parse_id_token(token)
        session['username'] = userinfo['user_displayname']
        session['home_region'] = app.config['OCI_HOME_REGION']
        session['tenant'] = app.config['OCI_TENANT']
        logger.info(f"App Config {app.config}")
        end_session_endpoint = idcs.server_metadata['end_session_endpoint']
        logout_redirect_url = {
            'post_logout_redirect_url':
            app.config['OKIT_SERVER_BASE'] + url_for('okit.postlogout'),
            'id_token_hint':
            token['id_token']
        }
        logout_url = end_session_endpoint + '?post_logout_redirect_url=' + str(
            logout_redirect_url['post_logout_redirect_url']
        ) + '&id_token_hint=' + str(logout_redirect_url['id_token_hint'])
        session['logout'] = logout_url
        return redirect(url_for('okit.designer'), code=302)

    # Logout Step 1 - Handled by IDCS
    # Logout Step 2 - Local cleanup
    @okitWebDesigner.bp.route('/logout', methods=(['GET', 'POST']))
    def logout():
        session.pop('username', None)
        session.pop('logout', None)
        session.pop('tenant', None)
        session.pop('home_region', None)
        return Response(status=200)

    # Logout Step 3 - Local redirect to home page
    @okitWebDesigner.bp.route('/postlogout', methods=(['GET', 'POST']))
    def postlogout():
        session.pop('username', None)
        session.pop('logout', None)
        session.pop('tenant', None)
        session.pop('home_region', None)
        return redirect(url_for('okit.designer'), code=302)

    app.register_blueprint(okitWebDesigner.bp)
    from . import okitPricing
    app.register_blueprint(okitPricing.bp)
    from . import okitOci
    app.register_blueprint(okitOci.bp)
    from . import okitImport
    app.register_blueprint(okitImport.bp)

    @app.route('/')
    def index():
        return login()

    return app
コード例 #4
0
from flask import Blueprint, render_template, redirect, url_for, current_app, request, flash
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import LoginManager, login_user, logout_user, login_required
from authlib.integrations.flask_client import OAuth
from form import LoginForm, SignupForm
from db import User, db, Category, createTutorial
from config import OAUTH_CONFIG

oauth = OAuth(current_app)
bp = Blueprint("auth", __name__, url_prefix="/auth")

login_manager = LoginManager()
login_manager.init_app(current_app)
login_manager.login_view = 'auth.login'

error_msgs = {
    "duplicate_user": "******",
    "duplicate_email": "이미 존재하는 이메일입니다. 다른 이메일을 사용하세요.",
    "user_not_exist": "존재하지 않는 이름입니다. 회원가입을 먼저 해주세요.",
    "wrong_password": "******"
}

google = oauth.register(
    name='google',
    client_id=OAUTH_CONFIG['client_id'],
    client_secret=OAUTH_CONFIG['client_secret'],
    access_token_url='https://accounts.google.com/o/oauth2/token',
    access_token_params=None,
    authorize_url='https://accounts.google.com/o/oauth2/auth',
    authorize_params=None,
    api_base_url='https://www.googleapis.com/oauth2/v1/',
コード例 #5
0
 def test_create_client(self):
     app = Flask(__name__)
     oauth = OAuth(app)
     self.assertIsNone(oauth.create_client('dev'))
     oauth.register('dev', client_id='dev')
     self.assertIsNotNone(oauth.create_client('dev'))
コード例 #6
0
ファイル: Login.py プロジェクト: KAAzadi/Public
class Login(object):
    app = Flask(__name__)

    oauth = OAuth(app)

    auth0 = oauth.register(
        name='google',
        client_id='YOUR_CLIENT_ID',
        client_secret='YOUR_CLIENT_SECRET',
        access_token_url='https://accounts.google.com/o/oauth2/token',
        access_token_params=None,
        authorize_url='https://accounts.google.com/o/oauth2/token',
        authorize_params=None,
        api_base_url="https://www.googleapis.com/oauth2/v1",
        client_kwargs={
            'scope': 'openid profile email',
        },
    )

    @app.route('/login')
    def Login(self):
        return self.auth0.authorize_redirect(redirect_uri='login.html')

    @app.route('/logout')
    def Logout(self):
        # Clear session stored data
        session.clear()
        # Redirect user to logout endpoint
        params = {
            'returnTo': url_for('home', _external=True),
            'client_id': 'YOUR_CLIENT_ID'
        }
        return redirect(self.auth0.api_base_url + '/v2/logout?' +
                        urlencode(params))

    @app.route('/callback')
    def CallbackHandling(self):
        # Handles response from token endpoint
        self.auth0.authorize_access_token()
        resp = self.auth0.get('userinfo')
        userinfo = resp.json()

        # Store the user information in flask session.
        session['jwt_payload'] = userinfo
        session['profile'] = {
            'user_id': userinfo['id'],
            'password': userinfo['password'],
            'name': userinfo['name'],
            'children': userinfo['children'],
            'phone number': userinfo['phone number']
        }
        return redirect('/dashboard')

    def RequiresAuth(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            if 'profile' not in session:
                # Redirect to Login page here
                return redirect('/')

            return f(*args, **kwargs)

        return decorated

    @app.route('/dashboard')
    @RequiresAuth
    def Dashboard():
        return render_template('dashboard.html',
                               userinfo=session['profile'],
                               userinfo_pretty=json.dumps(
                                   session['jwt_payload'], indent=4))
コード例 #7
0
from flask import Flask
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy
from authlib.integrations.flask_client import OAuth

flask_app = Flask(__name__)

flask_app.config.from_object('config')
db = SQLAlchemy(flask_app)
oauth = OAuth(flask_app)

oauth.register(
    name='google',
    client_id=flask_app.config.get('GOOGLE_OAUTH_CLIENT_ID'),
    client_secret=flask_app.config.get('GOOGLE_OAUTH_CLIENT_SECRET'),
    client_kwargs={'scope': 'https://www.googleapis.com/auth/userinfo.email'},
    api_base_url='https://www.googleapis.com/oauth2/v1/',
    request_token_url=None,
    access_token_method='POST',
    access_token_url='https://accounts.google.com/o/oauth2/token',
    authorize_url='https://accounts.google.com/o/oauth2/auth')

login_manager = LoginManager()
login_manager.init_app(flask_app)
login_manager.login_view = "login"

from app import views, models, forms, api, context_processors
コード例 #8
0
def create_app(test_config=None):
    app = Flask(__name__, static_folder='../client/build', static_url_path='')
    setup_db(app)
    oauth = OAuth(app)
    CORS(app, resources={
         r"*": {"origins": [
                            os.environ["FRONT_END_HOST"],
                            "http://*****:*****@app.route('/')
    def serve():
        try:
            return send_from_directory(app.static_folder, 'index.html')
        except Exception as ex:
            flash("An error occurred.")
            print(sys.exc_info())
            abort(404)


    @app.route('/callback')
    def callback_handling():
        access_data = auth0.authorize_access_token() # Handles response from token endpoint
        access_token = access_data['access_token']
        id_token = access_data['id_token']

        resp = auth0.get('userinfo')
        userinfo = resp.json()

        # Store the user information in flask session.
        session['jwt_payload'] = userinfo
        session['profile'] = {
            'user_id': userinfo['sub'],
            'name': userinfo['name'],
            'picture': userinfo['picture'],
            'nickname': userinfo['nickname'],
        }

        if session['profile']['user_id'] is None:
            raise ValueError("No defined user from authentication.")

        matching_observer = Observer.query.filter(Observer.auth0_id == session['profile']['user_id']).first()
        if matching_observer is None: # this should imply that this is a sign-up operation by a new user
            matching_observer = add_new_user(session['profile']['user_id'])

        final_response = make_response(redirect(f"{os.environ['FRONT_END_HOST']}/#/dashboard"))
        final_response.set_cookie(USER_ACCESS_TOKEN_KEY, access_token)
        final_response.set_cookie(USER_ID_TOKEN_KEY, id_token)
        final_response.set_cookie(OBSERVER_DATABASE_ID_KEY, str(matching_observer.id))
        final_response.set_cookie(USER_PICTURE_KEY, session['profile']['picture'])
        final_response.set_cookie(USER_NICKNAME_KEY, session['profile']['nickname'])
        return final_response


    def add_new_user(user_auth0_id):
        nonlocal management_api_access_token
        conn = http.client.HTTPSConnection(os.environ["AUTH0_DOMAIN"])
        if management_api_access_token is None:
            management_api_access_token = acquire_management_api_access_token()
        payload = "{ \"roles\": [ \"" + os.environ["DISASTER_REPORTER_ROLE_ID"] + "\" ] }"
        headers = {
            'content-type': "application/json",
            'authorization': f"Bearer {management_api_access_token}",
            'cache-control': "no-cache"
        }
        try:
            conn.request("POST", f"/api/v2/users/{user_auth0_id}/roles", payload, headers)
            conn.getresponse()
            new_observer = Observer(session['profile']['nickname'], user_auth0_id, session['profile']['picture']) # add entry to database
            new_observer.insert()
            return new_observer
        except Exception as ex:
            flash("An error occurred.")
            print("\n\n\n")
            print("ex:", ex)
            print("\n\n\n")
            print(sys.exc_info())


    def acquire_management_api_access_token():
        print("\nAcquiring management API access token...\n")
        conn = http.client.HTTPSConnection(os.environ['AUTH0_DOMAIN'])
        payload = "{\"client_id\":\"" + os.environ['AUTH0_CLIENT_ID'] + "\",\"client_secret\":\"" + os.environ['CLIENT_SECRET'] + "\",\"audience\":\"https://" + os.environ['AUTH0_DOMAIN'] + "/api/v2/\",\"grant_type\":\"client_credentials\"}"
        headers = { 'content-type': "application/json" }
        conn.request("POST", "/" + os.environ['AUTH0_DOMAIN'] + "/oauth/token", payload, headers)
        res = conn.getresponse()
        data = res.read()
        json_data = json.loads(data)
        return json_data["access_token"]


    # update most recent update datetime of corresponding disaster
    def update_parent_disaster_of_witness_report(disaster_id):
        disaster_match = Disaster.query.filter(
            Disaster.id == disaster_id
        ).first()
        if disaster_match is None:
            raise ValueError(f"No matching disaster id: {body.get('disaster_id')}")
        disaster_match.update()


    @app.route('/my-login')
    def login():
        return auth0.authorize_redirect(redirect_uri=f"{os.environ['BACK_END_HOST']}/callback", audience=os.environ["API_AUDIENCE"])


    @app.route('/my-logout')
    def logout():
        session.clear() # Clear session stored data
        # params = {'returnTo': f'{os.environ["FRONT_END_HOST"]}/#/404', 'client_id': os.environ["AUTH0_CLIENT_ID"]} # Redirect user to logout endpoint
        params = {'returnTo': f'{os.environ["FRONT_END_HOST"]}', 'client_id': os.environ["AUTH0_CLIENT_ID"]} # Redirect user to logout endpoint
        response = make_response(redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params)))
        response.delete_cookie(USER_ACCESS_TOKEN_KEY)
        response.delete_cookie(USER_ID_TOKEN_KEY)
        response.delete_cookie(OBSERVER_DATABASE_ID_KEY)
        response.delete_cookie(USER_PICTURE_KEY)
        response.delete_cookie(USER_NICKNAME_KEY)
        return response


    @app.route('/api')
    def get_greeting():
        excited = os.environ['EXCITED']
        greeting = "Hello"
        if excited == 'true':
            greeting = greeting + "!!!!!"
        return greeting


    @app.route('/api/coolkids')
    def be_cool():
        return "Be cool, man, be coooool! You're almost an FSND grad!"


    def get_page_of_resource(arr, page):
        if page <= 0:
            raise ValueError("A non-positive page is not recognized.")

        start = min((page - 1) * PAGE_SIZE, len(arr))
        end = min(page * PAGE_SIZE, len(arr))
        return arr[start:end]


    def get_random_report_data(witness_reports):
        disaster_map = dict()
        for (disaster_id, observer_id, comment, image_url) in witness_reports:
            if disaster_id not in disaster_map:
                disaster_map[disaster_id] = list()
            disaster_map[disaster_id].append((observer_id, comment, image_url))

        random_report_data = dict()
        for k, v in disaster_map.items():
            reports_with_images = list(filter(lambda report_data: report_data[2] is not None, v))
            if len(reports_with_images) > 0:
                random_report_data[k] = reports_with_images[randrange(len(reports_with_images))]
            else:
                random_report_data[k] = v[randrange(len(v))]
        return random_report_data


    def combine_disaster_data(
            formatted_disasters: list,
            formatted_affected_people: list,
            random_report_data: dict,
            all_users: list) -> dict:
        affected_map = {A[0]: (A[1], A[2], A[3], A[4], A[5])
                        for A in formatted_affected_people}
        user_map = {
            user["id"]: {
                "username": user["username"],
                "photograph_url": user["photograph_url"]
            }
            for user in all_users
        }

        for disaster in formatted_disasters:
            if disaster["id"] in affected_map:
                disaster["people_affected"] = affected_map[disaster["id"]][0]
                disaster["average_severity"] = affected_map[disaster["id"]][1]
                disaster["first_observance"] = affected_map[disaster["id"]][2]
                disaster["last_observance"] = affected_map[disaster["id"]][3]
                disaster["num_reports"] = affected_map[disaster["id"]][4]
            else:
                disaster["people_affected"] = None
                disaster["average_severity"] = None
                disaster["first_observance"] = None
                disaster["last_observance"] = None
                disaster["num_reports"] = 0

            if disaster["id"] in random_report_data:
                user_info = random_report_data[disaster["id"]]
                disaster["random_observer"] = \
                    user_map[user_info[0]]["username"]
                disaster["random_observer_url"] = user_map[user_info[0]
                                                           ]["photograph_url"]
                disaster["random_comment"] = user_info[1]
                disaster["random_witness_image"] = user_info[2]
            else:
                disaster["random_observer"] = None
                disaster["random_observer_url"] = None
                disaster["random_comment"] = None
                disaster["random_witness_image"] = None

        return formatted_disasters


    def combine_single_disaster_data(
            disaster,
            formatted_additional_data,
            formatted_reports,
            page) -> dict:
        all_data = copy(disaster)
        all_data["people_affected"] = formatted_additional_data[1]
        all_data["average_severity"] = formatted_additional_data[2]
        all_data["first_observance"] = formatted_additional_data[3]
        all_data["last_observance"] = formatted_additional_data[4]
        all_data["num_reports"] = formatted_additional_data[5]

        all_data["reports"] = get_page_of_resource(formatted_reports, page)

        for report in all_data["reports"]:
            del report["disaster_id"]

        return all_data


    '''
    A GET endpoint to get all disasters or disasters by disaster type. This
    endpoint takes an optional parameter 'disaster_type' to filter by the
    disaster_type. If no disaster_type parameter is provided, then the data
    for all disasters is returned. If the disaster_type parameter is provided
    but is not one of the recognized enums, a 404 error is raised.

    The endpoint also has an optional page request parameter corresponding to
    the paginated page to use. The current default for the size of a page is
    10. If the page is non-positive, then a 422 error occurs.

    The endpoint has another optional parameter: query. This is to match
    informal_name or official_name.

    This endpoint does not return any of the witness reports associated with a
    specific disaster. For each disaster, the data in the disaster table is
    returned along with a random comment and the author of that comment from a
    witness of the disaster (if any) and some descriptive data about the
    disaster reports per disaster (namely, the number of reports, the first
    observance, the last observance, and the number of people affected).
    '''
    @app.route('/api/disasters')
    def disasters():
        page = int(request.args.get("page", "1"))
        disaster_type = request.args.get("disaster_type")
        query_string = request.args.get("query")
        use_inclusive_search = False

        try:
            if disaster_type is not None and disaster_type.upper(
            ) not in NaturalDisasterEnum.__members__:
                raise AttributeError("Unrecognized natural disaster type.")
            formatted_disasters = []

            if query_string is not None and disaster_type is None and query_string.upper() in NaturalDisasterEnum.__members__:
                disaster_type = query_string
                use_inclusive_search = True

            if query_string is None and disaster_type is None:
                disasters = Disaster.query.order_by(Disaster.last_update_datetime.desc()).all()
            elif query_string is None and disaster_type is not None:
                disasters = Disaster.query.filter(Disaster.disaster_type == disaster_type.upper()).order_by(Disaster.last_update_datetime.desc()).all()
            elif query_string is not None and disaster_type is None:
                disasters = Disaster.query.filter(or_(
                    Disaster.informal_name.ilike('%' + query_string + '%'), 
                    Disaster.official_name.ilike('%' + query_string + '%')
                )).order_by(Disaster.last_update_datetime.desc()).all()
            elif query_string is not None and disaster_type is not None and not use_inclusive_search:
                disasters = Disaster.query.filter(and_(
                    or_(
                        Disaster.informal_name.ilike('%' + query_string + '%'),
                        Disaster.official_name.ilike('%' + query_string + '%'),
                    ),
                    Disaster.disaster_type == disaster_type.upper()
                )).order_by(Disaster.last_update_datetime.desc()).all()
            else:
                disasters = Disaster.query.filter(or_(
                    Disaster.informal_name.ilike('%' + query_string + '%'),
                    Disaster.official_name.ilike('%' + query_string + '%'),
                    Disaster.disaster_type == disaster_type.upper()
                )).order_by(Disaster.last_update_datetime.desc()).all()

            total_disasters = len(disasters)
            formatted_disasters = get_page_of_resource(
                [disaster.format() for disaster in disasters], page)

            additional_data = WitnessReport.query.with_entities(
                WitnessReport.disaster_id,
                func.max(WitnessReport.people_affected),
                func.avg(WitnessReport.severity),
                func.min(WitnessReport.event_datetime),
                func.max(WitnessReport.event_datetime),
                func.count(WitnessReport.disaster_id),
            ).group_by(WitnessReport.disaster_id).all()

            formatted_additional_data = [
                (report[0],
                 report[1],
                 float(report[2]) if report[2] else None,
                 report[3],
                 report[4],
                 report[5]) for report in additional_data]

            # disaster_id, observer_id, comment
            all_witness_reports = WitnessReport.query.with_entities(
                WitnessReport.disaster_id, WitnessReport.observer_id,
                WitnessReport.comment, WitnessReport.image_url).all()

            # dictionary containing some random report data per disaster
            random_report_data = get_random_report_data(all_witness_reports)

            all_users = [user.format() for user in Observer.query.all()]

            return jsonify(
                {
                    'total_disasters': total_disasters,
                    'disasters': combine_disaster_data(
                        formatted_disasters, formatted_additional_data,
                        random_report_data, all_users
                    ),
                })
        except AttributeError as ex:
            flash('An error occurred.')
            print(sys.exc_info())
            abort(404)
        except Exception as ex:
            flash("An error occurred.")
            print(sys.exc_info())
            abort(422)


    '''
    A GET endpoint to get the details of a single disaster, including:
        - id (int)
        - informal_name (str)
        - official_name (str)
        - disaster_type (enum str)
        - is_ongoing (bool)
        - location (list of pair of floats)
        - people_affected (maximum over all reports if there exist reports,
            otherwise None)
        - average_severity (float)
        - first_observance (datetime str)
        - last_observance (datetime str)
        - num_reports (int; if no reports exist, it is 0)
        - reports (list)

    The reports property contains a list of individual witness reports, each
        including:
        - id (int)
        - observer_id (int)
        - event_datetime (datetime str)
        - severity (int)
        - image_url (str)
        - comment (str)
        - people_affected (int)
        - location (list of pair of floats)
        - username (str)
        - user_photograph_url (str)

    A page query parameter allows the page setting of the reports with 10 per
    page; if the page is invalid, a 422 error is returned; otherwise, if the id
    provided does not correspond to an existing disaster, a 404 error is
    returned
    '''
    @app.route('/api/disasters/<disaster_id>')
    def retrieve_disaster_by_id(disaster_id):
        page = int(request.args.get("page", "1"))

        try:
            if page <= 0:
                raise ValueError("The request page must be positive.")

            disaster = Disaster.query.filter(
                Disaster.id == disaster_id).first()

            additional_data = WitnessReport.query.filter(
                WitnessReport.disaster_id == disaster_id).with_entities(
                        WitnessReport.disaster_id,
                        func.max(WitnessReport.people_affected),
                        func.avg(WitnessReport.severity),
                        func.min(WitnessReport.event_datetime),
                        func.max(WitnessReport.event_datetime),
                        func.count(WitnessReport.disaster_id),
                    ).group_by(WitnessReport.disaster_id).first()

            if additional_data:
                formatted_additional_data = (
                    additional_data[0],
                    additional_data[1],
                    float(
                        additional_data[2]) if additional_data[2] else None,
                    additional_data[3],
                    additional_data[4],
                    additional_data[5])
            else:
                formatted_additional_data = (None, None, None, None, None, 0)

            reports, observer_map = WitnessReport.observer_join(disaster_id)
            formatted_reports = [report.format() for report in reports]
            for fr in formatted_reports:
                fr["username"] = observer_map[fr["observer_id"]][0]
                fr["user_photograph_url"] = observer_map[fr["observer_id"]][1]

            return jsonify(
                combine_single_disaster_data(
                    disaster.format(),
                    formatted_additional_data,
                    formatted_reports,
                    page))
        except AttributeError as ex:
            flash("An attribute error occurred.")
            print(sys.exc_info())
            abort(404)
        except Exception as ex:
            flash("An error occurred.")
            print(sys.exc_info())
            abort(422)


    '''
    A GET endpoint to retrieve a page of the set of observers, including the
    observers' ids, usernames, and the URLs of their user photographs. The page
    can be specified as a query parameter and if none is provided, it will be
    assumed to be 1. The use of an invalid page (i.e. a non-positive page) will
    cause a status 422 error to be returned.
    '''
    @app.route('/api/observers', methods=["GET"])
    @requires_auth('get:observers')
    def get_all_observers(payload):
        page = int(request.args.get("page", "1"))
        try:
            observers = Observer.query.all()
            page_observers = get_page_of_resource(observers, page)
            formatted_observers = [observer.format()
                                   for observer in page_observers]
            return jsonify({"observers": formatted_observers})
        except Exception as ex:
            flash("An error occurred.")
            print(sys.exc_info())
            abort(422)


    '''
    A GET endpoint to retrieve a witness report of the set of observers, 
    including:
        - witness report id
        - disaster id
        - observer id
        - event datetime
        - severity
        - image URL
        - comment
        - number of peopl affected
        - location (array of latitude and longitude)
    
    When an id (witness_report_id) is provided which does not correspond to an 
    existing witness report, a 404 error is returned.
    '''
    @app.route('/api/witnessreports/<witness_report_id>', methods=["GET"])
    def retrieve_witness_report_by_id(witness_report_id):
        try:
            witness_report = WitnessReport.query.filter(
                WitnessReport.id == witness_report_id).first()
            return jsonify(witness_report.format())
        except Exception as ex:
            flash("An error occurred.")
            print(sys.exc_info())
            abort(404)


    '''
    A POST endpoint to insert a disaster into the database. The body for the
    request is a dictionary with the following keys:

        - informal_name (str)
        - official_name (str, required, must be unique)
        - disaster_type (str, disaster enum)
        - is_ongoing (bool, default True)
        - location_latitude (float, required)
        - location_longitude (float, required)

    If the request's disaster data does not meet the conditions of requirement
    described above, a 400 status code error is returned
    '''
    @app.route('/api/disasters', methods=["POST"])
    @requires_auth('post:disasters')
    def send_disaster(payload):
        try:
            body = request.get_json()
            disaster = Disaster(
                body.get("informal_name"),
                body.get("official_name"),
                body.get("disaster_type").lower(),
                body.get("is_ongoing"),
                body.get("location_latitude"),
                body.get("location_longitude"),
            )
            disaster.insert()
            return jsonify({"id": disaster.id})
        except Exception as ex:
            flash("An error occurred.")
            print(f"ex: {ex}")
            print(sys.exc_info())
            abort(400)


    '''
    A POST endpoint to insert a user into the database. THe body for the
    request is a dictionary with the following keys:

        - username (str, required, unique)
        - photograph_url (str)

    If the request's data does not meet the conditions of requirement described
    above, then a 400 status code error is returned
    '''
    @app.route('/api/observers', methods=["POST"])
    def send_user():
        try:
            body = request.get_json()
            observer = Observer(body.get("username"),
                                body.get("auth0_id"),
                                body.get("photograph_url"))
            observer.insert()
            return jsonify({"id": observer.id})
        except Exception as ex:
            flash("An error occurred.")
            print(f"ex: {ex}")
            print(sys.exc_info())
            abort(400)


    '''
    A POST endpoint to insert a witness's report into the database. The body
    for the request is a dictionary with the following keys:

        - disaster_id (int, required)
        - observer_id (int, required)
        - event_datetime (datetime str, required)
        - severity (int)
        - image_url (str)
        - comment (str)
        - people_affected (int, default = 0)
        - location_latitude (float)
        - location_longitude (float)

    If the request's data does not meet the conditions of requirement described
    above, then a 400 status code error is returned
    '''
    @app.route('/api/witnessreports', methods=["POST"])
    @requires_auth('post:witnessreports')
    def send_witness_report(payload):
        try:
            body = request.get_json()
            witness_report = WitnessReport(
                body.get("disaster_id"),
                body.get("observer_id"),
                body.get("event_datetime"),
                body.get("severity"),  # optional
                body.get("image_url"),  # optional
                body.get("comment"),  # optional
                body.get("people_affected"),
                body.get("location_latitude"),
                body.get("location_longitude")
            )
            witness_report.insert()

            # update most recent update datetime of corresponding disaster
            update_parent_disaster_of_witness_report(body.get('disaster_id'))

            return jsonify({"id": witness_report.id})
        except Exception as ex:
            flash("An error occurred.")
            print(sys.exc_info())
            abort(400)


    '''
    A PATCH endpoint to update a disaster. The body of the request is a
    dictionary with the following keys, all of which are optional except for
    id:

        - id (int)
        - informal_name (str)
        - official_name (str)
        - disaster_type (str)
        - is_ongoing (str)
        - location_latitude (str)
        - location_longitude (str)

    If no id is provided, then a 400 status code error is returned. If an id is
    provided but it does not match that of any disaster in the database, a 404
    status code error is returned. Otherwise, if there are any malformed parts
    of the update data dictionary, then a 422 error is thrown.
    '''
    @app.route('/api/disasters', methods=["PATCH"])
    @requires_auth('patch:disasters')
    def update_disaster(payload):
        try:
            body = request.get_json()
            if "id" not in body:
                raise AttributeError(
                    "id is not present as a property in the sent data.")
            disaster = Disaster.query.filter(Disaster.id == body["id"]).first()

            if disaster is None:
                raise ValueError("Unrecognized disaster id")

            if "informal_name" in body:
                disaster.informal_name = body["informal_name"]
            if "official_name" in body:
                disaster.official_name = body["official_name"]
            if "disaster_type" in body:
                disaster.disaster_type = body["disaster_type"]
            if "is_ongoing" in body:
                disaster.is_ongoing = body["is_ongoing"]
            if "location_latitude" in body:
                disaster.location_latitude = body["location_latitude"]
            if "location_longitude" in body:
                disaster.location_longitude = body["location_longitude"]

            disaster.update()
            return jsonify(disaster.format())
        except AttributeError as err:
            flash(str(err))
            print(sys.exc_info())
            abort(400)
        except ValueError as err:
            flash(str(err))
            print(sys.exc_info())
            abort(404)
        except Exception as err:
            flash("An error occurred.")
            print(sys.exc_info())
            abort(422)


    '''
    A PATCH endpoint to update a witness report of a disaster. The body of the
    request is a dictionary with the following keys, all of which are optional
    except for id (all fields except for id represent fields which are being
    changed):

        - id (int, required)
        - event_datetime (datetime str)
        - severity (int)
        - image_url (str)
        - comment (str)
        - people_affected (int)
        - location_latitude (str)
        - location_longitude (str)

    If no id is provided, then a 400 status code error is returned. If an id is
    provided but it does not match that of any witness report in the database,
    a 404 status code error is returned. Otherwise, if there are any malformed
    parts of the update data dictionary, then a 422 error is thrown.
    '''
    @app.route('/api/witnessreports', methods=["PATCH"])
    @requires_auth('patch:witnessreports')
    def update_witness_report(payload):
        try:
            body = request.get_json()
            if "id" not in body:
                raise AttributeError(
                    "id is not present as a property in the sent data.")

            witness_report = WitnessReport.query.filter(
                WitnessReport.id == body["id"]).first()

            if witness_report is None:
                raise ValueError("Unrecognized witness report id")

            if "event_datetime" in body:
                witness_report.event_datetime = body["event_datetime"]
            if "severity" in body:
                witness_report.severity = body["severity"]
            if "image_url" in body:
                witness_report.image_url = body["image_url"]
            if "comment" in body:
                witness_report.comment = body["comment"]
            if "people_affected" in body:
                witness_report.people_affected = body["people_affected"]
            if "location_latitude" in body:
                witness_report.location_latitude = body["location_latitude"]
            if "location_longitude" in body:
                witness_report.location_longitude = body["location_longitude"]
            
            witness_report.update()

            # update most recent update datetime of corresponding disaster
            update_parent_disaster_of_witness_report(witness_report.disaster_id)

            return jsonify(witness_report.format())
        except AttributeError as err:
            flash(str(err))
            print(sys.exc_info())
            abort(400)
        except ValueError as err:
            flash(str(err))
            print(sys.exc_info())
            abort(404)
        except Exception as err:
            flash("An error occurred.")
            print(sys.exc_info())
            abort(422)


    '''
    Verify that a user can delete a witness report. A user may only delete a 
    witness report if he or she is an admin or the witness report was created
    by the user. Otherwise, a 403 unauthorized error will be raised.
    '''
    def validate_delete_witness_report(witness_report, user_data_payload):
        if "post:disasters" in user_data_payload["permissions"]: # user is an admin
            return True
        
        author_observer = Observer.query.filter(Observer.id == witness_report.observer_id).first()

        if author_observer is None:
            abort(401)
        
        if author_observer.auth0_id == user_data_payload["sub"]:
            return True
        else:
            abort(403)


    '''
    A DELETE endpoint for deleting a witness report. If the listed id does not
    exist among witness reports, a 400 status error is returned.
    '''
    @app.route('/api/witnessreports/<witness_report_id>', methods=["DELETE"])
    @requires_auth('delete:witnessreports')
    def remove_witness_report(payload, witness_report_id):
        try:
            witness_report = WitnessReport.query.filter(
                WitnessReport.id == witness_report_id).first()
            if witness_report is None:
                raise AttributeError("Entry not found")
            validate_delete_witness_report(witness_report, payload)

            # update most recent update datetime of corresponding disaster
            update_parent_disaster_of_witness_report(witness_report.disaster_id)

            witness_report.delete()
            return jsonify({
                "success": True,
                "delete": witness_report_id,
            })
        except AttributeError as err:
            flash(str(err))
            print(sys.exc_info())
            abort(400)


    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "malformed request - " + str(error)
        }), 400


    @app.errorhandler(401)
    def authorization_header_missing(error):
        return jsonify({
            "success": False,
            "error": 401,
            "message": "authorization issue - " + str(error)
        }), 401


    @app.errorhandler(403)
    def authorization_incorrect_permission(error):
        return jsonify({
            "success": False,
            "error": 403,
            "message": "authorization incorrect permission - " + str(error)
        }), 403


    @app.errorhandler(404)
    def resource_not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found - " + str(error)
        }), 404


    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable - " + str(error),
        }), 422

    return app
コード例 #9
0
def create_oauth_app(service_config, name):
    service_oauth = OAuth(app)
    service_app = service_oauth.register(name, **service_config)
    return service_app
コード例 #10
0
import requests
from requests.exceptions import HTTPError

from flask import session, redirect, url_for, request, render_template
from flask import current_app as app
from authlib.integrations.flask_client import OAuth

import invite0.config as conf
import invite0.auth0.management_client as auth0_mgmt
from invite0.auth0.exceptions import UserNotLoggedIn, CanNotUnsetFieldError

_oauth_client = OAuth(app).register(
    'auth0',
    client_id=conf.AUTH0_CLIENT_ID,
    client_secret=conf.AUTH0_CLIENT_SECRET,
    api_base_url=f'https://{conf.AUTH0_DOMAIN}',
    access_token_url=f'https://{conf.AUTH0_DOMAIN}/oauth/token',
    authorize_url=f'https://{conf.AUTH0_DOMAIN}/authorize',
    client_kwargs={'scope': 'openid profile email'},
)


class _CurrentUser:
    """
    An abstraction over the Flask `session` and Auth0 APIs

    An instance of this class has no state of its own: the Flask `session`
    holds the state, which the instance merely reflects.

    There is no need to instantiate this class outside this module -- just
    import  `current_user` (instantiated below) -- but there is no harm in
コード例 #11
0
def create_app(test_config=None):
    app = Flask(__name__)
    app.secret_key = SECRET_KEY
    setup_db(app)
    CORS(app)

    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Origin', '*')
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PUT,POST,DELETE,OPTIONS')
        return response

    oauth = OAuth(app)

    auth0 = oauth.register(
        'auth0',
        client_id=AUTH0_CLIENT_ID,
        client_secret=AUTH0_CLIENT_SECRET,
        api_base_url=AUTH0_BASE_URL,
        access_token_url=AUTH0_BASE_URL + '/oauth/token',
        authorize_url=AUTH0_BASE_URL + '/authorize',
        client_kwargs={
            'scope': 'openid profile email',
        },
    )

    def requires_auth(permission='', permissions=[]):
        def requires_auth_decorator(f):
            @wraps(f)
            def decorated(*args, **kwargs):
                if PROFILE_KEY not in session:
                    abort(401)
                    return redirect('/login')
                if permission not in session['permissions']:
                    abort(401)
                return f(*args, **kwargs)

            return decorated

        return requires_auth_decorator

    # Controllers API
    @app.route('/')
    def home():
        return redirect('/login')

    @app.route('/callback')
    def callback_handling():
        auth0.authorize_access_token()
        resp = auth0.get('userinfo')
        userinfo = resp.json()
        url = 'https://sp31051998.auth0.com/api/v2/users/' + userinfo[
            'sub'] + '/permissions'
        headers = {
            "authorization":
            "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InBaV1Q1UjJ6QURlcFFKTF91cHM0eCJ9.eyJpc3MiOiJodHRwczovL3NwMzEwNTE5OTguYXV0aDAuY29tLyIsInN1YiI6ImZPT2gyUGVVblRWdGtGcFJtbm9wUGRvNndVbTVydmp2QGNsaWVudHMiLCJhdWQiOiJodHRwczovL3NwMzEwNTE5OTguYXV0aDAuY29tL2FwaS92Mi8iLCJpYXQiOjE1OTI3NTMxMjIsImV4cCI6MTU5MjgzOTUyMiwiYXpwIjoiZk9PaDJQZVVuVFZ0a0ZwUm1ub3BQZG82d1VtNXJ2anYiLCJzY29wZSI6InJlYWQ6Y2xpZW50X2dyYW50cyBjcmVhdGU6Y2xpZW50X2dyYW50cyBkZWxldGU6Y2xpZW50X2dyYW50cyB1cGRhdGU6Y2xpZW50X2dyYW50cyByZWFkOnVzZXJzIHVwZGF0ZTp1c2VycyBkZWxldGU6dXNlcnMgY3JlYXRlOnVzZXJzIHJlYWQ6dXNlcnNfYXBwX21ldGFkYXRhIHVwZGF0ZTp1c2Vyc19hcHBfbWV0YWRhdGEgZGVsZXRlOnVzZXJzX2FwcF9tZXRhZGF0YSBjcmVhdGU6dXNlcnNfYXBwX21ldGFkYXRhIHJlYWQ6dXNlcl9jdXN0b21fYmxvY2tzIGNyZWF0ZTp1c2VyX2N1c3RvbV9ibG9ja3MgZGVsZXRlOnVzZXJfY3VzdG9tX2Jsb2NrcyBjcmVhdGU6dXNlcl90aWNrZXRzIHJlYWQ6Y2xpZW50cyB1cGRhdGU6Y2xpZW50cyBkZWxldGU6Y2xpZW50cyBjcmVhdGU6Y2xpZW50cyByZWFkOmNsaWVudF9rZXlzIHVwZGF0ZTpjbGllbnRfa2V5cyBkZWxldGU6Y2xpZW50X2tleXMgY3JlYXRlOmNsaWVudF9rZXlzIHJlYWQ6Y29ubmVjdGlvbnMgdXBkYXRlOmNvbm5lY3Rpb25zIGRlbGV0ZTpjb25uZWN0aW9ucyBjcmVhdGU6Y29ubmVjdGlvbnMgcmVhZDpyZXNvdXJjZV9zZXJ2ZXJzIHVwZGF0ZTpyZXNvdXJjZV9zZXJ2ZXJzIGRlbGV0ZTpyZXNvdXJjZV9zZXJ2ZXJzIGNyZWF0ZTpyZXNvdXJjZV9zZXJ2ZXJzIHJlYWQ6ZGV2aWNlX2NyZWRlbnRpYWxzIHVwZGF0ZTpkZXZpY2VfY3JlZGVudGlhbHMgZGVsZXRlOmRldmljZV9jcmVkZW50aWFscyBjcmVhdGU6ZGV2aWNlX2NyZWRlbnRpYWxzIHJlYWQ6cnVsZXMgdXBkYXRlOnJ1bGVzIGRlbGV0ZTpydWxlcyBjcmVhdGU6cnVsZXMgcmVhZDpydWxlc19jb25maWdzIHVwZGF0ZTpydWxlc19jb25maWdzIGRlbGV0ZTpydWxlc19jb25maWdzIHJlYWQ6aG9va3MgdXBkYXRlOmhvb2tzIGRlbGV0ZTpob29rcyBjcmVhdGU6aG9va3MgcmVhZDphY3Rpb25zIHVwZGF0ZTphY3Rpb25zIGRlbGV0ZTphY3Rpb25zIGNyZWF0ZTphY3Rpb25zIHJlYWQ6ZW1haWxfcHJvdmlkZXIgdXBkYXRlOmVtYWlsX3Byb3ZpZGVyIGRlbGV0ZTplbWFpbF9wcm92aWRlciBjcmVhdGU6ZW1haWxfcHJvdmlkZXIgYmxhY2tsaXN0OnRva2VucyByZWFkOnN0YXRzIHJlYWQ6dGVuYW50X3NldHRpbmdzIHVwZGF0ZTp0ZW5hbnRfc2V0dGluZ3MgcmVhZDpsb2dzIHJlYWQ6c2hpZWxkcyBjcmVhdGU6c2hpZWxkcyB1cGRhdGU6c2hpZWxkcyBkZWxldGU6c2hpZWxkcyByZWFkOmFub21hbHlfYmxvY2tzIGRlbGV0ZTphbm9tYWx5X2Jsb2NrcyB1cGRhdGU6dHJpZ2dlcnMgcmVhZDp0cmlnZ2VycyByZWFkOmdyYW50cyBkZWxldGU6Z3JhbnRzIHJlYWQ6Z3VhcmRpYW5fZmFjdG9ycyB1cGRhdGU6Z3VhcmRpYW5fZmFjdG9ycyByZWFkOmd1YXJkaWFuX2Vucm9sbG1lbnRzIGRlbGV0ZTpndWFyZGlhbl9lbnJvbGxtZW50cyBjcmVhdGU6Z3VhcmRpYW5fZW5yb2xsbWVudF90aWNrZXRzIHJlYWQ6dXNlcl9pZHBfdG9rZW5zIGNyZWF0ZTpwYXNzd29yZHNfY2hlY2tpbmdfam9iIGRlbGV0ZTpwYXNzd29yZHNfY2hlY2tpbmdfam9iIHJlYWQ6Y3VzdG9tX2RvbWFpbnMgZGVsZXRlOmN1c3RvbV9kb21haW5zIGNyZWF0ZTpjdXN0b21fZG9tYWlucyB1cGRhdGU6Y3VzdG9tX2RvbWFpbnMgcmVhZDplbWFpbF90ZW1wbGF0ZXMgY3JlYXRlOmVtYWlsX3RlbXBsYXRlcyB1cGRhdGU6ZW1haWxfdGVtcGxhdGVzIHJlYWQ6bWZhX3BvbGljaWVzIHVwZGF0ZTptZmFfcG9saWNpZXMgcmVhZDpyb2xlcyBjcmVhdGU6cm9sZXMgZGVsZXRlOnJvbGVzIHVwZGF0ZTpyb2xlcyByZWFkOnByb21wdHMgdXBkYXRlOnByb21wdHMgcmVhZDpicmFuZGluZyB1cGRhdGU6YnJhbmRpbmcgZGVsZXRlOmJyYW5kaW5nIHJlYWQ6bG9nX3N0cmVhbXMgY3JlYXRlOmxvZ19zdHJlYW1zIGRlbGV0ZTpsb2dfc3RyZWFtcyB1cGRhdGU6bG9nX3N0cmVhbXMgY3JlYXRlOnNpZ25pbmdfa2V5cyByZWFkOnNpZ25pbmdfa2V5cyB1cGRhdGU6c2lnbmluZ19rZXlzIHJlYWQ6bGltaXRzIHVwZGF0ZTpsaW1pdHMiLCJndHkiOiJjbGllbnQtY3JlZGVudGlhbHMifQ.lnL_zFiHF1NjkRIK6MBNusoUO9NawuxBXQzZ_ocvFHsu2fz8GFzVevMSfvQL1jp7QE_5Qv6I6Up1yiyogO616G8ZOHfIJnX2bpI3WecMLziVGRU-Lbw-SXx7JoqZeiKHkWGXEDCLepUrAGOHlhBaNFHYkZaXdB4hcxRXSjAFDbP-_fFm4spOjCTOr09kQLlyhAP_f1tPPd1u_jUZr5lDkahodTghP7_fmSncgCtdqbhc6ivFWnDppP2SgDMyft5hXV8YMSMEKIAkLwkB7oSou9bmxqdDcG3YmhRCbwdDTlLTY1-d8bHLXYDhx3SBK1hBNB7yJPhYNXHnP1mfxAKplw"
        }
        req = requests.get(url, headers=headers)
        permissions = []

        response = json.loads(req.text)

        for permission in response:
            permissions.append(permission['permission_name'])
        session['permissions'] = permissions
        session[JWT_PAYLOAD] = userinfo
        session[PROFILE_KEY] = {
            'user_id': userinfo['sub'],
            'name': userinfo['name'],
            'picture': userinfo['picture']
        }
        return redirect('/dashboard')

    @app.route('/login')
    def login():
        if session.get(PROFILE_KEY) is not None:
            return render_template('dashboard.html',
                                   permissions=session['permissions'])
        else:
            return auth0.authorize_redirect(redirect_uri=AUTH0_CALLBACK_URL,
                                            audience=AUTH0_AUDIENCE)

    @app.route('/logout')
    def logout():
        session.clear()
        params = {
            'returnTo': url_for('home', _external=True),
            'client_id': AUTH0_CLIENT_ID
        }
        return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))

    @app.route('/dashboard')
    def dashboard():
        if session.get(PROFILE_KEY) is not None:
            return render_template('dashboard.html',
                                   permissions=session['permissions'])
        else:
            return auth0.authorize_redirect(redirect_uri=AUTH0_CALLBACK_URL,
                                            audience=AUTH0_AUDIENCE)

    @app.route('/actors')
    #@requires_auth('get:actors')
    def retrieve_actors():
        selection = Actor.query.order_by(Actor.id).all()
        current_actors = [data.format() for data in selection]
        if len(current_actors) == 0:
            abort(404)

        return jsonify({
            'success': True,
            'actors': current_actors,
            'total_actors': len(Actor.query.all())
        })

    @app.route('/actors', methods=['POST'])
    #@requires_auth('post:actors')
    def create_actor():
        body = request.get_json()

        new_name = body.get('name', None)
        new_age = body.get('age', None)
        new_gender = body.get('gender', None)
        print(new_name, new_age, new_gender)

        try:
            actor = Actor(name=new_name, age=new_age, gender=new_gender)
            actor.insert()

            return jsonify({
                'success': True,
                'created': actor.format(),
            })
        except Exception as e:
            abort(422)

    @app.route('/actors/<int:actor_id>', methods=['PATCH'])
    #@requires_auth('patch:actors')
    def update_actor(actor_id):
        body = request.get_json()
        name = body.get('name', None)
        gender = body.get('gender', None)
        age = body.get('age', None)
        try:
            actor = Actor.query.filter(Actor.id == actor_id)\
                        .one_or_none()
            if actor is None:
                abort(404)
            if name is not None:
                actor.name = name
            if gender is not None:
                actor.gender = gender
            if age is not None:
                actor.age = age
            actor.update()
            return jsonify({
                'success': True,
                'actor': actor.format(),
            })

        except Exception as e:
            abort(422)

    @app.route('/actors/<int:actor_id>', methods=['DELETE'])
    #@requires_auth('delete:actors')
    def delete_actor(actor_id):
        try:
            actor = Actor.query.filter(Actor.id == actor_id)\
                        .one_or_none()
            actor.delete()
            return jsonify({
                'success': True,
                'deleted': actor_id,
            })
        except Exception as e:
            abort(404)

    @app.route('/movies')
    #@requires_auth('get:movies')
    def retrieve_movies():
        selection = Movie.query.order_by(Movie.id).all()
        current_movies = [data.format() for data in selection]
        if len(current_movies) == 0:
            abort(404)
        print((current_movies[0]['release_date']).strftime("%x"))
        return jsonify({
            'success': True,
            'movies': current_movies,
            'total_movies': len(Movie.query.all())
        })

    @app.route('/movies', methods=['POST'])
    #@requires_auth('post:movies')
    def create_movie():
        body = request.get_json()

        new_title = body.get('title', None)
        new_release_date = body.get('release_date', None)

        try:
            movie = Movie(title=new_title, release_date=new_release_date)
            movie.insert()

            return jsonify({
                'success': True,
                'created': movie.format(),
            })
        except Exception as e:
            abort(422)

    @app.route('/movies/<int:movie_id>', methods=['PATCH'])
    #@requires_auth('patch:movies')
    def update_movie(movie_id):
        body = request.get_json()
        title = body.get('title', None)
        release_date = body.get('release_date', None)
        try:
            movie = Movie.query.filter(Movie.id == movie_id)\
                        .one_or_none()
            if movie is None:
                abort(404)
            if title is not None:
                movie.title = title
            if release_date is not None:
                movie.release_date = release_date
            movie.update()
            return jsonify({
                'success': True,
                'movie': movie.format(),
            })

        except Exception as e:
            abort(422)

    @app.route('/movies/<int:movie_id>', methods=['DELETE'])
    #@requires_auth('delete:movies')
    def delete_movie(movie_id):
        try:
            movie = Movie.query.filter(Movie.id == movie_id)\
                        .one_or_none()
            movie.delete()
            return jsonify({
                'success': True,
                'deleted': movie_id,
            })
        except Exception as e:
            abort(404)

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(405)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 405,
            "message": "method not allowed"
        }), 405

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "bad request"
        }), 400

    @app.errorhandler(500)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "Internal server error"
        }), 500

    @app.errorhandler(401)
    def user_not_authorized(error):
        return jsonify({
            "success": False,
            "error": 401,
            "message": "User not authorized"
        }), 401

    return app
コード例 #12
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    app.secret_key = constants.SECRET_KEY
    CORS(app)
    setup_db(app)

    @app.errorhandler(Exception)
    def handle_auth_error(ex):
        response = jsonify(message=str(ex))
        response.status_code = (ex.code
                                if isinstance(ex, HTTPException) else 500)
        return response

    oauth = OAuth(app)

    auth0 = oauth.register(
        'auth0',
        client_id=AUTH0_CLIENT_ID,
        client_secret=AUTH0_CLIENT_SECRET,
        api_base_url=AUTH0_BASE_URL,
        access_token_url=AUTH0_BASE_URL + '/oauth/token',
        authorize_url=AUTH0_BASE_URL + '/authorize',
        client_kwargs={
            'scope': 'openid profile email',
        },
    )

    def requires_auth0(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            if constants.PROFILE_KEY not in session:
                return redirect('/login')
            return f(*args, **kwargs)

        return decorated

    @app.route('/')
    def home():
        return render_template('home.html')

    @app.route('/callback')
    def callback_handling():
        # Handles response from token endpoint
        token = auth0.authorize_access_token()
        session['token'] = token['access_token']
        print(session['token'])

        resp = auth0.get('userinfo')
        userinfo = resp.json()

        # Store the user information in flask session.
        session['jwt_payload'] = userinfo
        session['profile'] = {
            'user_id': userinfo['sub'],
            'name': userinfo['name'],
            'picture': userinfo['picture']
        }
        return redirect('/dashboard')

    @app.route('/login')
    def login():
        return auth0.authorize_redirect(redirect_uri=AUTH0_CALLBACK_URL,
                                        audience=AUTH0_AUDIENCE)

    @app.route('/logout')
    def logout():
        session.clear()
        params = {
            'returnTo': url_for('home', _external=True),
            'client_id': AUTH0_CLIENT_ID
        }
        return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))

    @app.route('/dashboard')
    @requires_auth0
    def dashboard():
        return render_template('dashboard.html',
                               userinfo=session[constants.PROFILE_KEY],
                               userinfo_pretty=json.dumps(
                                   session[constants.JWT_PAYLOAD], indent=4),
                               token=session['token'])

    @app.route('/drinks')
    @requires_auth('get:drinks')
    def view_drinks(jwt):
        try:
            drinks = Drink.query.all()
            if drinks is None:
                abort(404)
        except Exception as e:
            print(e)
        return jsonify({
            'success': True,
            'drinks': [drink.format() for drink in drinks]
        })

    @app.route('/desserts')
    @requires_auth('get:desserts')
    def view_dessert(jwt):
        try:
            desserts = Dessert.query.all()
            if desserts is None:
                abort(404)
        except Exception as e:
            print(e)
        return jsonify({
            'success': True,
            'desserts': [dessert.format() for dessert in desserts]
        })

    @app.route('/drinks', methods=['POST'])
    @requires_auth('post:drinks')
    def create_drink(jwt):
        body = request.get_json()
        if body is None:
            abort(400)
        drink_title = body.get('title')
        drink = Drink(title=drink_title)
        drink.insert()
        return jsonify({'success': True, 'drinks': [drink.format()]})

    @app.route('/desserts', methods=['POST'])
    @requires_auth('post:desserts')
    def create_dessert(jwt):
        body = request.get_json()
        if body is None:
            abort(400)
        dessert_title = body.get('title')
        dessert = Dessert(title=dessert_title)
        dessert.insert()
        return jsonify({'success': True, 'desserts': [dessert.format()]})

    @app.route('/drinks/<id>', methods=['PATCH'])
    @requires_auth('patch:drinks')
    def update_drink(jwt, id):
        drink = Drink.query.get(id)
        if drink:
            try:
                body = request.get_json()
                new_title = body.get('title')
                if new_title:
                    drink.title = new_title
                drink.update()
                return jsonify({'success': True, 'drinks': [drink.format()]})
            except Exception as e:
                print(e)
                abort(422)
        else:
            abort(404)

    @app.route('/desserts/<id>', methods=['PATCH'])
    @requires_auth('patch:desserts')
    def update_dessert(jwt, id):
        dessert = Dessert.query.get(id)
        if dessert:
            try:
                body = request.get_json()
                new_title = body.get('title')
                if new_title:
                    dessert.title = new_title
                dessert.update()
                return jsonify({
                    'success': True,
                    'desserts': [dessert.format()]
                })
            except Exception as e:
                print(e)
                abort(422)
        else:
            abort(404)

    @app.route('/drinks/<id>', methods=['DELETE'])
    @requires_auth('delete:drinks')
    def delete_drink(jwt, id):
        drink = Drink.query.get(id)
        if drink:
            try:
                drink.delete()
                return jsonify({'success': True, 'delete': id})
            except:
                abort(422)
        else:
            abort(404)

    @app.route('/desserts/<id>', methods=['DELETE'])
    @requires_auth('delete:desserts')
    def delete_dessert(jwt, id):
        dessert = Dessert.query.get(id)
        if dessert:
            try:
                dessert.delete()
                return jsonify({'success': True, 'delete': id})
            except:
                abort(422)
        else:
            abort(404)

    @app.errorhandler(AuthError)
    def auth_error(error):
        return jsonify({
            'success': False,
            'error': error.status_code,
            'message': error.error
        }), error.status_code

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(401)
    def unauthorised(error):
        return jsonify({
            "success": False,
            "error": 401,
            "message": "unauthorised"
        }), 401

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "bad_request"
        }), 400

    return app
コード例 #13
0
class OAuth2Authentication(BaseAuthentication):
    """OAuth Authentication Class"""

    LOGOUT_VIEW = OAUTH2_LOGOUT

    oauth_obj = OAuth(Flask(__name__))
    oauth2_clients = {}
    oauth2_config = {}

    def __init__(self):
        for oauth2_config in config.OAUTH2_CONFIG:

            OAuth2Authentication.oauth2_config[
                oauth2_config['OAUTH2_NAME']] = oauth2_config

            OAuth2Authentication.oauth2_clients[oauth2_config[
                'OAUTH2_NAME']] = OAuth2Authentication.oauth_obj.register(
                    name=oauth2_config['OAUTH2_NAME'],
                    client_id=oauth2_config['OAUTH2_CLIENT_ID'],
                    client_secret=oauth2_config['OAUTH2_CLIENT_SECRET'],
                    access_token_url=oauth2_config['OAUTH2_TOKEN_URL'],
                    authorize_url=oauth2_config['OAUTH2_AUTHORIZATION_URL'],
                    api_base_url=oauth2_config['OAUTH2_API_BASE_URL'],
                    client_kwargs={
                        'scope': oauth2_config.get('OAUTH2_SCOPE',
                                                   'email profile')
                    },
                )

    def get_source_name(self):
        return OAUTH2

    def get_friendly_name(self):
        return self.oauth2_config[self.oauth2_current_client]['OAUTH2_NAME']

    def validate(self, form):
        return True

    def login(self, form):
        profile = self.get_user_profile()
        if 'email' not in profile or not profile['email']:
            current_app.logger.exception(
                "An email id is required to login into pgAdmin. "
                "Please update your Oauth2 profile.")
            return False, gettext(
                "An email id is required to login into pgAdmin. "
                "Please update your Oauth2 profile.")

        user, msg = self.__auto_create_user(profile)
        if user:
            user = db.session.query(User).filter_by(
                username=profile['email'], auth_source=OAUTH2).first()
            current_app.login_manager.logout_view = \
                OAuth2Authentication.LOGOUT_VIEW
            return login_user(user), None
        return False, msg

    def get_user_profile(self):
        session['oauth2_token'] = self.oauth2_clients[
            self.oauth2_current_client].authorize_access_token()

        session['pass_enc_key'] = session['oauth2_token']['access_token']

        resp = self.oauth2_clients[self.oauth2_current_client].get(
            self.oauth2_config[
                self.oauth2_current_client]['OAUTH2_USERINFO_ENDPOINT'],
            token=session['oauth2_token'])
        resp.raise_for_status()
        return resp.json()

    def authenticate(self, form):
        self.oauth2_current_client = request.form['oauth2_button']
        redirect_url = url_for(OAUTH2_AUTHORIZE, _external=True)

        if self.oauth2_current_client not in self.oauth2_clients:
            return False, gettext(
                "Please set the configuration parameters properly.")
        return False, self.oauth2_clients[
            self.oauth2_current_client].authorize_redirect(redirect_url)

    def __auto_create_user(self, resp):
        if config.OAUTH2_AUTO_CREATE_USER:
            user = User.query.filter_by(username=resp['email'],
                                        auth_source=OAUTH2).first()
            if not user:
                return create_user({
                    'username': resp['email'],
                    'email': resp['email'],
                    'role': 2,
                    'active': True,
                    'auth_source': OAUTH2
                })

        return True, {'username': resp['email']}
コード例 #14
0
ファイル: __init__.py プロジェクト: terestahl/scout
"""Code for extensions used by flask"""

from flask_bootstrap import Bootstrap
from flask_debugtoolbar import DebugToolbarExtension
from flask_ldap3_login import LDAP3LoginManager
from flask_login import LoginManager
from authlib.integrations.flask_client import OAuth
from flask_mail import Mail

from scout.adapter import MongoAdapter

from .loqus_extension import LoqusDB
from .mongo_extension import MongoDB

toolbar = DebugToolbarExtension()
bootstrap = Bootstrap()
store = MongoAdapter()
login_manager = LoginManager()
ldap_manager = LDAP3LoginManager()
oauth_client = OAuth()
mail = Mail()

loqusdb = LoqusDB()
mongo = MongoDB()
コード例 #15
0
from data.models import User

bp = Blueprint("auth", __name__, url_prefix="/auth")
db = DEFAULT_DATABASE.db


def fetch_google_token():
    return session.get('google_token')


def update_google_token(token):
    session['google_token'] = token
    return session['google_token']


oauth = OAuth()  # pylint: disable=invalid-name
oauth.register(
    name='google',  # nosec
    api_base_url='https://www.googleapis.com/',
    access_token_url='https://accounts.google.com/o/oauth2/token',
    authorize_url='https://accounts.google.com/o/oauth2/auth',
    fetch_token=fetch_google_token,
    update_token=update_google_token,
    client_kwargs={'scope': 'email profile'})


@bp.route("/login", methods=["GET"])
def login():
    if is_authenticated():
        return redirect("/")
コード例 #16
0
ファイル: routes.py プロジェクト: jslee6091/python_flask
AUTH0_BASE_URL = 'https://' + AUTH0_DOMAIN
AUTH0_AUDIENCE = env.get(constants.AUTH0_AUDIENCE)

blueprint.config = {}
blueprint.config['SECRET_KEY'] = constants.SECRET_KEY
blueprint.config['DEBUG'] = True


@blueprint.errorhandler(Exception)
def handle_auth_error(ex):
    response = jsonify(message=str(ex))
    response.status_code = (ex.code if isinstance(ex, HTTPException) else 500)
    return response


oauth = OAuth(blueprint)

auth0 = oauth.register(
    'auth0',
    client_id=AUTH0_CLIENT_ID,
    client_secret=AUTH0_CLIENT_SECRET,
    api_base_url=AUTH0_BASE_URL,
    access_token_url=AUTH0_BASE_URL + '/oauth/token',
    authorize_url=AUTH0_BASE_URL + '/authorize',
    client_kwargs={
        'scope': 'openid profile email',
    },
)

config = {
    'host': 'AWS_RDS_ENDPOINT',
コード例 #17
0
    if refresh_token:
        item = OAuth2Token.filter_by(name=name, refresh_token=refresh_token).first()
    elif access_token:
        item = OAuth2Token.filter_by(name=name, access_token=access_token).first()
    else:
        return
    if not item:
        return
    # update old token
    item.access_token = token['access_token']
    item.refresh_token = token.get('refresh_token')
    item.expires_at = token['expires_at']
    db.session.commit()


oauth = OAuth(fetch_token=fetch_token, update_token=update_token)
github = oauth.register(
    name='github',
    access_token_url='https://github.com/login/oauth/access_token',
    access_token_params=None,
    authorize_url='https://github.com/login/oauth/authorize',
    authorize_params=None,
    api_base_url='https://api.github.com/',
    client_kwargs={'scope': 'user:email'},
)
google = oauth.register(
    name='google',
    access_token_url='https://www.googleapis.com/oauth2/v4/token',
    access_token_params={'grant_type': 'authorization_code'},
    authorize_url='https://accounts.google.com/o/oauth2/v2/auth?access_type=offline',
    authorize_params=None,
コード例 #18
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    app.secret_key = constants.SECRET_KEY

    setup_db(app)
    CORS(app)

    '''
    Use the after_request decorator to set Access-Control-Allow
    '''
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PATCH,POST,DELETE,OPTIONS')

        return response

    def requires_login(f):
        '''
        Decorator to enforce endpoints which require the user to be logged
        in regradless of role
        '''
        @wraps(f)
        def decorated(*args, **kwargs):
            if constants.PROFILE_KEY not in session:
                return redirect('/login')
            return f(*args, **kwargs)

        return decorated

    # OAuth setup and endpoints
    oauth = OAuth(app)

    auth0 = oauth.register(
        'auth0',
        client_id=AUTH0_CLIENT_ID,
        client_secret=AUTH0_CLIENT_SECRET,
        api_base_url=AUTH0_BASE_URL,
        access_token_url=AUTH0_BASE_URL + '/oauth/token',
        authorize_url=AUTH0_BASE_URL + '/authorize',
        client_kwargs={
            'scope': 'openid profile email',
        },
    )

    @app.route('/callback')
    def callback_handling():
        try:
            auth = auth0.authorize_access_token()
            resp = auth0.get('userinfo')
            userinfo = resp.json()
            print(userinfo)
            # store jwt in session
            session['token'] = auth['access_token']
            # store username in session
            session['user'] = userinfo['name']

            session[constants.JWT_PAYLOAD] = userinfo
            session[constants.PROFILE_KEY] = {
                'user_id': userinfo['sub'],
                'name': userinfo['name'],
                'picture': userinfo['picture']
            }
            return redirect('/dashboard')
        except Exception as e:
            print('Error on callback:', e)

    @app.route('/login')
    def login():
        '''
        Manage login flow by redirecting to Auth0
        '''
        try:
            return auth0.authorize_redirect(redirect_uri=AUTH0_CALLBACK_URL,
                                            audience=AUTH0_AUDIENCE)
        except Exception as e:
            print('Error on login:'******'/logout')
    def logout():
        session.clear()
        params = {'returnTo':
                  url_for('home', _external=True),
                  'client_id': AUTH0_CLIENT_ID}
        return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))

    @requires_login
    @app.route('/dashboard')
    def dashboard():
        '''
        Endpoint to redirect to once logged in
        '''
        return render_template(
            'dashboard.html',
            userinfo=session[constants.PROFILE_KEY],
            userinfo_pretty=json.dumps(session[constants.JWT_PAYLOAD],
                                       indent=4)
        )

    @app.route('/')
    def home():
        return render_template('home.html')

    @app.route('/actors', methods=['GET'])
    @requires_auth(permission='get:actors')
    def get_actors(payload):
        '''
        Get the full list of actors, formatted
        '''
        actors = [actor.format() for actor in Actor.query.all()]

        if len(actors) == 0:
            abort(404)

        return jsonify({
                  "success": True,
                  'status_code': 200,
                  "actors": actors
                }), 200

    @app.route('/movies', methods=['GET'])
    @requires_auth(permission='get:movies')
    def get_movies(payload):
        '''
        Get the full list of movies, formatted
        '''
        movies = [movie.format() for movie in Movie.query.all()]

        if len(movies) == 0:
            abort(404)

        return jsonify({
                  "success": True,
                  'status_code': 200,
                  "movies": movies
                }), 200

    @app.route('/actors', methods=['POST'])
    @requires_auth(permission='post:actors')
    def create_actor(payload):
        body = request.get_json()
        name = body.get('name')
        age = body.get('age')
        gender = body.get('gender')

        actor = Actor(name=name, age=age, gender=gender)

        actor.insert()

        return jsonify({
                    "success": True,
                    'status_code': 200
                }), 200

    @app.route('/movies', methods=['POST'])
    @requires_auth(permission='post:movies')
    def create_movie(payload):
        body = request.get_json()
        title = body.get('title')
        release_date = body.get('release_date')

        movie = Movie(title=title, release_date=release_date)

        movie.insert()

        return jsonify({
                    "success": True,
                    'status_code': 200
                }), 200

    @app.route('/actors/<int:id>', methods=['PATCH'])
    @requires_auth(permission='patch:actors')
    def edit_actor(payload, id):
        actor = Actor.query.filter(Actor.id == id).one_or_none()

        # Check actor exists
        if not actor:
            abort(404)

        body = request.get_json()
        actor.name = body.get('name', actor.name)
        actor.age = body.get('age', actor.age)
        actor.gender = body.get('gender', actor.gender)

        actor.update()

        return jsonify({
                    "success": True,
                    'status_code': 200,
                    "actor": actor.format()
                }), 200

    @app.route('/movies/<int:id>', methods=['PATCH'])
    @requires_auth(permission='patch:movies')
    def edit_movie(payload, id):
        movie = Movie.query.filter(Movie.id == id).one_or_none()

        # Check actor exists
        if not movie:
            abort(404)

        body = request.get_json()
        movie.title = body.get('title', movie.title)
        movie.release_date = body.get('release_date', movie.release_date)

        movie.update()

        return jsonify({
                    "success": True,
                    'status_code': 200,
                    "movie": movie.format()
                }), 200

    @app.route('/actors/<int:id>', methods=['DELETE'])
    @requires_auth(permission='delete:actors')
    def delete_actor(payload, id):
        actor = Actor.query.filter(Actor.id == id).one_or_none()

        # Check actor exists
        if not actor:
            abort(404)

        id = actor.id

        actor.delete()

        return jsonify({
                    "success": True,
                    'status_code': 200,
                    "delete": id
                }), 200

    @app.route('/movies/<int:id>', methods=['DELETE'])
    @requires_auth(permission='delete:movies')
    def delete_movie(payload, id):
        movie = Movie.query.filter(Movie.id == id).one_or_none()

        # Check movie exists
        if not movie:
            abort(404)

        id = movie.id

        movie.delete()

        return jsonify({
                    "success": True,
                    'status_code': 200,
                    "delete": id
                }), 200

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "Not found"
        }), 404

    @app.errorhandler(405)
    def not_allowed(error):
        return jsonify({
            "success": False,
            "error": 405,
            "message": "Method Not Allowed"
        }), 405

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "Unprocessable Entity"
        }), 422

    @app.errorhandler(500)
    def internal_error(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "Internal Server Error"
        }), 500

    @app.errorhandler(AuthError)
    def auth_error(error):
        return jsonify({
                        "success": False,
                        "error": "AuthError",
                        "message": "Authorization error"
                    }), AuthError

    return app
コード例 #19
0
def create_app(test_config=None):
    app = Flask(__name__, static_folder="templates/stylesheets")
    setup_db(app)
    oauth = OAuth(app)
    app.secret_key = "temp key"

    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type, Authorization, true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET, POST, DELETE, PATCH')
        response.headers.add('Access-Control-Allow-Credentials', 'true')
        return response

    auth0 = oauth.register(
        'auth0',
        client_id='yzDykpaQCAi0qMfaYnbD3pwH6nQiRgSs',
        client_secret=
        'T5ggzfkhmQMFIDj2TeHnpu75Gqn8n2UEcABKIRImMkq0N8czZ0SYFO7jYbIiTPC-',
        api_base_url='https://hackthistest.us.auth0.com',
        access_token_url='https://hackthistest.us.auth0.com/oauth/token',
        authorize_url='https://hackthistest.us.auth0.com/authorize',
        client_kwargs={
            'scope': 'openid profile email',
        },
    )

    @app.route('/login')
    def login():
        return auth0.authorize_redirect(
            redirect_uri='https://community-cafe.herokuapp.com/login-results')

    @app.route('/signup')
    def signup():
        return auth0.authorize_redirect(
            redirect_uri='https://community-cafe.herokuapp.com/signup-results')

    @app.route('/login_business')
    def business_login():
        return auth0.authorize_redirect(
            redirect_uri=
            'https://community-cafe.herokuapp.com/login-results-business')

    @app.route('/signup_business')
    def business_signup():
        return auth0.authorize_redirect(
            redirect_uri=
            'https://community-cafe.herokuapp.com/signup-results-business')

    @app.route('/login-results')
    def login_handling():
        # Handles response from token endpoint
        auth0.authorize_access_token()
        resp = auth0.get('userinfo')
        userinfo = resp.json()

        # Store the user information in flask session.
        session['jwt_payload'] = userinfo
        session['profile'] = {
            'user_id': userinfo['sub'],
            'name': userinfo['name'],
            'picture': userinfo['picture']
        }
        return redirect('/dashboard/display')

    @app.route('/signup-results')
    def signup_handling():
        # Handles response from token endpoint
        auth0.authorize_access_token()
        resp = auth0.get('userinfo')
        userinfo = resp.json()

        # Store the user information in flask session.
        session['jwt_payload'] = userinfo
        session['profile'] = {
            'user_id': userinfo['sub'],
            'name': userinfo['name'],
            'picture': userinfo['picture']
        }
        return redirect('/profile/student/create')

    @app.route('/login-results-business')
    def business_login_handling():
        # Handles response from token endpoint
        auth0.authorize_access_token()
        resp = auth0.get('userinfo')
        userinfo = resp.json()

        # Store the user information in flask session.
        session['jwt_payload'] = userinfo
        session['business_profile'] = {
            'user_id': userinfo['sub'],
            'name': userinfo['name'],
            'picture': userinfo['picture']
        }
        return redirect('/profile/business/display')

    @app.route('/signup-results-business')
    def business_signup_handling():
        # Handles response from token endpoint
        auth0.authorize_access_token()
        resp = auth0.get('userinfo')
        userinfo = resp.json()

        # Store the user information in flask session.
        session['business_jwt_payload'] = userinfo
        session['business_profile'] = {
            'user_id': userinfo['sub'],
            'name': userinfo['name'],
            'picture': userinfo['picture']
        }
        return redirect('/profile/business/create')

    def requires_auth(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            if 'profile' not in session:
                # Redirect to Login page here
                return redirect('/login')
            return f(*args, **kwargs)

        return decorated

    def requires_business_auth(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            if 'business_profile' not in session:
                # Redirect to Login page here
                return redirect('/login_business')
            return f(*args, **kwargs)

        return decorated

    @app.route('/logout')
    def logout():
        # Clear session stored data
        session.clear()
        # Redirect user to logout endpoint
        params = {
            'returnTo': url_for('index', _external=True),
            'client_id': 'yzDykpaQCAi0qMfaYnbD3pwH6nQiRgSs'
        }
        return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))

    #______________________________student endpoints___________________________________

    @app.route('/dashboard/display', methods=['GET'])
    @requires_auth
    def display_student_dashboard():
        student_id = get_student_id_from_auth_id()
        student = Student.query.get(student_id)
        student_name = student.name
        return render_template('student_dashboard.html',
                               student_id=student_id,
                               student_name=student_name)

    @app.route('/dashboard', methods=['GET'])
    @requires_auth
    def get_student_dashboard():
        student_id = get_student_id_from_auth_id()
        if student_id == 0:
            abort(400)

        student = Student.query.get(student_id)
        if not student:
            abort(404)

        student_zip_code = student.zip_code

        recommended_businesses = Business.query.filter_by(
            zip_code=student_zip_code).all()
        if not recommended_businesses:
            abort(404)

        data = []
        for business in recommended_businesses:
            data.append(business.name)
        '''
        student_zip_code = student.zip_code
        search = SearchEngine(simple_zipcode=True)
        zipcode = search.by_zipcode(student_zip_code)
        zipcode_json = zipcode.to_json()
        student_lat = zipcode_json["lat"]
        student_long = zipcode_json["long"]

        all_businesses = Business.query.filter(Business.address != None).all()
        businesses_in_zip_code = []
        #geolocator = geocode.GoogleV3(api_key='APIKEY')

        for business in all_businesses:
            if (business.zip_code == student.zip_code):
                #location = geolocator.geocode(business.address, timeout=15)
                #g = geocoder.google(business.address)
                #businesses_in_zip_code.append({
                    'id': business.id,
                    'name': business.name,
                    'latitude': g.latlng[0],
                    'longitude': g.latlng[1]
                })
        '''
        return jsonify({
            'success': True,
            'id': student_id,
            'name': student.name,
            'business_names': student.business_names,
            'recommended_count': len(recommended_businesses),
            'recommended': data
            #'student_lat': student_lat,
            #'student_long': student_long,
            #'businesses_in_zip_code': businesses_in_zip_code
        }), 200

    @app.route('/profile/student/create', methods=['GET', 'POST'])
    @requires_auth
    def create_student_profile():
        if request.method == 'GET':
            return render_template('new_student_form.html',
                                   userinfo=session['profile'])

        body = request.get_json()
        try:
            name = body.get('name')
            email = body.get('email')
            zip_code = body.get('zip_code')
            interests = body.get('interests')
            qualifications = body.get('qualifications')
            auth_id = body.get('auth_id')

            student = Student(name=name,
                              email=email,
                              zip_code=zip_code,
                              interests=interests,
                              qualifications=qualifications,
                              auth_id=auth_id)

            if not student:
                abort(404)

            student.insert()

            return jsonify({
                'success': True,
                'name': student.name,
                'email': student.email,
                'zip_code': student.zip_code,
                'interests': student.interests,
                'qualifications': student.qualifications,
                'auth_id': student.auth_id
            }), 200
        except:
            abort(422)

    @app.route('/profile/student/display', methods=['GET'])
    @requires_auth
    def display_student_profile():
        student_id = get_student_id_from_auth_id()
        return render_template('my_profile.html', student_id=student_id)

    @app.route('/profile/student', methods=['GET'])
    @requires_auth
    def get_student_profile():
        student_id = get_student_id_from_auth_id()
        if student_id == 0:
            abort(400)

        student = Student.query.get(student_id)
        if not student:
            abort(404)

        return jsonify({
            'success': True,
            'id': student_id,
            'name': student.name,
            'email': student.email,
            'zip_code': student.zip_code,
            'interests': student.interests,
            'qualifications': student.qualifications,
            'business_names': student.business_names
        }), 200

    @app.route('/profile/student/edit', methods=['GET', 'PATCH'])
    @requires_auth
    def update_student_profile():
        student_id = get_student_id_from_auth_id()
        if request.method == 'GET':
            return render_template('update_student_form.html',
                                   student_id=student_id)

        if student_id == 0:
            abort(400)

        student = Student.query.get(student_id)

        if not student:
            abort(404)

        body = request.get_json()

        try:
            name = body.get('name')
            email = body.get('email')
            zip_code = body.get('zip_code')
            interests = body.get('interests')
            qualifications = body.get('qualifications')

            if name:
                student.name = name
            if email:
                student.email = email
            if zip_code:
                student.zip_code = zip_code
            if interests:
                student_interests = interests
            if qualifications:
                student.qualifications = qualifications

            if not student:
                abort(404)

            student.update()

            return jsonify({
                'success': True,
                'name': student.name,
                'email': student.email,
                'zip_code': student.zip_code,
                'interests': student.interests,
                'qualifications': student.qualifications
            }), 200
        except:
            abort(422)

    @app.route('/profile/student', methods=['DELETE'])
    @requires_auth
    def delete_student_profile():
        student_id = get_student_id_from_auth_id()
        if student_id == 0:
            abort(400)

        student = Student.query.get(student_id)
        if not student:
            abort(404)

        student.delete()

        return jsonify({'success': True, 'id': student_id}), 200

    @app.route('/student/search', methods=['GET', 'POST'])
    @requires_auth
    def search_businesses():
        if request.method == 'GET':
            return render_template("search.html")

        body = request.get_json()
        search_term = body.get('search_term')

        businesses = Business.query.filter(
            Business.name.ilike('%{}%'.format(search_term))).all()

        if len(businesses) == 0:
            abort(404)

        data = []
        for business in businesses:
            data.append({
                "id": business.id,
                "name": business.name,
                "skills": business.skills
            })

        return jsonify({
            'success': True,
            'count': len(businesses),
            'data': data
        })

    @app.route('/profile/business/<int:business_id>/display', methods=['GET'])
    @requires_auth
    def display_business_profile_student_view(business_id):
        return render_template('business_profile_student_view.html',
                               business_id=business_id)

    @app.route('/profile/business/<int:business_id>', methods=['GET'])
    @requires_auth
    def get_business_profile_student_view(business_id):
        if business_id == 0:
            abort(400)

        business = Business.query.get(business_id)
        if not business:
            abort(404)

        return jsonify({
            'success': True,
            'id': business.id,
            'name': business.name,
            'email': business.email,
            'zip_code': business.zip_code,
            'goals': business.goals,
            'website': business.website,
            'address': business.address,
            'description': business.description,
            'skills': business.skills
        }), 200

    @app.route('/student/login', methods=['GET'])
    def login_buttons():
        return render_template('student_login.html')

    #for testing purposes
    '''
    @app.route('/listallstudents', methods=['GET'])
    def listemall():
        students = Student.query.all()
        data = []
        for student in students:
            data.append({
                "id": student.id
            })
        return jsonify({
            'success': True,
            'data': data
        })
    '''
    #_____________________________business endpoints__________________________________

    @app.route('/profile/business/create', methods=['GET', 'POST'])
    @requires_business_auth
    def create_business_profile():
        if request.method == 'GET':
            return render_template('new_business_form.html',
                                   userinfo=session['business_profile'])

        body = request.get_json()
        try:
            name = body.get('name')
            email = body.get('email')
            zip_code = body.get('zip_code')
            goals = body.get('goals')
            website = body.get('website')
            address = body.get('address')
            description = body.get('description')
            skills = body.get('skills'),
            auth_id = body.get('auth_id')

            business = Business(name=name,
                                email=email,
                                zip_code=zip_code,
                                goals=goals,
                                website=website,
                                address=address,
                                description=description,
                                skills=skills,
                                auth_id=auth_id)

            if not business:
                abort(404)

            business.insert()

            return jsonify({
                'success': True,
                'name': business.name,
                'email': business.email,
                'zip_code': business.zip_code,
                'goals': business.goals,
                'website': business.website,
                'address': business.address,
                'description': business.description,
                'skills': business.skills,
                'auth_id': business.auth_id
            }), 200
        except:
            abort(422)

    @app.route('/profile/business/display', methods=['GET'])
    @requires_business_auth
    def display_business_profile():
        business_id = get_business_id_from_auth_id()
        return render_template('business_profile_business_view.html',
                               business_id=business_id)

    @app.route('/profile/business', methods=['GET'])
    @requires_business_auth
    def get_business_profile():
        business_id = get_business_id_from_auth_id()
        if business_id == 0:
            abort(400)

        business = Business.query.get(business_id)
        if not business:
            abort(404)

        return jsonify({
            'success': True,
            'id': business.id,
            'name': business.name,
            'email': business.email,
            'zip_code': business.zip_code,
            'goals': business.goals,
            'website': business.website,
            'address': business.address,
            'description': business.description,
            'skills': business.skills
        }), 200

    @app.route('/profile/business/edit', methods=['GET', 'PATCH'])
    @requires_business_auth
    def update_business_profile():
        business_id = get_business_id_from_auth_id()
        if request.method == 'GET':
            return render_template('update_business_form.html',
                                   business_id=business_id)

        if business_id == 0:
            abort(400)

        business = Business.query.get(business_id)

        if not business:
            abort(404)

        body = request.get_json()

        try:
            name = body.get('name')
            email = body.get('email')
            zip_code = body.get('zip_code')
            goals = body.get('goals')
            website = body.get('website')
            address = body.get('address')
            description = body.get('description')
            skills = body.get('skills')

            if name:
                business.name = name
            if email:
                business.email = email
            if zip_code:
                business.zip_code = zip_code
            if goals:
                business.goals = goals
            if website:
                business.website = website
            if address:
                business.address = address
            if description:
                business.description = description
            if skills:
                business.skills = skills

            if not business:
                abort(404)

            business.update()

            return jsonify({
                'success': True,
                'id': business.id,
                'name': business.name,
                'email': business.email,
                'zip_code': business.zip_code,
                'goals': business.goals,
                'website': business.website,
                'address': business.address,
                'description': business.description,
                'skills': business.skills
            }), 200
        except:
            abort(422)

    @app.route('/profile/business', methods=['DELETE'])
    @requires_business_auth
    def delete_business_profile():
        business_id = get_business_id_from_auth_id()
        if business_id == 0:
            abort(400)

        business = Business.query.get(business_id)
        if not business:
            abort(404)

        business.delete()

        return jsonify({'success': True, 'id': business_id}), 200

    @app.route('/business/search', methods=['GET', 'POST'])
    @requires_business_auth
    def search_students():
        if request.method == 'GET':
            return render_template('search_business.html')

        body = request.get_json()
        search_term = body.get('search_term')

        students = Student.query.filter(
            Student.name.ilike('%{}%'.format(search_term))).all()

        if len(students) == 0:
            abort(404)

        data = []
        for student in students:
            data.append({
                "id": student.id,
                "name": student.name,
                "interests": student.interests
            })

        return jsonify({'success': True, 'count': len(students), 'data': data})

    @app.route('/profile/student/<int:student_id>/display', methods=['GET'])
    @requires_business_auth
    def display_student_profile_business_view(student_id):
        return render_template('student_profile_business_view.html',
                               student_id=student_id)

    @app.route('/profile/student/<int:student_id>', methods=['GET'])
    @requires_business_auth
    def get_student_profile_business_view(student_id):
        if student_id == 0:
            abort(400)

        student = Student.query.get(student_id)
        if not student:
            abort(404)

        return jsonify({
            'success': True,
            'id': student_id,
            'name': student.name,
            'email': student.email,
            'zip_code': student.zip_code,
            'interests': student.interests,
            'qualifications': student.qualifications
        }), 200

    @app.route('/business/login', methods=['GET'])
    def business_login_buttons():
        return render_template('business_login.html')

    #___________________________endpoints for everyone!________________________________

    @app.route('/')
    def index():
        return render_template('home.html'), 200

    #_______________________________error handlers____________________________________

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(404)
    def resource_not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found - PLEASE REFRESH PAGE"
        }), 404

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "bad request"
        }), 400

    @app.errorhandler(403)
    def bad_login(error):
        return jsonify({
            "success": False,
            "error": 403,
            "message": "bad login"
        }), 403

    return app
コード例 #20
0
ファイル: spotify_oauth.py プロジェクト: gniall12/shuff
from .config import (
    auth_base_url, token_base_url, client_id,
    client_secret, scope, base_url
)

log = logging.getLogger(__name__)


def get_spotify_oauth_token(name):
    try:
        return session['access_token']
    except KeyError:
        abort(400, 'No access token')


oauth = OAuth(fetch_token=get_spotify_oauth_token)

oauth.register(
    name='spotify',
    client_id=client_id,
    client_secret=client_secret,
    access_token_url=token_base_url,
    authorize_url=auth_base_url,
    authorize_params={'scope': scope, 'show_dialog': True},
    api_base_url=base_url,
)


def get_user_id():
    log.info('Getting user id')
    user = oauth.spotify.get('me')
コード例 #21
0
def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__)
    setup_db(app)
    CORS(app)
    migrate = Migrate(app, db)
    app.secret_key = "udacity"

    # ------------------------------------------------------------------------
    # set Access-Control-allow, API Configuration
    # ------------------------------------------------------------------------
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type, Authorization, true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PUT,POST,PUT,PATCH,DELETE,OPTIONS')
        return response

    oauth = OAuth(app)

    auth0 = oauth.register(
        'auth0',
        client_id='4bH07NXNIJ02BMCRkZsN85JYRDkB4sVI',
        client_secret='udacity',
        api_base_url='https://dev-mrlzc2vg.us.auth0.com',
        access_token_url='https://dev-mrlzc2vg.us.auth0.com' + '/oauth/token',
        authorize_url='https://dev-mrlzc2vg.us.auth0.com' + '/authorize',
        client_kwargs={
            'scope': 'openid profile email',
        },
    )

    # --------------------------------------------------------------------------
    # Custom Functions
    # --------------------------------------------------------------------------

    def paginate_movies(request, selection):
        page = request.args.get('page', 1, type=int)

        # determine the movies for each page
        start = (page - 1) * MOVIES_PER_PAGE
        end = start + MOVIES_PER_PAGE

        formatted_movies = [movie.format() for movie in selection]
        current_movies = formatted_movies[start:end]
        return current_movies

    def paginate_actors(request, selection):
        page = request.args.get('page', 1, type=int)

        # determine the actors for each page
        start = (page - 1) * ACTORS_PER_PAGE
        end = start + ACTORS_PER_PAGE

        formatted_actors = [actor.format() for actor in selection]
        current_actors = formatted_actors[start:end]
        return current_actors

    @app.route('/')
    def index():
        return render_template('index.html')

    @app.route('/login_result')
    def login_result():
        return render_template('index.html')

    @app.route('/logout')
    def logout():
        # Clear session stored data
        session.clear()
        # Redirect user to logout endpoint
        params = {
            'returnTo': url_for('index', _external=True),
            'client_id': '4bH07NXNIJ02BMCRkZsN85JYRDkB4sVI'
        }
        return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))

    # -------------------------------------------------------------------------
    # API endpoints : movies GET/POST/DELETE/PATCH
    # -------------------------------------------------------------------------

    # GET MOVIES
    @app.route('/movies', methods=['GET'])
    @requires_auth('read:movie')
    def get_movies(payload):

        movies = Movie.query.all()
        current_movies = paginate_movies(request, movies)

        # if there are no movies abort 404
        if len(current_movies) == 0:
            abort(404)

        # return data to view
        return jsonify({
            'success': True,
            'movies': current_movies,
            'total_movies': len(movies)
        }), 200

    # CREATE / SEARCH MOVIES
    @app.route('/movies/search', methods=['POST'])
    @requires_auth('post:movie')
    def create_search_movie(payload):
        # Get request json
        body = request.get_json()

        if body is None:
            abort(400)

        # load data from body
        new_title = body.get('title', None)
        new_release_date = body.get('release_date', None)
        search = body.get('searchTerm', None)
        if not search:
            # ensure all fields have data
            if not new_title:
                abort(422)
            if not new_release_date:
                abort(422)

        try:
            if search:
                selection = Movie.query.order_by(Movie.id) \
                    .filter(Movie.title.ilike('%{}%'.format(search)))
                current_movies = paginate_movies(request, selection)

                # return data to view
                return jsonify({
                    'success': True,
                    'movies': current_movies,
                    'total_movies': len(Movie.query.all())
                }), 200
            else:

                # create and insert new movie
                movie = Movie(title=new_title, release_date=new_release_date)
                movie.insert()

                movies = Movie.query.all()
                formatted_movies = [movie.format() for movie in movies]

                # return data to view
                return jsonify({
                    'success': True,
                    'created': movie.id,
                    'movies': formatted_movies,
                    'total_movies': len(movies)
                }), 200
        except:
            abort(401)

    # DELETE MOVIE
    @app.route('/movies/<int:movie_id>', methods=['DELETE'])
    @requires_auth('delete:movie')
    def delete_movie(payload, movie_id):
        # Abort if no movie_id has been provided
        if not movie_id:
            abort(400)

        # get the movie should be deleted
        movie = Movie.query.filter(Movie.id == movie_id).one_or_none()

        # if no movie found abort 404
        if movie is None:
            abort(404)
        try:
            # delete the movie
            movie.delete()

            movies = Movie.query.all()
            formatted_movies = [movie.format() for movie in movies]

            # return success response
            return jsonify({
                'success': True,
                'deleted': movie_id,
                'movies': formatted_movies,
                'total_movies': len(movies)
            }), 200
        except:
            # if problem deleting
            abort(422)

    # UPDATE MOVIE
    @app.route('/movies/<int:movie_id>', methods=['PATCH'])
    @requires_auth('update:movie')
    def update_movie(payload, movie_id):
        body = request.get_json()

        if not movie_id:
            abort(400)

        if not body:
            abort(400)

        # get the movie
        movie = Movie.query.filter(Movie.id == movie_id).one_or_none()

        # if no movie found abort 404
        if movie is None:
            abort(404)
        try:
            if 'title' in body:
                movie.title = body.get('title')
            if 'release_date' in body:
                movie.release_date = body.get('release_date')

            # update the movie
            movie.update()

            movies = Movie.query.all()
            formatted_movies = [movie.format() for movie in movies]

            # return success response
            return jsonify({
                'success': True,
                'updated': movie_id,
                'movies': formatted_movies,
                'total_movies': len(movies)
            }), 200
        except:
            # if problem updating
            abort(401)

    # GET MOVIES BY ACTOR
    @app.route('/actors/<actor_id>/movies', methods=['GET'])
    @requires_auth('read:movie')
    def get_movies_by_actor(payload, actor_id):
        performances = Performance.query.filter(
            Performance.actor_id == actor_id).all()

        if len(performances) == 0:
            abort(404)

        movies = {}
        for movie in performances:
            movie_actor = Movie.query.filter(
                Movie.id == movie.movie_id).first()
            movies[movie.id] = movie_actor.format()

        return jsonify({
            'success': True,
            'movies': movies,
            'total_movies_by_actor': len(movies)
        }), 200

    # ------------------------------------------------------------------------
    # API endpoints : actors GET/POST/DELETE/PATCH
    # ------------------------------------------------------------------------

    # GET ACTORS
    @app.route('/actors', methods=['GET'])
    @requires_auth('read:movie')
    def get_actors(payload):
        actors = Actor.query.all()
        current_actors = paginate_actors(request, actors)

        # if there are no actors abort 404
        if len(current_actors) == 0:
            abort(404)

        # return data to view
        return jsonify({
            'success': True,
            'actors': current_actors,
            'total_actors': len(actors)
        }), 200

    # CREATE / SEARCH BY NAME
    @app.route('/actors/search', methods=['POST'])
    @requires_auth('post:actor')
    def create_search_actor(payload):
        # Get request json
        body = request.get_json()

        if body is None:
            abort(400)

        # load data from body
        new_name = body.get('name', None)
        new_age = body.get('age', None)
        new_gender = body.get('gender', None)
        search = body.get('searchTerm', None)

        try:
            if search:
                selection = Actor.query.order_by(Actor.id) \
                    .filter(Actor.name.ilike('%{}%'.format(search)))
                current_actors = paginate_actors(request, selection)

                # return data to view
                return jsonify({
                    'success': True,
                    'actors': current_actors,
                    'total_actors': len(Actor.query.all())
                }), 200
            else:
                # ensure all fields have data
                if not new_name or not new_age or not new_gender:
                    abort(422)

                # create and insert new movie
                actor = Actor(name=new_name, age=new_age, gender=new_gender)
                actor.insert()

                actors = Actor.query.all()
                formatted_actors = [actor.format() for actor in actors]

                # return data to view
                return jsonify({
                    'success': True,
                    'created': actor.id,
                    'actors': formatted_actors,
                    'total_actors': len(actors)
                }), 200
        except:
            abort(422)

    # DELETE ACTOR
    @app.route('/actors/<int:actor_id>', methods=['DELETE'])
    @requires_auth('delete:actor')
    def delete_actor(payload, actor_id):
        # get the actor
        actor = Actor.query.filter(Actor.id == actor_id).one_or_none()

        # if no actor found abort 404
        if actor is None:
            abort(404)
        try:
            # delete the actor
            actor.delete()

            actors = Actor.query.all()
            formatted_actors = [actor.format() for actor in actors]

            # return success response
            return jsonify({
                'success': True,
                'deleted': actor_id,
                'actors': formatted_actors,
                'total_actors': len(actors)
            }), 200
        except:
            # if problem deleting
            abort(422)

    # UPDATE ACTOR
    @app.route('/actors/<int:actor_id>', methods=['PATCH'])
    @requires_auth('update:actor')
    def update_actor(payload, actor_id):
        body = request.get_json()

        if not actor_id:
            abort(400)

        if not body:
            abort(400)

        # get the actor
        actor = Actor.query.filter(Actor.id == actor_id).one_or_none()

        # if no actor found abort 404
        if actor is None:
            abort(404)
        try:
            if 'name' in body:
                actor.name = body.get('name')
            if 'age' in body:
                actor.age = int(body.get('age'))
            if 'gender' in body:
                actor.gender = body.get('gender')

            # update the actor
            actor.update()

            actors = Actor.query.all()
            formatted_actors = [actor.format() for actor in actors]

            # return success response
            return jsonify({
                'success': True,
                'updated': actor_id,
                'actors': formatted_actors,
                'total_actors': len(actors)
            }), 200
        except:
            # if problem updating
            abort(401)

    # GET ACTORS BY MOVIE
    @app.route('/movies/<movie_id>/actors', methods=['GET'])
    @requires_auth('read:actor')
    def get_actors_by_movie(payload, movie_id):
        performances = Performance.query.filter(
            Performance.movie_id == movie_id).all()

        if len(performances) == 0:
            abort(404)

        actors = {}
        for actor in performances:
            actor_movie = Actor.query.filter(
                Actor.id == actor.actor_id).first()
            actors[actor.id] = actor_movie.format()

        return jsonify({
            'success': True,
            'actors': actors,
            'total_actors_by_movie': len(actors)
        }), 200

    # ------------------------------------------------------------------------------------
    # Error handler
    # ------------------------------------------------------------------------------------

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            'success': False,
            'error': 404,
            'message': 'Resource not found'
        }), 404

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            'success': False,
            'error': 422,
            'message': 'unprocessable'
        }), 422

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            'success': False,
            'error': 400,
            'message': 'bad request'
        }), 400

    @app.errorhandler(401)
    def unauthorized_error(error):
        return jsonify({
            'success': False,
            'error': 401,
            'message': 'unauthorized'
        }), 401

    @app.errorhandler(403)
    def unauthorized_error(error):
        return jsonify({
            'success': False,
            'error': 403,
            'message': 'Permission not found'
        }), 403

    return app
コード例 #22
0
from six.moves.urllib.parse import urlencode
import os
import sys
import json


def create_app(test_config=None):
    app = Flask(__name__)
    app.secret_key = os.getenv("FLASK_SECRET_KEY")
    setup_db(app)
    CORS(app)
    return app


APP = create_app()
oauth = OAuth(APP)

auth0_url = 'https://' + os.getenv('AUTH0_DOMAIN')

auth0 = oauth.register(
    'auth0',
    client_id=os.getenv("CLIENT_ID"),
    client_secret=os.getenv('AUTH0_SECRET'),
    api_base_url=auth0_url,
    access_token_url=auth0_url + '/oauth/token',
    authorize_url=auth0_url + '/authorize',
    client_kwargs={
        'scope': 'openid profile email',
    },
)
AD_OBSERVATORY_COGNITO_ACCESS_TOKEN_URL = (COGNITO_ACCESS_TOKEN_URL_TEMPLATE %
                                           AD_OBSERVATORY_COGNITO_HOST)
AD_OBSERVATORY_COGNITO_LOGIN_URL = COGNITO_LOGIN_URL_TEMPLATE % AD_OBSERVATORY_COGNITO_HOST
AD_OBSERVATORY_COGNITO_USERINFO_URL = COGNITO_USERINFO_URL_TEMPLATE % AD_OBSERVATORY_COGNITO_HOST

# TODO(macpd): centralize setting and use.
AD_SCREENER_OAUTH_REDIRECT_URL = os.environ['AD_SCREENER_OAUTH_REDIRECT_URL']
AD_OBSERVATORY_OAUTH_REDIRECT_URL = os.environ[
    'AD_OBSERVATORY_OAUTH_REDIRECT_URL']
AD_OBSERVATORY_AUTHORIZATION_SUCCESS_REDIRECT_URL = (
    os.environ['AD_OBSERVATORY_AUTHORIZATION_SUCCESS_REDIRECT_URL'])

AD_SCREENER_OAUTH_CLIENT_NAME = 'ad_screener_cognito'
AD_OBSERVATORY_OAUTH_CLIENT_NAME = 'ad_observatory_cognito'

oauth = OAuth()

oauth.register(name=AD_SCREENER_OAUTH_CLIENT_NAME,
               client_id=os.environ['AD_SCREENER_OAUTH_CLIENT_ID'],
               client_secret=os.environ['AD_SCREENER_OAUTH_CLIENT_SECRET'],
               access_token_url=AD_SCREENER_COGNITO_ACCESS_TOKEN_URL,
               access_token_params={
                   'grant_type': 'authorization_code',
                   'client_id': os.environ['AD_SCREENER_OAUTH_CLIENT_ID'],
                   'redirect_uri': AD_SCREENER_OAUTH_REDIRECT_URL,
                   'scope':
                   'aws.cognito.signin.user.admin email openid profile'
               },
               authorize_url=AD_SCREENER_COGNITO_LOGIN_URL,
               authorize_params={
                   'redirect_uri': AD_SCREENER_OAUTH_REDIRECT_URL,
コード例 #24
0
    DEBUG = True


# ######################## APP PREP #####################################

# # create and configure the app
application = Flask(__name__)

if ENV == 'DEV':
    # load the dev config
    application.config.from_object(DevelopmentConfig())
else:
    # load the prod config
    application.config.from_object(ProductionConfig())

oauth = OAuth(application)

auth0 = oauth.register(
    'auth0',
    client_id=AUTH0_CLIENT_ID,
    client_secret=AUTH0_CLIENT_SECRET,
    api_base_url=AUTH0_BASE_URL,
    access_token_url=AUTH0_BASE_URL + '/oauth/token',
    authorize_url=AUTH0_BASE_URL + '/authorize',
    client_kwargs={
        'scope': 'openid profile email',
    },
)


@application.errorhandler(Exception)
コード例 #25
0
ファイル: app.py プロジェクト: alexsandberg/plant-survey-app
def create_app(test_config=None):

    # set up environment variables using dotenv
    ENV_FILE = find_dotenv()
    if ENV_FILE:
        load_dotenv(ENV_FILE)

    # set up Auth0
    AUTH0_CALLBACK_URL = env.get(constants.AUTH0_CALLBACK_URL)
    AUTH0_CLIENT_ID = env.get(constants.AUTH0_CLIENT_ID)
    AUTH0_CLIENT_SECRET = env.get(constants.AUTH0_CLIENT_SECRET)
    AUTH0_DOMAIN = env.get(constants.AUTH0_DOMAIN)
    AUTH0_BASE_URL = 'https://' + AUTH0_DOMAIN
    AUTH0_AUDIENCE = env.get(constants.AUTH0_AUDIENCE)

    # set up Flask app
    app = Flask(__name__)
    setup_db(app)
    app.secret_key = constants.SECRET_KEY

    # set up OAuth
    oauth = OAuth(app)
    auth0 = oauth.register(
        'auth0',
        client_id=AUTH0_CLIENT_ID,
        client_secret=AUTH0_CLIENT_SECRET,
        api_base_url=AUTH0_BASE_URL,
        access_token_url=AUTH0_BASE_URL + '/oauth/token',
        authorize_url=AUTH0_BASE_URL + '/authorize',
        client_kwargs={
            'scope': 'openid profile email preferred_username',
        },
    )

    # set up CORS, allowing all origins
    CORS(app, resources={'/': {'origins': '*'}})

    @app.after_request
    def after_request(response):
        '''
        Sets access control.
        '''
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PUT,PATCH,POST,DELETE,OPTIONS')
        return response

    def login_required(f):
        @wraps(f)
        def wrap(*args, **kwargs):
            if 'logged_in' in session:
                return f(*args, **kwargs)
            else:
                flash('You need to sign in first')
                return render_template('pages/login.html'), 200

        return wrap

    # add login link function to jinja context
    app.jinja_env.globals.update(create_login_link=create_login_link)

    # UTILITY FUNCTIONS

    # plant formatting
    def format_plants(plants):
        return [plant.format() for plant in plants]

    # observation formatting
    def format_observations(observations):
        return [observation.format() for observation in observations]

    # get Auth0 management API token
    def get_mgmt_token():

        data = {
            'grant_type': 'client_credentials',
            'client_id': AUTH0_CLIENT_ID,
            'client_secret': AUTH0_CLIENT_SECRET,
            'audience': 'https://plant-survey.auth0.com/api/v2/'
        }

        resp = requests.post(
            'https://plant-survey.auth0.com/oauth/token',
            data=data,
            headers={'content-type': 'application/x-www-form-urlencoded'})
        info = resp.json()
        mgmt_token = info['access_token']

        return mgmt_token

    # check if user is in database
    def check_if_user_exists(user_id):

        # look in Users table for user
        user = User.query.filter_by(user_id=user_id).one_or_none()

        # if user not found return false
        if user is None:
            return False
        else:
            return True

    # add 'Public' role to user
    def add_public_role(user_id, mgmt_token):

        # Auth0 public role ID
        PUBLIC_ROLE_ID = 'rol_X9T29OUlO7kYdItp'

        # request body
        data = {"roles": [PUBLIC_ROLE_ID]}

        # call management API with user_id and role
        role_resp = requests.post(
            f'https://plant-survey.auth0.com/api/v2/users/{user_id}/roles',
            headers={'Authorization': f"Bearer {mgmt_token}"},
            json=data)

        # raises exception for any 4xx or 5xx errors
        role_resp.raise_for_status()

    # add user if not in database
    def create_new_user(user):

        # create new user
        new_user = User(name=user['name'],
                        username=user['username'],
                        user_id=user['user_id'],
                        date_added=user['date_added'],
                        role=user['role'])

        try:
            # insert new user in Users table
            new_user.insert()
        except Exception as e:
            print('ERROR: ', str(e))
            abort(422)

        return new_user.id

    # AUTH ROUTES

    @app.route('/callback')
    def callback_handling():
        token = auth0.authorize_access_token()
        # print('TOKEN: ', token['access_token'])

        # get user info and store user id
        resp = auth0.get('userinfo')
        userinfo = resp.json()
        user_id = userinfo['sub']
        # print('ID: ', user_id)

        # store user info
        user = {'user_id': user_id}

        # check if user exists in Users table
        if check_if_user_exists(user_id):

            # get user info from Users table
            user_table_id = User.query.filter_by(
                user_id=user_id).one_or_none().id
            name = User.query.filter_by(user_id=user_id).one_or_none().name
            username = User.query.filter_by(
                user_id=user_id).one_or_none().username
            date_added = User.query.filter_by(
                user_id=user_id).one_or_none().date_added
            role = User.query.filter_by(user_id=user_id).one_or_none().role

            # add to user info
            user['user_table_id'] = user_table_id
            user['name'] = name
            user['username'] = username
            user['date_added'] = date_added
            user['role'] = role

        # if no, create new user
        else:
            # get management API token
            mgmt_token = get_mgmt_token()
            # print('MGMT TOKEN: ', mgmt_token)

            # set new user role to 'Public' on Auth0
            add_public_role(user_id, mgmt_token)
            user['role'] = 'Public'

            # get additional user info from management api
            user_resp = requests.get(
                f'https://plant-survey.auth0.com/api/v2/users/{user_id}',
                headers={'Authorization': f"Bearer {mgmt_token}"})
            id_info = user_resp.json()

            # get username from response
            if 'username' in id_info:
                username = id_info['username']
            elif 'name' in id_info:
                username = id_info['name']
            else:
                username = id_info['email']

            user['username'] = username
            user['name'] = id_info['name']

            # set date added to now
            user['date_added'] = datetime.utcnow()

            # add new user to Users table, save user_table_id
            user_table_id = create_new_user(user)
            user['user_table_id'] = user_table_id

        # add session variables
        session['logged_in'] = True
        session[constants.JWT_PAYLOAD] = userinfo
        session[constants.JWT] = token['access_token']
        session[constants.PROFILE_KEY] = user

        return redirect('/dashboard')

    @app.route('/login')
    def login():
        return auth0.authorize_redirect(redirect_uri=AUTH0_CALLBACK_URL,
                                        audience=AUTH0_AUDIENCE)

    @app.route('/logout')
    def logout():
        session.clear()
        params = {
            'returnTo': url_for('home', _external=True),
            'client_id': AUTH0_CLIENT_ID
        }
        return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))

    @app.route('/favicon.ico')
    def favicon():
        return redirect('https://img.icons8.com/color/48/000000/flower.png')

    # ------------------------------------
    # ROUTES
    # ------------------------------------

    @app.route('/dashboard')
    def dashboard():

        # if no active jwt, render login page
        if 'JWT' not in session:
            return render_template('pages/login.html'), 200

        # get user from Users table
        user_table_id = User.query.filter_by(
            user_id=session['profile']['user_id']).one_or_none().id

        # get all plants and observations that match user
        plants = Plant.query.filter_by(user_id=user_table_id).all()
        observations = Observation.query.filter_by(user_id=user_table_id).all()

        # format all plants and observations
        if (len(plants) != 0):
            plants = format_plants(plants)

        if (len(observations) != 0):
            observations = format_observations(observations)

        return render_template('/pages/dashboard.html',
                               userinfo=session[constants.PROFILE_KEY],
                               plants=plants,
                               observations=observations)

    # home page route handler
    @app.route('/')
    def home():

        return redirect('plants')

    @app.route('/about')
    def about():

        return render_template('/pages/about.html'), 200

    @app.route('/plants')
    def plants():
        '''
        Handles GET requests for getting all plants.
        '''

        # get all plants from API
        response = get_plants_api()
        data = json.loads(response.data)
        plants = data['plants']

        # return template with plants
        return render_template('pages/plants.html', plants=plants), 200

    @app.route('/plants/<int:id>')
    def get_plant_by_id(id):

        # get plant by id from API
        response = get_plant_by_id_api(id)
        data = json.loads(response.data)
        plant = data['plant']

        # serve plant page with plant result
        return render_template('pages/plant.html', plant=plant), 200

    @app.route('/plants/new')
    @login_required
    @requires_auth('post:plants')
    def new_plant_form(jwt):
        '''
        Handles GET requests for new plant form page.
        '''
        # return new plant form
        return render_template('forms/new_plant.html'), 200

    @app.route('/plants/<int:id>/edit')
    @login_required
    @requires_auth('edit_or_delete:plants')
    def get_edit_plant_form(*args, **kwargs):
        '''
        Handles GET requests for edit plant form.
        '''

        # get id from kwargs
        id = kwargs['id']

        # get plant by id
        plant = Plant.query.filter_by(id=id).one_or_none()

        # return edit plant template with plant info
        return render_template('forms/edit_plant.html',
                               plant=plant.format()), 200

    @app.route('/observations')
    def get_plant_observations():
        '''
        Handles GET requests for getting all observations.
        '''

        # get all plant observations from API
        response = get_observations_api()
        data = json.loads(response.data)
        observations = data['observations']

        # return template with observations
        return render_template('pages/observations.html',
                               observations=observations), 200

    @app.route('/observations/new')
    @login_required
    @requires_auth('post:observations')
    def new_observation_form(jwt):
        '''
        Handles GET requests for new plant form page.
        '''

        # redirect to observations if plant id not included
        if 'plant' not in request.args:
            return redirect('/observations')

        # get args from request
        plant_id = request.args.get('plant')

        # get plant by id
        plant = Plant.query.filter_by(id=plant_id).one_or_none()

        # abort 404 if not found
        if plant is None:
            abort(404)

        # return new plant form
        return render_template('forms/new_observation.html',
                               plant=plant.format()), 200

    @app.route('/observations/<int:id>/edit')
    @login_required
    @requires_auth('edit_or_delete:observations')
    def get_edit_observation_form(*args, **kwargs):
        '''
        Handles GET requests for edit observation form.
        '''

        # get id from kwargs
        id = kwargs['id']

        # get plant by id
        observation = Observation.query.filter_by(id=id).one_or_none()

        # return edit plant template with plant info
        return render_template('forms/edit_observation.html',
                               observation=observation.format()), 200

    # API ROUTES

    @app.route('/api/plants')
    def get_plants_api():
        '''
        Handles API GET requests for getting all plants. Returns JSON.
        '''

        # get all plants from database
        plants = Plant.query.all()

        # 404 if no plants found
        if len(plants) == 0:
            abort(404)

        # format each plant
        plants = format_plants(plants)

        # return plants
        return jsonify({'success': True, 'plants': plants})

    @app.route('/api/plants/<int:id>')
    def get_plant_by_id_api(id):
        '''
        Handles API GET requests for getting plant by ID. Returns JSON.
        '''

        # get plant by ID
        plant = Plant.query.filter_by(id=id).one_or_none()

        # 404 if no plants found
        if plant is None:
            abort(404)

        # return formatted plant
        return jsonify({'success': True, 'plant': plant.format()})

    @app.route('/api/plants/new', methods=['POST'])
    @requires_auth('post:plants')
    def new_plant_api(jwt):

        # get request body
        body = request.get_json()

        # get user table id from session or jwt
        if 'profile' in session:
            user_id = session['profile']['user_table_id']
        else:
            auth0_user_id = jwt['sub']
            user_id = User.query.filter_by(
                user_id=auth0_user_id).one_or_none().id

        # load plant form data
        name = body.get('name')
        latin_name = body.get('latinName')
        description = body.get('description')
        image_link = body.get('imageLink')

        # ensure all fields have data
        if ((name == "") or (latin_name == "") or (description == "")
                or (image_link == "")):
            abort(422)

        # create a new plant
        plant = Plant(user_id=user_id,
                      name=name,
                      latin_name=latin_name,
                      description=description,
                      image_link=image_link)

        try:
            # add plant to the database
            plant.insert()
        except Exception as e:
            print('ERROR: ', str(e))
            abort(422)

        # flash success message
        flash(f'Plant {name} successfully created!')

        return jsonify({'success': True, 'plant': plant.format()})

    @app.route('/api/plants/<int:id>/edit', methods=['PATCH', 'DELETE'])
    @requires_auth('edit_or_delete:plants')
    def edit_or_delete_plant_api(*args, **kwargs):
        '''
        Handles API PATCH and DELETE requests for plants.
        '''

        # get id from kwargs
        id = kwargs['id']

        # get plant by id
        plant = Plant.query.filter_by(id=id).one_or_none()

        # abort 404 if no plant found
        if plant is None:
            abort(404)

        # if PATCH
        if request.method == 'PATCH':

            # get request body
            body = request.get_json()

            # get all keys from request body
            body_keys = []
            for key in body:
                body_keys.append(key)

            # make sure correct keys are present
            if sorted(body_keys) != sorted(
                ['name', 'latinName', 'description', 'imageLink']):
                abort(422)

            # update plant with data from body
            if body.get('name'):
                plant.name = body.get('name')

            if body.get('latinName'):
                plant.latin_name = body.get('latinName')

            if body.get('description'):
                plant.description = body.get('description')

            if body.get('imageLink'):
                plant.image_link = body.get('imageLink')

            try:
                # update plant in database
                plant.insert()
            except Exception as e:
                print('ERROR: ', str(e))
                abort(422)

            # flash success message
            flash(f'Plant {plant.name} successfully updated.')

            # return plant if success
            return jsonify({"success": True, "plant": plant.format()})

        # if DELETE
        if request.method == 'DELETE':

            # save plant name
            plant_name = plant.name

            # first delete all observations related to plant
            observations = Observation.query.filter_by(plant_id=id).all()
            for observation in observations:
                observation.delete()

            try:
                # delete plant from the database
                plant.delete()
            except Exception as e:
                print('ERROR: ', str(e))
                abort(422)

            # flash success message
            flash(f'Plant {plant_name} successfully deleted.')

            # return if successfully deleted
            return jsonify({
                "success": True,
                "plant_name": plant_name,
                "plant_id": id
            })

    @app.route('/api/observations')
    def get_observations_api():
        '''
        Handles API GET requests for getting all observations. Returns JSON.
        '''

        # get all observations from database
        observations = Observation.query.all()

        # 404 if no observations found
        if len(observations) == 0:
            abort(404)

        # format each observation
        observations = format_observations(observations)

        # return observations
        return jsonify({'success': True, 'observations': observations})

    @app.route('/api/observations/<int:id>')
    def get_observation_by_id_api(id):
        '''
        Handles API GET requests for getting observation by id. Returns JSON.
        '''

        # get observation from database by id
        observation = Observation.query.filter_by(id=id).one_or_none()

        # 404 if no observation found
        if observation is None:
            abort(404)

        # return formatted observation
        return jsonify({'success': True, 'observation': observation.format()})

    @app.route('/api/observations/new', methods=['POST'])
    @requires_auth('post:observations')
    def post_plant_observation_api(jwt):
        '''
        Handles API POST requests for adding new observation.
        '''

        # get request body
        body = request.get_json()

        # get user table id from session or jwt
        if 'profile' in session:
            user_id = session['profile']['user_table_id']
        else:
            auth0_user_id = jwt['sub']
            user_id = User.query.filter_by(
                user_id=auth0_user_id).one_or_none().id

        # load observation body data
        plant_id = body.get('plantID')
        date = body.get('date')
        notes = body.get('notes')

        # ensure required fields have data
        if ((date == '') or (plant_id == '')):
            abort(422)

        # create a new observation
        observation = Observation(user_id=user_id,
                                  date=date,
                                  plant_id=plant_id,
                                  notes=notes)

        try:
            # add observation to the database
            observation.insert()
        except Exception as e:
            print('ERROR: ', str(e))
            abort(422)

        # flash success message
        flash('Observation successfully created!')

        # return observation
        return jsonify({'success': True, 'observation': observation.format()})

    @app.route('/api/observations/<int:id>/edit', methods=['PATCH', 'DELETE'])
    @requires_auth('edit_or_delete:observations')
    def edit_or_delete_observation_api(*args, **kwargs):
        '''
        Handles PATCH and DELETE requests for observations.
        '''

        # get id from kwargs
        id = kwargs['id']

        # get jwt from args
        jwt = args[0]

        # get observation by id
        observation = Observation.query.filter_by(id=id).one_or_none()

        # abort 404 if no observation found
        if observation is None:
            abort(404)

        # get user table id from session or jwt
        if 'profile' in session:
            user_id = session['profile']['user_table_id']
        else:
            auth0_user_id = jwt['sub']
            user_id = User.query.filter_by(
                user_id=auth0_user_id).one_or_none().id

        # abort if request user_id doesn't match observation user_id
        # users can only edit/delete their own observations
        if observation.user_id != user_id:
            abort(401)

        # if PATCH
        if request.method == 'PATCH':

            # get request body
            body = request.get_json()

            # get all keys from request body
            body_keys = []
            for key in body:
                body_keys.append(key)

            # make sure correct keys are present
            if sorted(body_keys) != sorted(['date', 'notes']):
                abort(422)

            # update observation with data from body
            if body.get('date'):
                observation.date = body.get('date')

            if body.get('notes'):
                observation.notes = body.get('notes')

            try:
                # update observation in database
                observation.insert()
            except Exception as e:
                print('ERROR: ', str(e))
                abort(422)

            # flash success message
            flash('Observation successfully updated!')

            # return observation if success
            return jsonify({
                "success": True,
                "observation": observation.format()
            })

        # if DELETE
        if request.method == 'DELETE':

            # save observation id
            observation_id = observation.id

            try:
                # delete observation from the database
                observation.delete()
            except Exception as e:
                print('ERROR: ', str(e))
                abort(422)

            # flash success message
            flash('Observation successfully deleted!')

            # return success
            return jsonify({"success": True, "observation_id": observation_id})

    @app.route('/api/key')
    def get_api_key():
        '''
        Endpoint for getting API key for curl requests and testing
        '''

        return render_template('/pages/api_key.html')

    # Error Handling
    '''
    Error handling for unprocessable entity
    '''

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    '''
    Error handling for resource not found
    '''

    @app.errorhandler(404)
    def resource_not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    '''
    Error handling for method not allowed
    '''

    @app.errorhandler(405)
    def method_not_allowed(error):
        return jsonify({
            "success": False,
            "error": 405,
            "message": "method not allowed"
        }), 405

    '''
    Error handling for bad request
    '''

    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "bad request"
        }), 400

    '''
    Error handling for AuthError
    '''

    @app.errorhandler(AuthError)
    def handle_auth_error(ex):
        message = ex.error['description']
        response = jsonify(ex.error)
        response.status_code = ex.status_code
        print('AUTH ERROR: ', response.get_data(as_text=True))
        flash(f'{message} Please login.')
        return redirect('/')

    return app
コード例 #26
0
from authlib.integrations.flask_client import OAuth

from statsapp.models.oauth import fetch_token, OAuth2Token

oauth = OAuth(fetch_token=fetch_token, update_token=OAuth2Token.update_token)

from .withings import WithingsAPI
コード例 #27
0
def create_app(test_config=None):
    app = Flask(__name__)
    app.config.from_object('config')
    db.init_app(app)
    migrate = Migrate(app, db)

    # Configuring Auth0 Credentials

    oauth = OAuth(app)

    auth0 = oauth.register(
        'auth0',
        client_id=os.environ.get('client_id'),
        client_secret=os.environ.get('client_secret'),
        api_base_url=os.environ.get('api_base_url'),
        access_token_url=os.environ.get('access_token_url'),
        authorize_url=os.environ.get('authorize_url'),
        client_kwargs={
            'scope': 'openid profile email',
        },
    )

    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                             'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                             'GET,PATCH,POST,DELETE,OPTIONS')
        return response

    # Endpoints

    @app.route('/')
    def index():
        """
        Returns:
            The main page
        """
        return render_template('index.html')

    @app.route('/movies', methods=['GET'])
    @requires_auth('get:movies')
    def get_movies(jwt):
        """
        Returns:
            The list of all movies
        """
        try:

            movies = Movie.query.all()

            return jsonify({
                'success': True,
                "movies": [movie.id for movie in movies]
            })
        except Exception as e:
            return jsonify({
                'success': False,
            })

    @app.route('/actors', methods=['GET'])
    @requires_auth('get:actors')
    def get_actors(jwt):
        """
        Returns:
            The list of all actors
        """
        try:
            actors = Actor.query.all()

            return jsonify({
                'success': True,
                "actors": [actor.id for actor in actors]
            })
        except Exception as e:
            return jsonify({
                'success': False,
            })

    @app.route('/movies', methods=['POST'])
    @requires_auth('post:movies')
    def post_movie(jwt):
        """
        Returns:
            The object of newly created movie
        """
        try:
            title = request.json['title']
            release_date = request.json['release_date']

            nMovie = Movie(title=title, release_date=release_date)
            nMovie.insert()

            return jsonify({
                'success': True,
                'movie': nMovie
            })

        except Exception as e:
            return jsonify({
                'success': False,
            })

    @app.route('/actors', methods=['POST'])
    @requires_auth('post:actors')
    def post_actor(jwt):
        """
        Returns:
            The object of newly created actor
        """
        try:

            name = request.json['name']
            age = request.json['age']
            gender = request.json['gender']

            nActor = Actor(name=name, age=age, gender=gender)
            nActor.insert()

            return jsonify({
                'success': True,
                'actor': nActor
            })

        except Exception as e:
            return jsonify({
                'success': False,
            })

    @app.route('/movies/<int:id>', methods=['PATCH'])
    @requires_auth('patch:movies')
    def patch_movie(jwt, id):
        """
        Args
            The id of the movie to be edited
        Returns:
            The edited movie object
        """
        try:
            body = request.get_json()
            ntitle = body.get('title', None)
            nrelease = body.get('release_date', None)

            movie = Movie.query.filter(Movie.id == id).one_or_none()

            if not ntitle == 'null':
                movie.title = ntitle
            if not nrelease == 'null':
                movie.release_date = nrelease

            movie.update()

            return jsonify({
                'success': True,
                'movie': movie
            })

        except Exception as e:
            return jsonify({
                'success': False,
            })

    @app.route('/actors/<int:id>', methods=['PATCH'])
    @requires_auth('patch:actors')
    def patch_actor(jwt, id):
        """
        Args
            The id of the actor to be edited
        Returns:
            The edited actor object
        """
        try:
            body = request.get_json()
            nname = body.get('name', None)
            nage = body.get('age', None)
            ngender = body.get('gender', None)

            actor = Actor.query.filter(Actor.id == id).one_or_none()

            if not nname == 'null':
                actor.name = nname
            if not nage == 'null':
                actor.age = nage
            if not ngender == 'null':
                actor.gender = ngender

            actor.update()

            return jsonify({
                'success': True,
                'actor': actor
            })

        except Exception as e:
            return jsonify({
                'success': False,
            })

    @app.route('/movies/<int:id>', methods=['DELETE'])
    @requires_auth('delete:movies')
    def delete_movie(jwt, id):
        """
        Args
            The id of the movie to be deleted
        Returns:
            The id of the deleted movie
        """
        try:
            movie = Movie.query.filter(Movie.id == id).one_or_none()
            movie.delete()

            return jsonify({
                'success': True,
                "delete": id
            })

        except Exception as e:
            return jsonify({
                'success': False,
            })

    @app.route('/actors/<int:id>', methods=['DELETE'])
    @requires_auth('delete:actors')
    def delete_actor(jwt, id):
        """
        Args
            The id of the movie to be deleted
        Returns:
            The id of the deleted movie
        """
        try:
            actor = Actor.query.filter(Actor.id == id).one_or_none()
            actor.delete()

            return jsonify({
                'success': True,
                "delete": id
            })

        except Exception as e:
            return jsonify({
                'success': False,
            })

    # Error Handling

    @app.errorhandler(422)
    def unprocessable(error):
        """
        returns:
            handling for 422 (unprocessable) Error
        """
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(404)
    def not_found(error):
        """
        returns:
            handling for 404 (Not found) Error
        """

        return jsonify({
            "success": False,
            "error": 404,
            "message": "Not found"
        }), 404

    @app.errorhandler(400)
    def Bad_request(error):
        """
        returns:
            handling for 400 (Bad request) Error
        """

        return jsonify({
            "success": False,
            "error": 400,
            "message": "Bad request"
        }), 400

    @app.errorhandler(405)
    def method_not_allowed(error):
        """
        returns:
            handling for 405 (method not allowed) Error
        """

        return jsonify({
            "success": False,
            "error": 405,
            "message": "method not allowed"
        }), 405

    @app.errorhandler(500)
    def Server_error(error):
        """
        returns:
            handling for 500 (Server error) Error
        """

        return jsonify({
            "success": False,
            "error": 500,
            "message": "Server error"
        }), 500

    @app.errorhandler(403)
    def forbidden(error):
        """
        returns:
            handling for 403 (forbidden) Error
        """

        return jsonify({
            "success": False,
            "error": 403,
            "message": "forbidden"
        }), 403

    @app.errorhandler(409)
    def Duplicate_resource(error):
        """
        returns:
            handling for 409 (Duplicate resource) Error
        """

        return jsonify({
            "success": False,
            "error": 409,
            "message": "Duplicate resource"
        }), 409

    @app.errorhandler(AuthError)
    def Auth_Error(error):
        """
        returns:
            handling for 401 (Authentication error) Error
        """

        return jsonify({
            "success": False,
            "error": 401,
            "message": "Authentication error"
        }), 401

    return app
コード例 #28
0
def create_app(test_config=None):
    #load .env variables for Auth0
    ENV_FILE = find_dotenv()
    if ENV_FILE:
        load_dotenv(ENV_FILE)

    AUTH0_CALLBACK_URL = os.getenv('AUTH0_CALLBACK_URL')
    AUTH0_CLIENT_ID = os.getenv('AUTH0_CLIENT_ID')
    AUTH0_CLIENT_SECRET = os.getenv('AUTH0_CLIENT_SECRET')
    AUTH0_DOMAIN = os.getenv('AUTH0_DOMAIN')
    AUTH0_BASE_URL = 'https://'+str(AUTH0_DOMAIN)
    AUTH0_AUDIENCE = os.getenv('AUTH0_AUDIENCE')
 
    app = Flask(__name__)
    app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
    app.debug = True
    setup_db(app)
    migrate = Migrate(app, db)

    oauth = OAuth(app)

    auth0 = oauth.register(
        'auth0',
        client_id=AUTH0_CLIENT_ID,
        client_secret=AUTH0_CLIENT_SECRET,
        api_base_url=AUTH0_BASE_URL,
        access_token_url='https://onstagram.eu.auth0.com' + '/oauth/token',
        authorize_url='https://onstagram.eu.auth0.com' + '/authorize',
        client_kwargs={'scope': 'openid profile email'}
      )
# -------------------------------------------------------------------------#
# Enable CORS
# -------------------------------------------------------------------------#
    CORS(app)
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers',
                                'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods',
                                'GET,PATCH,POST,DELETE,OPTIONS')
        return response
    #callback handling for Auth0

   
      # route handler to log in
    @app.route('/login', methods=['GET'])
    @cross_origin()
    def login():
        print('Audience: {}'.format(AUTH0_AUDIENCE))
        print('callback: {}'.format(AUTH0_CALLBACK_URL))
        return auth0.authorize_redirect(
          redirect_uri=AUTH0_CALLBACK_URL,
          audience=AUTH0_AUDIENCE
          )

     # route handler for home page once logged in
    @app.route('/callback', methods=['GET'])
    @cross_origin()
    def post_login():
        token = auth0.authorize_access_token()
        session['token'] = token['access_token']
        resp = auth0.get('userinfo')
        userinfo = resp.json()
        session[constants.JWT_PAYLOAD] = userinfo
        session[constants.JWT] = token['access_token']
        session[constants.PROFILE_KEY] = {
            'user_id': userinfo['sub'],
            'name': userinfo['name']
        }
        print(session['token'])
        return redirect(url_for('profile'))

    @app.route('/logout')
    def logout():
        try:
            session.clear()
            params = {'returnTo': url_for('home', _external=True), 'client_id': AUTH0_CLIENT_ID}
            return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))
        except Exception as e:
            print (e)

    # -------------------------------------------------------------------------#
    # Application Routes
    # -------------------------------------------------------------------------#
    @app.route('/')
    @cross_origin()
    def home():
        try:
            groups = Group.query.all()
            permission = get_permission()
            posts = Post.query.order_by(Post.id.desc())
            return render_template("index.html", posts=posts, groups=groups, permission=permission), 200
        except Exception as e:
            print(e)
            abort(400)



    @app.route("/posts/<int:group_id>")
    def filter_posts(group_id):
        groups = Group.query.all()
        for g in groups: #check if requested group exists
            if g.id == group_id:
                group_id = g.id
                id=group_id
                break
            else:
                id=None
        if id:
            try:
                permission = get_permission()
                posts = Post.query.filter_by(group_id=id).order_by(Post.id.desc())
                return render_template("posts.html", posts=posts, groups=groups, permission=permission),200
            except Exception as e:
                print(f"error: {e}")
                abort(400)
        else:
            return "Group Not Found. Redirecting to home", {"Refresh": "3; url=http://localhost:5000"}
        
            

    @app.route('/profile')
    @cross_origin()
    def profile():
        try:
            permission = get_permission()
            userinfo=session[constants.PROFILE_KEY]
            token=session['token']
            return render_template("profile.html", userinfo = userinfo, token = token, permission = permission),200
            
        except Exception as e:
            print(f"error: {e}")
            abort(401)
        
      

    # ----------- POSTS ENDPOINTS ------------
    @app.route('/posts/create', methods=['POST', 'GET'])
    @cross_origin()
    @requires_auth('post:images')
    def create_post(payload):
        form = PostForm(request.form)
        groups = Group.query.all()
        form.group.choices = [(g.id, g.name) for g in groups]
        
        if request.method == "POST":
            try:
                userinfo=session[constants.PROFILE_KEY]
                author = userinfo.get("name"),
                post = Post()
                form.populate_obj(post)
                post.group_id= request.form.get("group")
                post.author = author
                post.insert()
                return redirect (url_for("home"))
                
            except Exception as e:
                print(e)
                abort(400)
        return render_template("new_post.html", form=form)

    @app.route('/posts/<post_id>/delete', methods=['DELETE'])
    @cross_origin()
    @requires_auth('post:images')
    def delete_post(payload, post_id):
        post = Post.query.filter_by(id=post_id).one_or_none()
        post.delete()
        print(f"post with id {post_id} successfully deleted")
        return redirect(url_for("home"))
            
        
    
    @app.route('/posts/<post_id>/edit', methods=['GET','POST']) 
    @cross_origin()
    @requires_auth('post:images')
    def edit_post(payload, post_id):
        groups = Group.query.all()
        form = PostForm(request.form)
        form.group.choices = [(g.id, g.name) for g in groups]
        post = Post.query.filter_by(id=post_id).one_or_none()
        if request.method == "POST":
            form.populate_obj(post)
            post.group_id= request.form.get("group")
            
            
            post.update()
            return redirect(url_for("home"))
        
        else:
            form = PostForm(request.form)
            return render_template("edit_post.html", post=post, form=form)
        
    # ----------- GROUPS ENDPOINTS ------------
    @app.route("/groups/create", methods=['POST', 'GET'])
    @cross_origin()
    @requires_auth("post:groups")
    def create_group(payload):
        form = GroupForm(request.form)
        groups = Group.query.all()
        if request.method == "POST":
            try:
                group = Group()
                form.populate_obj(group)
                group.insert()
                return redirect (url_for("home")),200
                
            except Exception as e:
                print(e)
                abort(400)
        return render_template("new_group.html", form=form, groups=groups)

    @app.route('/groups/<group_id>/edit', methods=['GET','POST']) #TODO: add permission check
    @cross_origin()
    @requires_auth('post:groups')
    def edit_group(payload, group_id):
        group = Group.query.filter_by(id=group_id).one_or_none()
        if request.method == "POST":
            group.name=request.form.get("name")
            group.update()
            return redirect(url_for("home"))
        
        else:
            form = GroupForm(request.form)
            return render_template("edit_group.html", group=group, form=form)
    

    
    # -------------------------------------------------------------------------#
    # Error handling
    # -------------------------------------------------------------------------#
    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            'success': False,
            'error': 400,
            "message": "bad request"
        }), 400

    @app.errorhandler(401)
    def unauthorized(error):
        return jsonify({
            'success': False,
            'error': 401,
            "message": "unauthorized"
        }), 401

    @app.errorhandler(404)
    def resource_not_found(error):
        return jsonify({
            'success': False,
            'error': 404,
            'message': 'resource not found'
        }), 404

    @app.errorhandler(405)
    def method_not_allowed(error):
        return jsonify({
            'success': False,
            'error': 405,
            'message': 'method not allowed'
        }), 405

    @app.errorhandler(422)
    def unprocessable_entity(error):
        return jsonify({
            'success': False,
            'error': 422,
            'message': 'unprocessable entity'
        }), 422

    @app.errorhandler(500)
    def internal_server_error(error):
        return jsonify({
            'success': False,
            'error': 500,
            'message': 'internal server error'
        }), 422


    return app
コード例 #29
0
#!/usr/bin/python3
from authlib.integrations.flask_client import OAuth
from flask import Flask, url_for, render_template, redirect
import json
import os
# use loginpass to make OAuth connection simpler

app = Flask(__name__)
app.secret_key = os.environ.get('SECRET_KEY') or 'pengwingsiscool'

oauth = OAuth(app)
oauth.register(
    name='github',
    client_id=os.getenv('CLIENT_ID') or '10a81c493f912828f09f',
    client_secret=os.getenv('CLIENT_SECRET')
    or 'cd6b2f37ab6b2e2991ef2c09bc918a8499d4af11',
    access_token_url='https://github.com/login/oauth/access_token',
    access_token_params=None,
    authorize_url='https://github.com/login/oauth/authorize',
    authorize_params=None,
    api_base_url='https://api.github.com/',
    client_kwargs={'scope': 'user repo'},
)


@app.route('/')
def homepage():
    return render_template('index.html')


@app.route('/login')
コード例 #30
0
ファイル: app.py プロジェクト: LeopoldKink/capstone
def create_app(test_config=None):

    app = Flask(__name__)
    oauth = OAuth(app)
    db.init_app (app)
    migrate.init_app (app, db)
    CORS(app)
    cors = CORS(app, resources={r"/*": {"origins": "*"}})
    app.config['SECRET_KEY'] = '5791628bb0b13cefhri3j0c676dtrfefeefde280ba245'
    app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_URL']
    ###app.config['SQLALCHEMY_DATABASE_URI'] = "postgres://*****:*****@localhost:5432/fitness_api"

    # ACTIVE SETTING
    def getJSON(filePathAndName):
        with open(filePathAndName, 'r') as fp:
            return json.load(fp)

    setting_list = getJSON("./settings.json")
    active_setting_JSON = getJSON("./active_setting.json")
    active_setting = active_setting_JSON["setting"]

    for setting in setting_list:
        if setting["setting"] == active_setting:
            env = setting

    #Auth0

    auth0 = oauth.register(
        'auth0',
        client_id=env["auth0"]["client_id"],
        client_secret=env["auth0"]["client_secret"],
        api_base_url='https://hnc.auth0.com',
        access_token_url='https://hnc.auth0.com/oauth/token',
        authorize_url='https://hnc.auth0.com/authorize',
        client_kwargs={
            'scope': 'openid profile email',
        },
    )

    @app.route('/callback')
    def callback_handling():
        # Handles response from token endpoint
        try:
            auth0.authorize_access_token()
            resp = auth0.get('userinfo')
            userinfo = resp.json()
            access_token = auth0.token['access_token']
            accessinfo = verify_decode_jwt(access_token)

            # Store the user information in flask session.
            session['accessinfo'] = accessinfo
            session['isLogged'] = True
            return redirect('/exercices')
        except:
            print(sys.exc_info())
            abort(404)

    @app.route('/login')
    def login():
        try:
            return auth0.authorize_redirect(redirect_uri=env["auth0"]["redirect_uri"], audience='fitnessapi')
        except:
            print(sys.exc_info())
            abort(404)

    @app.route('/logout')
    def logout():
        try:
            # Clear session stored data
            session.clear()
            # Redirect user to logout endpoint
            params = {'returnTo': url_for(
                'index', _external=True), 'client_id': env["auth0"]["client_id"]}
            return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))
        except:
            print(sys.exc_info())
            abort(404)


    #########################################################   GET  #########################################################   GET  ########################################### 


    @app.route('/exercices', methods=['GET'])
    def index():
        selection = Exercice.query.all()
        exercices = [Exercice.format() for Exercice in selection]
        
        return jsonify({'exercices' : exercices})


    @app.route('/instructors', methods=['GET'])
    def instructors():
        selection = Instructor.query.all()
        instructors = [Instructor.format() for Instructor in selection]
        
        return jsonify({'instructors' : instructors})


    @app.route('/instructors/<int:inst_id>', methods=['GET'])
    @requires_auth('get:instructor')
    def show_instructor(inst_id):
        success = False
        try:
            instructor = Instructor.query.filter(Instructor.id == inst_id).one_or_none()
            instructor_json = instructor.format()
            success = True
        except:
            print(sys.exc_info())
            abort(404)
        return jsonify({
            'instructor' : instructor_json,
            'success' : success
        })





    #########################################################   POST  #########################################################   POST  ########################################### 

    @app.route('/exercices', methods=['POST'])
    @requires_auth('post:workout')
    def create_exercice(accessinfo):
        success = False
        try:
            body = request.get_json()
            name = body['name']
            difficulty = body['difficulty']
            muscles = body['muscles']
            requirements = body['requirements']
            video_path = body['video_path']
            new_exercice = Exercice(name=name, difficulty=difficulty, muscles=muscles, requirements=requirements, video_path=video_path)
            db.session.add(new_exercice)
            db.session.commit()
            success = True
        except:
            print(sys.exc_info())
            abort(404)
        return jsonify({
            'success' : success,
            'created' : new_exercice.id,
            'exercice name' : new_exercice.name
        })

    @app.route('/instructors', methods=['POST'])
    @requires_auth('post:workout')
    def create_instructor(accessinfo):
        success = False
        try:
            body = request.get_json()
            name = body['name']
            profile_pic_path = body['profile_pic_path']
            age = body['age']
            new_instructor = Instructor(name=name, profile_pic_path=profile_pic_path, age=age)
            db.session.add(new_instructor)
            db.session.commit()
            success = True
        except:
            print(sys.exc_info())
            abort(404)
        return jsonify({
            'success' : success,
            'created' : new_instructor.id,
            'exercice name' : new_instructor.name
        })



    #########################################################   DELETE  #########################################################   DELETE  ########################################### 


    @app.route('/exercices/<int:ex_id>', methods=['DELETE']) 
    @requires_auth('delete:workout')
    def delete_exercice(accessinfo, ex_id):
        success = False
        try:
            exercice = Exercice.query.filter(Exercice.id == ex_id).one_or_none()
            exercice.delete()
            success = True
        except:
            print(sys.exc_info())
            abort(404)
        return jsonify({
            'success' : success,
            'deleted' : exercice.id
        })

    #########################################################   PATCH  #########################################################   PATCH  ########################################### 

    @app.route('/exercices/<int:ex_id>', methods=['PATCH'])
    @requires_auth('patch:workout')
    def patch_exercice(accessinfo, ex_id):
        success = False
        try:
            exercice = Exercice.query.filter(Exercice.id == ex_id).first()
            body = request.get_json()
            exercice.name = body['name']
            exercice.difficulty = body['difficulty']
            exercice.muscles = body['muscles']
            exercice.requirements = body['requirements']
            exercice.video_path = body['video_path']
            db.session.commit()
            success = True
        except:
            print(sys.exc_info())
            abort(404)
        return jsonify({
            'success' : success,
            'updated' : exercice.id,
            'exercice name' : exercice.name
        })


    #########################################################   ERRORS  #########################################################   ERRORS  ########################################### 


    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "Not found"
        }), 404


    @app.errorhandler(401)
    def unauthorized(error):
        return jsonify({
            "success": False,
            "error": 401,
            "message": "Unauthorized!"
        }), 401


    @app.errorhandler(405)
    def method_not_allowed(error):
        return jsonify({
            "success": False,
            "error": 405,
            "message": "method not allowed"
        }), 405


    @app.errorhandler(403)
    def forbidden(error):
        return jsonify({
            "success": False,
            "error": 403,
            "message": "forbidden"
        }), 403

    @app.errorhandler(AuthError)
    def auth_error(error):
        return jsonify({
            "success": False,
            "error": 401,
            "message": "Unauthorized!"
        }), 401

    @app.errorhandler(500)
    def handle_500(e):
        '''
        original = getattr(e, "orig", None)

        if original is None:
            # direct 500 error, such as abort(500)
            return render_template("500.html"), 500
        '''
        return jsonify({
            "success": False,
            "error": 500,
            "message": "Internal Server error"
        }), 500

    return app