Skip to content

Commit

Permalink
Add follow state (#508)
Browse files Browse the repository at this point in the history
* fix: add attributes of requester follow state on user and project

* ch:correct spelling

* fix: pinned projects and prevent return of deleted projects

* chore: add auth to user docs

* fx: optimize  projects endpoint with follow status

* ch: change celery version

* chore: modify celery
  • Loading branch information
khalifan-kfan authored Jul 1, 2024
1 parent fa66a92 commit 4595881
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 43 deletions.
4 changes: 4 additions & 0 deletions api_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ paths:
produces:
- application/json
parameters:
- in: header
name: Authorization
required: true
description: "Bearer [token]"
- in: path
name: user_id
required: true
Expand Down
77 changes: 42 additions & 35 deletions app/controllers/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,12 +556,14 @@ def get(self, user_id):
"""

current_user_id = get_jwt_identity()
current_user_roles = get_jwt_claims()['roles']
page = request.args.get('page' , 1 , type=int)
per_page = request.args.get('per_page' , 10 , type=int)
current_user = User.get_by_id(current_user_id)
# current_user_roles = get_jwt_claims()['roles']
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 10, type=int)

if not is_current_or_admin(user_id, current_user_id, current_user_roles):
return dict(status='fail', message='unauthorised'), 403
# open endpoint
# if not is_current_or_admin(user_id, current_user_id, current_user_roles):
# return dict(status='fail', message='unauthorised'), 403

project_schema = ProjectSchema(many=True)
user = User.get_by_id(user_id)
Expand All @@ -570,24 +572,28 @@ def get(self, user_id):
ProjectUser, Project.id == ProjectUser.project_id
).filter(
ProjectUser.user_id == user_id,
ProjectUser.pinned == True
ProjectUser.pinned == True,
Project.deleted == False
).all()

pagination_meta_data , projects = paginate(user.projects , per_page , page)
pagination_meta_data, projects = paginate(
user.projects, per_page, page)

projects_json, errors = project_schema.dumps(projects)

pinned_projects_json , errs = project_schema.dumps(pinned_projects)
user_projects, errors = project_schema.dumps(
projects)

pinned_projects, errs = project_schema.dumps(pinned_projects)

if errors and errs:
return dict(status='fail', message='Internal server error'), 500

return dict(
status='success',
data=dict(
pagination = {**pagination_meta_data , 'pinnned_count' : len(pinned_projects)},
pinned = json.loads(pinned_projects_json),
projects=json.loads(projects_json)
pagination={**pagination_meta_data,
'pinned_count': len(pinned_projects)},
pinned=json.loads(pinned_projects),
projects=json.loads(user_projects),
)
), 200

Expand Down Expand Up @@ -806,55 +812,56 @@ def post(self, project_id):

class ProjectPinView(Resource):
@jwt_required
def post(self , project_id):
def post(self, project_id):

current_user_id = get_jwt_identity()
project = Project.get_by_id(project_id)

project_user = ProjectUser.query.filter_by(user_id = current_user_id , project_id = project_id).first()
project_user = ProjectUser.query.filter_by(
user_id=current_user_id, project_id=project_id).first()

if not is_authorised_project_user(project, current_user_id, 'member'):
return dict(status='fail', message='unauthorised'), 403


if project_user.pinned:
return dict(
message = 'The project is already pinned',
status = 'fail'
) , 409
message='The project is already pinned',
status='fail'
), 409

pinned_projects_count = ProjectUser.count(user_id = current_user_id , pinned = True)
pinned_projects_count = ProjectUser.count(
user_id=current_user_id, pinned=True)

if pinned_projects_count >= 6 :
if pinned_projects_count >= 6:
return dict(
status = 'Fail',
message = 'Pinned projects cant be more than 6'
) , 409

status='Fail',
message='Pinned projects cant be more than 6'
), 409

project_user.pinned = True
project_user.save()

return dict(
status = 'Success',
message = f'Project {project_id} pinned successfully'
) , 200
status='Success',
message=f'Project {project_id} pinned successfully'
), 200

@jwt_required
def delete(self,project_id):
def delete(self, project_id):

current_user_id = get_jwt_identity()
project = Project.get_by_id(project_id)

project_user = ProjectUser.query.filter_by(user_id = current_user_id , project_id = project_id).first()
project_user = ProjectUser.query.filter_by(
user_id=current_user_id, project_id=project_id).first()

if not is_authorised_project_user(project, current_user_id, 'member'):
return dict(status='fail', message='unauthorised'), 403

project_user.pinned = False
project_user.save()

return dict(
status = 'Success',
message = f'Project {project_id} unpinned successfully'
) , 200
status='Success',
message=f'Project {project_id} unpinned successfully'
), 200
19 changes: 12 additions & 7 deletions app/controllers/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,13 @@ def post(self):

class UserDetailView(Resource):

@jwt_required
def get(self, user_id):
"""
"""
user_schema = UserSchema()
current_user_id = get_jwt_identity()
current_user = User.get_by_id(current_user_id)

user = User.get_by_id(user_id)

Expand All @@ -377,6 +380,9 @@ def get(self, user_id):
user_data['projects_count'] = len(user.projects)
user_data['following_count'] = user.followed.count()
user_data['follower_count'] = user.followers.count()
# Identify if the person making the details request follows the user or not
user_data['requesting_user_follows'] = user.is_followed_by(
current_user)
user_data['apps_count'] = sum(
len(project.apps) for project in user.projects)

Expand Down Expand Up @@ -425,21 +431,19 @@ def patch(self, user_id):
current_user_roles = get_jwt_claims()['roles']

user = User.get_by_id(user_id)

if (current_user_id != user_id):
if (not is_admin(current_user_roles)):
return dict(
status = 'UnAuthorised',
message = 'You are not authorized to edit this users information'
) , 401

status='UnAuthorised',
message='You are not authorized to edit this users information'
), 401

validate_user_data, errors = user_schema.load(user_data)

if errors:
return dict(status='fail', message=errors), 400


updated = User.update(user, **validate_user_data)

if not updated:
Expand Down Expand Up @@ -968,7 +972,8 @@ def get(self):
metadata=meta_data,
graph_data=user_info)
), 200



class InActiveUsersView(Resource):
computed_results = {} # Dictionary to cache computed results
current_date = None # Variable to track the current date
Expand Down
3 changes: 3 additions & 0 deletions app/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ class Project(ModelMixin):
deleted = db.Column(db.Boolean, default=False)
disabled = db.Column(db.Boolean, default=False)
admin_disabled = db.Column(db.Boolean, default=False)

def is_followed_by(self, user):
return any(follower.user_id == user.id for follower in self.followers)
11 changes: 10 additions & 1 deletion app/schemas/project.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from marshmallow import Schema, fields, validate
from app.helpers.age_utility import get_item_age
from app.models.app import App
from flask_jwt_extended import get_jwt_identity
from app.models.user import User


class ProjectSchema(Schema):
Expand Down Expand Up @@ -29,6 +31,13 @@ class ProjectSchema(Schema):
disabled = fields.Boolean(dump_only=True)
admin_disabled = fields.Boolean(dump_only=True)
prometheus_url = fields.Method("get_prometheus_url", dump_only=True)
is_following = fields.Method("get_is_following", dump_only=True)

def get_is_following(self, obj):
# Assuming current_user is available in the view context
current_user_id = get_jwt_identity()
current_user = User.get_by_id(current_user_id)
return obj.is_followed_by(current_user)

def get_age(self, obj):
return get_item_age(obj.date_created)
Expand All @@ -37,4 +46,4 @@ def get_apps_count(self, obj):
return App.count(project_id=obj.id)

def get_prometheus_url(self, obj):
return obj.cluster.prometheus_url
return obj.cluster.prometheus_url

0 comments on commit 4595881

Please sign in to comment.