satishsurath / archive.summarizeme.io

AI-powered text summarization made simple. Condense articles, web pages, and PDFs effortlessly. Save time and boost productivity with Summarize.io
https://SummarizeMe.io
1 stars 2 forks source link

Add Oauth Login Feature with Flask-Dance (for Facebook, GitHub, Google, LinkedIn, Reddit and Twitter) #15

Closed satishsurath closed 1 year ago

satishsurath commented 1 year ago

Feature Enhancement Placeholder: Add Oauth Login Feature with Twitter

satishsurath commented 1 year ago

Output from ChatGPT:

Sure! You can add a new column to the Entry_Post class to store the user's ID as a foreign key. First, you'll need to create a relationship between the Entry_Post and User classes using db.ForeignKey and db.relationship. Here's the updated models.py file:

from app import db
from datetime import datetime

class Entry_Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    posttype = db.Column(db.Integer, index=True) # 0 means Summarize from Text, 1 means from URL...
    url = db.Column(db.String(2048), index=True) # "0" for Summarize from Text; else URL string
    text2summarize = db.Column(db.String(214748364), index=True)
    text2summarize_hash = db.Column(db.String(64), index=True)  # Added new column for hash value
    openAIsummary = db.Column(db.String(214748), index=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))  # New column for user_id foreign key

    user = db.relationship('User', backref='entry_posts')  # Relationship between Entry_Post and User

    def __repr__(self):
        return '<Entry_Posts {}>'.format(self.id)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    oauth_id = db.Column(db.String(128), unique=True, nullable=False)
    name = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    picture = db.Column(db.String(256), nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    last_login = db.Column(db.DateTime, default=datetime.utcnow)

    def __repr__(self):
        return '<User {}>'.format(self.email)

Now, the Entry_Post class has a new column user_id, which is a foreign key referencing the id column in the User class. The db.relationship function creates a relationship between the two classes, allowing you to access the user who created an entry post and all the entry posts created by a user.

After making these changes, you'll need to create a new migration and apply it to update your database schema. If you're using Flask-Migrate, you can do this by running:

flask db migrate -m "Add user_id to Entry_Post"
flask db upgrade

This will generate a new migration script and apply the changes to your database.

To incorporate Twitter's OAuth capability and user roles, you can follow these steps:

Install Flask-Dance and Flask-Login for OAuth and user session management:

pip install Flask-Dance Flask-Login

Modify the User class in models.py to add a role column for user roles:


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    oauth_id = db.Column(db.String(128), unique=True, nullable=False)
    name = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    picture = db.Column(db.String(256), nullable=True)
    role = db.Column(db.String(32), default='User')  # New column for user roles
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    last_login = db.Column(db.DateTime, default=datetime.utcnow)

    def is_admin(self):  # Helper method to check if the user is an admin
        return self.role == 'Admin'

    def __repr__(self):
        return '<User {}>'.format(self.email)

Update your app.py or init.py file to set up Twitter OAuth with Flask-Dance, and use Flask-Login for session management:


from flask import Flask, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager, UserMixin, current_user, login_user, logout_user
from flask_dance.contrib.twitter import make_twitter_blueprint, twitter

# Initialize app, database, and other components
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'your-database-uri'
db = SQLAlchemy(app)
migrate = Migrate(app, db)
login_manager = LoginManager(app)
login_manager.login_view = 'login'

# Configure Twitter OAuth
app.config['TWITTER_OAUTH_CLIENT_KEY'] = 'your-twitter-client-key'
app.config['TWITTER_OAUTH_CLIENT_SECRET'] = 'your-twitter-client-secret'
twitter_blueprint = make_twitter_blueprint()
app.register_blueprint(twitter_blueprint, url_prefix='/login')

# Models
from models import User, Entry_Post

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

# Routes
@app.route('/login')
def login():
    if not twitter.authorized:
        return redirect(url_for('twitter.login'))
    resp = twitter.get('account/verify_credentials.json')
    if resp.ok:
        oauth_id = str(resp.json()['id'])
        user = User.query.filter_by(oauth_id=oauth_id).first()
        if user is None:
            user = User(
                oauth_id=oauth_id,
                name=resp.json()['name'],
                email=resp.json()['screen_name'] + '@twitter.com',  # Using screen_name as email
                picture=resp.json()['profile_image_url']
            )
            db.session.add(user)
            db.session.commit()
        login_user(user)
        flash('Logged in successfully.', 'success')
        return redirect(url_for('index'))
    else:
        flash('Failed to log in with Twitter.', 'danger')
        return redirect(url_for('login'))

@app.route('/logout')
def logout():
    logout_user()
    flash('You have been logged out.', 'success')
    return redirect(url_for('login'))

# Other routes and functions

Make sure your templates use the current_user variable provided by Flask-Login to display the user's information and conditionally display content based on the user's role: Modify your routes and views to check for user roles when necessary:


@app.route('/admin-dashboard')
def admin_dashboard():
    if not current_user.is_authenticated or not current_user.is_admin():
        flash('You do not have permission to access this page.', 'danger')
        return redirect(url_for('index'))
    # Your admin dashboard logic goes here
    return render_template('admin_dashboard.html')

# Other routes and functions

Update your templates to use the current_user variable provided by Flask-Login to display the user's information, and conditionally display content based on the user's role. For example, in your base template, you can display different navigation options based on the user's role:

<!-- base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <!-- meta tags, title, styles, etc. -->
</head>
<body>
    <nav>
        <!-- Navigation options for all users -->
        {% if current_user.is_authenticated %}
            {% if current_user.is_admin() %}
                <!-- Additional navigation options for admin users -->
                <a href="{{ url_for('admin_dashboard') }}">Admin Dashboard</a>
            {% endif %}
            <a href="{{ url_for('logout') }}">Logout</a>
        {% else %}
            <a href="{{ url_for('login') }}">Login with Twitter</a>
        {% endif %}
    </nav>

    {% block content %}
    {% endblock %}
</body>
</html>

Make sure to replace placeholders like 'your-secret-key', 'your-database-uri', 'your-twitter-client-key', and 'your-twitter-client-secret' with appropriate values. You can also customize the email address format for Twitter users and the user role checks according to your requirements.

satishsurath commented 1 year ago

completed this in the 9d3b12281beee7f1becf060b7676f31a81e4ca4d Commit