Skip to content

Commit

Permalink
refactor and add docstring to auth and user services
Browse files Browse the repository at this point in the history
  • Loading branch information
khansadaoudi committed Dec 9, 2024
1 parent e001954 commit 5dc4b7e
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 125 deletions.
115 changes: 21 additions & 94 deletions app/auth/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from datetime import datetime

from flask import (
abort,
current_app,
Expand All @@ -10,7 +8,7 @@
request,
Response,
)
from flask_login import current_user, login_user, login_required, logout_user
from flask_login import login_user, login_required
from authomatic.adapters import WerkzeugAdapter
from authomatic import Authomatic

Expand All @@ -21,44 +19,22 @@

from .auth_config import CONFIG

from ..user.service import UserService
from ..user.interface import UserInterface
from ..user.schema import UserSchema
from ..user.service import UserAuthService
from ..user.model import User
from ..github.service import GithubService
from ..projects.service import ProjectAccessService

from ..projects.service import ProjectAccessService

authomatic = Authomatic(CONFIG, Config.SECRET_KEY, report_errors=True)


def parse_user(provider_name, user):
results_parsed = {}

if provider_name == "github":
results_parsed["access_token"] = user.data.get("access_token")
data = GithubService.get_user_information(results_parsed["access_token"])
results_parsed["id"] = data.get("id")
results_parsed["username"] = data.get("login")
results_parsed["picture_url"] = data.get("avatar_url")
results_parsed["email"] = data.get("email")

elif provider_name == "google":
results_parsed["id"] = user.email
results_parsed["username"] = user.email.split("@")[0]
results_parsed["email"] = user.email
results_parsed["first_name"] = user.first_name
results_parsed["family_name"] = user.last_name
results_parsed["picture_url"] = user.picture

return results_parsed



@auth.route("/login/<provider_name>/")
def login(provider_name) -> Response:
"""
Login handler.
"""login using social authentication
Args:
provider_name (string): github | google
Returns:
Response
"""
# We need response object for the WerkzeugAdapter.
response = make_response()
Expand All @@ -76,48 +52,15 @@ def login(provider_name) -> Response:
if provider_name == "google":
# specific to google, we need to update the user to get more info.
result.user.update()

# parse the format specific to each provider
results_parsed = parse_user(provider_name, result.user)

# Retrieve the user
user = UserService.login_by_id(results_parsed.get("id"))

# If no existing user, create a new one
if not user:
username = results_parsed.get("username")
valid_username = UserService.make_valid_nickname(username)
unique_username = UserService.make_unique_nickname(valid_username)

new_attrs: UserInterface = {
"id": results_parsed["id"],
"auth_provider": result.user.provider.id,
"github_access_token": results_parsed.get("access_token"),
"username": unique_username,
"first_name": results_parsed.get("first_name"),
"family_name": results_parsed.get("family_name"),
"email": results_parsed.get("email"),
"not_share_email": False,
"picture_url": results_parsed.get("picture_url"),
"super_admin": False,
"created_date": datetime.utcnow(),
"last_seen": datetime.utcnow(),
}

user = UserService.create(new_attrs)
has_projects = False
else:
if user.auth_provider == "4":
changes: UserInterface = {
"github_access_token": results_parsed.get("access_token"),
"picture_url": results_parsed.get("picture_url"),
}
else:
changes: UserInterface = {
"picture_url": results_parsed.get("picture_url")
}
user = UserService.update(user, changes)
has_projects = ProjectAccessService.user_has_access_to_project(user.id)
results_parsed = UserAuthService.parse_user_information(provider_name, result.user)

user = UserAuthService.create_or_update_user(results_parsed)

has_projects = ProjectAccessService.user_has_access_to_project(user.id)
login_user(user, remember=True)

# If there is no superadmin in DB, add admin privilege to this new user
if not User.query.filter_by(super_admin=True).first():
print("firstsuper")
Expand All @@ -131,33 +74,17 @@ def login(provider_name) -> Response:
return make_response(
render_template("auth/redirect_prod.html", has_projects= has_projects)
)

return response


@auth.route("/firstsuper")
@login_required
def firstsuper():
"""
Handle requests to the /firstsuper route
"""Handle the request for /firstsuper
Returns:
template: render the template of the first user
"""
return render_template("admin/firstsuper.html")

@auth.route("/checkfirstsuper", methods=["POST"])
@login_required
def checkfirstsuper():
"""
Handle requests to the /firstsuper route
"""
mdp = request.form.get("password")
if mdp == Config.FIRSTADMINKEY:

user = UserService.get_by_id(current_user.id)
changes: UserInterface = {"super_admin": True}
UserService.update(user, changes)
message = "You are logged in as the first super user"
else:
message = "Access as superadmin has been denied."
flash(message)
return redirect("https://127.0.0.1:8080")

23 changes: 21 additions & 2 deletions app/user/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,27 @@

@api.route("/")
class UsersResource(Resource):
"Users"

@responds(schema=UserSchema(many=True), api=api)
def get(self) -> List[User]:
"""Get the list of users in the app
Returns:
List[User]: the list of the users in the app
"""
return UserService.get_all()


@api.route("/me")
class UserResource(Resource):
"User"

@responds(schema=UserSchema, api=api)
def get(self) -> User:
"""Get user information after log in and update last_seen value
Returns:
User: User entity
"""
user = UserService.get_by_id(current_user.id)
changes: UserInterface = {"last_seen": datetime.utcnow()}
user = UserService.update(user, changes)
Expand All @@ -38,6 +47,11 @@ def get(self) -> User:
@responds(schema=UserSchema, api=api)
@accepts(schema=UserSchema, api=api)
def put(self):
"""Update information of user
Returns:
User: return user entity with the updated values
"""
user = UserService.get_by_id(current_user.id)
changes: UserInterface = request.parsed_obj
return UserService.update(user,changes)
Expand All @@ -46,6 +60,11 @@ def put(self):
class UserLogoutResource(Resource):

def get(self):
"""Logout user
Returns:
Response: flask response
"""
logout_user()
js = json.dumps({"logout": True}, default=str)
return Response(js, status=200, mimetype="application/json")
1 change: 1 addition & 0 deletions app/user/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@


class UserInterface(TypedDict, total=False):
"""Typed interface to deal with user entity"""
id: str
auth_provider: str
github_access_token: str
Expand Down
4 changes: 2 additions & 2 deletions app/user/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@


class User(UserMixin, db.Model, BaseM):


"""User representation in db"""
__tablename__ = "users"

id = Column(String(256), primary_key=True)
auth_provider = Column(String(256))
github_access_token = Column(String(256))
Expand Down
2 changes: 1 addition & 1 deletion app/user/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


class UserSchema(Schema):
"""User schema"""
"""User schema user object serialization"""

id = fields.String(attribute="id")
authProvider = fields.String(attribute="auth_provider")
Expand Down
Loading

0 comments on commit 5dc4b7e

Please sign in to comment.