feat: new login with google
This commit is contained in:
parent
e5f86203ff
commit
ded387c66a
12
.env.example
12
.env.example
|
@ -0,0 +1,12 @@
|
||||||
|
MONGO_URI=
|
||||||
|
FLASK_ENV=
|
||||||
|
DEBUG=
|
||||||
|
|
||||||
|
SECRET_KEY=
|
||||||
|
|
||||||
|
GOOGLE_PROJECT_ID=
|
||||||
|
GOOGLE_CLIENT_ID=
|
||||||
|
GOOGLE_CLIENT_SECRET=
|
||||||
|
GOOGLE_AUHT_URI=
|
||||||
|
GOOGLE_TOKEN_URI=
|
||||||
|
GOOGLE_AUTH_PROVIDER_X509_CERT_URL=
|
|
@ -20,6 +20,12 @@ def login(auth_controller: AuthController = Provide[Container.auth_controller]):
|
||||||
return auth_controller.login()
|
return auth_controller.login()
|
||||||
|
|
||||||
|
|
||||||
|
@auth_blueprint.route("/login/google", methods=["POST"])
|
||||||
|
@inject
|
||||||
|
def google_login(auth_controller: AuthController = Provide[Container.auth_controller]):
|
||||||
|
return auth_controller.google_login()
|
||||||
|
|
||||||
|
|
||||||
@auth_blueprint.route("/logout", methods=["DELETE"])
|
@auth_blueprint.route("/logout", methods=["DELETE"])
|
||||||
@inject
|
@inject
|
||||||
def logout(auth_controller: AuthController = Provide[Container.auth_controller]):
|
def logout(auth_controller: AuthController = Provide[Container.auth_controller]):
|
||||||
|
|
|
@ -1,18 +1,27 @@
|
||||||
import os
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
|
||||||
load_dotenv() # Load environment variables from .env
|
# Load variabel dari file .env
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
MONGO_URI = os.getenv(
|
FLASK_ENV = os.getenv("FLASK_ENV", "development")
|
||||||
"MONGO_URI", "mongodb://localhost:27017/quiz_app"
|
DEBUG = os.getenv("DEBUG", "False").lower() in ("true", "1", "t")
|
||||||
) # Default value if not set
|
|
||||||
|
|
||||||
FLASK_ENV = os.getenv("FLASK_ENV", "development") # Default to development
|
SECRET_KEY = os.getenv("SECRET_KEY", "your_secret_key")
|
||||||
|
MONGO_URI = os.getenv("MONGO_URI", "mongodb://localhost:27017/yourdb")
|
||||||
|
|
||||||
DEBUG = os.getenv("DEBUG", "True").lower() in [
|
GOOGLE_PROJECT_ID = os.getenv("GOOGLE_PROJECT_ID")
|
||||||
"true",
|
GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
|
||||||
"1",
|
GOOGLE_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET")
|
||||||
"t",
|
GOOGLE_AUTH_URI = os.getenv(
|
||||||
] # Convert string to boolean
|
"GOOGLE_AUTH_URI", "https://accounts.google.com/o/oauth2/auth"
|
||||||
|
)
|
||||||
|
GOOGLE_TOKEN_URI = os.getenv(
|
||||||
|
"GOOGLE_TOKEN_URI", "https://oauth2.googleapis.com/token"
|
||||||
|
)
|
||||||
|
GOOGLE_AUTH_PROVIDER_X509_CERT_URL = os.getenv("GOOGLE_AUTH_PROVIDER_X509_CERT_URL")
|
||||||
|
|
||||||
|
GOOGLE_SCOPE = "email profile"
|
||||||
|
GOOGLE_BASE_URL = "https://www.googleapis.com/oauth2/v1/"
|
||||||
|
|
|
@ -5,9 +5,12 @@ from services import AuthService
|
||||||
|
|
||||||
|
|
||||||
class AuthController:
|
class AuthController:
|
||||||
def __init__(self, userService: UserService, authService: AuthService):
|
def __init__(
|
||||||
|
self, userService: UserService, authService: AuthService, googleAuth=None
|
||||||
|
):
|
||||||
self.user_service = userService
|
self.user_service = userService
|
||||||
self.auth_service = authService
|
self.auth_service = authService
|
||||||
|
self.google_auth = googleAuth
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
|
@ -17,6 +20,14 @@ class AuthController:
|
||||||
return jsonify(response.to_dict()), 200
|
return jsonify(response.to_dict()), 200
|
||||||
return jsonify(response.to_dict()), 400
|
return jsonify(response.to_dict()), 400
|
||||||
|
|
||||||
|
def google_login(self):
|
||||||
|
data = request.get_json()
|
||||||
|
id_token = data["token"]
|
||||||
|
response = self.google_auth.parse_id_token(id_token)
|
||||||
|
if response:
|
||||||
|
return jsonify({"message": response})
|
||||||
|
return jsonify({"message": "google login failed"})
|
||||||
|
|
||||||
def register(self):
|
def register(self):
|
||||||
|
|
||||||
return jsonify({"message": "register"})
|
return jsonify({"message": "register"})
|
||||||
|
|
|
@ -5,11 +5,9 @@ from configs import Config
|
||||||
|
|
||||||
def init_db(app: Flask) -> PyMongo:
|
def init_db(app: Flask) -> PyMongo:
|
||||||
try:
|
try:
|
||||||
app.config["MONGO_URI"] = Config.MONGO_URI
|
mongo = PyMongo(app)
|
||||||
mongo = PyMongo(app) # Initialize PyMongo with the app
|
|
||||||
print(f"Connecting to MongoDB: {Config.MONGO_URI}")
|
|
||||||
|
|
||||||
mongo.cx.server_info() # Ping the MongoDB server
|
mongo.cx.server_info()
|
||||||
print("✅ MongoDB connection successful!")
|
print("✅ MongoDB connection successful!")
|
||||||
|
|
||||||
return mongo
|
return mongo
|
||||||
|
|
|
@ -9,6 +9,7 @@ class Container(containers.DeclarativeContainer):
|
||||||
"""Dependency Injection Container"""
|
"""Dependency Injection Container"""
|
||||||
|
|
||||||
mongo = providers.Dependency()
|
mongo = providers.Dependency()
|
||||||
|
google_auth = providers.Dependency()
|
||||||
# repository
|
# repository
|
||||||
user_repository = providers.Factory(UserRepository, mongo.provided.db)
|
user_repository = providers.Factory(UserRepository, mongo.provided.db)
|
||||||
|
|
||||||
|
@ -17,4 +18,6 @@ class Container(containers.DeclarativeContainer):
|
||||||
user_service = providers.Factory(UserService, user_repository)
|
user_service = providers.Factory(UserService, user_repository)
|
||||||
|
|
||||||
# controllers
|
# controllers
|
||||||
auth_controller = providers.Factory(AuthController, user_service, auth_service)
|
auth_controller = providers.Factory(
|
||||||
|
AuthController, user_service, auth_service, google_auth
|
||||||
|
)
|
||||||
|
|
23
app/main.py
23
app/main.py
|
@ -4,15 +4,33 @@ from configs import Config
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from blueprints import auth_blueprint
|
from blueprints import auth_blueprint
|
||||||
from database import init_db
|
from database import init_db
|
||||||
|
from authlib.integrations.flask_client import OAuth
|
||||||
|
from flask_login import LoginManager
|
||||||
|
|
||||||
|
|
||||||
def createApp() -> Flask:
|
def createApp() -> Flask:
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
app.config.from_object(Config)
|
||||||
container = Container()
|
container = Container()
|
||||||
|
|
||||||
app.container = container
|
app.container = container
|
||||||
|
|
||||||
|
login_manager = LoginManager(app)
|
||||||
|
oauth = OAuth(app)
|
||||||
|
|
||||||
|
google = oauth.register(
|
||||||
|
name="google",
|
||||||
|
client_id=app.config["GOOGLE_CLIENT_ID"],
|
||||||
|
client_secret=app.config["GOOGLE_CLIENT_SECRET"],
|
||||||
|
access_token_url=app.config["GOOGLE_TOKEN_URI"],
|
||||||
|
authorize_url=app.config["GOOGLE_AUTH_URI"],
|
||||||
|
api_base_url=app.config["GOOGLE_BASE_URL"],
|
||||||
|
client_kwargs={"scope": "openid email profile"},
|
||||||
|
)
|
||||||
|
|
||||||
|
if google is not None:
|
||||||
|
container.google_auth.override(google)
|
||||||
|
|
||||||
mongo = init_db(app)
|
mongo = init_db(app)
|
||||||
if mongo is not None:
|
if mongo is not None:
|
||||||
container.mongo.override(mongo)
|
container.mongo.override(mongo)
|
||||||
|
@ -22,11 +40,10 @@ def createApp() -> Flask:
|
||||||
# Register Blueprints
|
# Register Blueprints
|
||||||
app.register_blueprint(default_blueprint)
|
app.register_blueprint(default_blueprint)
|
||||||
app.register_blueprint(auth_blueprint, url_prefix="/api")
|
app.register_blueprint(auth_blueprint, url_prefix="/api")
|
||||||
# app.register_blueprint(user_blueprint, url_prefix="/api")
|
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = createApp()
|
app = createApp()
|
||||||
app.run(debug=Config.DEBUG)
|
app.run(host="0.0.0.0", debug=Config.DEBUG)
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
from flask_login import (
|
||||||
|
LoginManager,
|
||||||
|
UserMixin,
|
||||||
|
login_user,
|
||||||
|
logout_user,
|
||||||
|
login_required,
|
||||||
|
current_user,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
google = oauth.remote_app(
|
||||||
|
"google",
|
||||||
|
consumer_key="YOUR_GOOGLE_CLIENT_ID",
|
||||||
|
consumer_secret="YOUR_GOOGLE_CLIENT_SECRET",
|
||||||
|
request_token_params={"scope": "email"},
|
||||||
|
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",
|
||||||
|
)
|
|
@ -5,4 +5,8 @@ python-dotenv==1.0.1
|
||||||
dependency-injector==4.46.0
|
dependency-injector==4.46.0
|
||||||
pytest==8.3.4
|
pytest==8.3.4
|
||||||
pydantic==2.10.6
|
pydantic==2.10.6
|
||||||
email-validator==2.2.0
|
email-validator==2.2.0
|
||||||
|
Flask-Bcrypt==1.0.1
|
||||||
|
flask-jwt-extended==4.7.1
|
||||||
|
Flask-Login==0.6.3
|
||||||
|
authlib==1.5.1
|
Loading…
Reference in New Issue