Home > database >  How to make an app.route() in Flask only functional if you are coming from a specific URL?
How to make an app.route() in Flask only functional if you are coming from a specific URL?

Time:02-11

I'm creating a project to learn how to use Stripe and work together with a registration template. My integration with Stripe is working, I can successfully make a payment and after the payment is done, I'm redirected to my registration template.

The problem is, you should only get access to the registration template after going through the Stripe integration, but what is happening is anyone who access the '/register' URL manually can by pass the payment stage and register himself in the registration template.

The route I'm using in the process is:

@app.route('/stripe_pay')
def stripe_pay():
    session = stripe.checkout.Session.create(
        payment_method_types=['card'],
        line_items=[{
            'price': '{{ PRICE ID }}',
            'quantity': 1,
        }],
        mode='subscription',
        success_url=url_for('register', _external=True),
        cancel_url=url_for('signup', _external=True),
    )
    return {
        'checkout_session_id': session['id'],
        'checkout_public_key': app.config['STRIPE_PUBLIC_KEY'],
    }

The '/register' route performs user data collection and then writes down all the information in a database. All is working fine with the process.

@app.route('/register')
def register():
    form = RegistrationForm()
    if form.validate_on_submit():
        todb = c_personal_info( first_name = form.first_name.data,
                            last_name = form.last_name.data,
                            email = form.email.data,
                            password = form.password.data,
                            subscription='M')
        with db.session.begin():
            db.session.add(todb)
        flash('Thanks for registering! You can now login!', category="success")
        return redirect(url_for('login'))
    return render_template('register.html', form = form)

The session is not authenticated, as the '/register' template is actually where you would create your credentials to log in.

My question is how do I make the '/register' end point only accessible when you are coming from the '/stripe_pay' end point? I also would love to hear your ideas and different aproaches to this.

CodePudding user response:

Study using a decorator to handle your problem. See https://flask.palletsprojects.com/en/2.0.x/tutorial/views/ for example.

def login_required(view):
    @functools.wraps(view)
    def wrapped_view(**kwargs):
        if g.user is None:
            return redirect(url_for('auth.login'))

        return view(**kwargs)

    return wrapped_view

This piece of code will require users to login first before able to access any page having the @login_required decorator.

CodePudding user response:

I solved my issue by using the "@login_required" decorator, in conjunction with the "current_user" module from "Flask-Login".

1 - As a last step, before routing to the route I want to protect, I logged in with an "admin" user. I created that user for that and for other priviledged accesses.

2 - I decorated the target route with "@login_required", so I blocked non logged users, then I used "current_user" with a condition to allow only the "admin" user to proceed. Any other logged in user is redirected to a different URL.

  • Related