Skip to content

Commit

Permalink
Merge branch 'dev-server' into production
Browse files Browse the repository at this point in the history
  • Loading branch information
shaheenhyderk committed Dec 12, 2023
2 parents feb5b12 + 6f5d7da commit aa1621f
Show file tree
Hide file tree
Showing 25 changed files with 214 additions and 156 deletions.
11 changes: 11 additions & 0 deletions api/dashboard/error_log/error_view.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import os

from decouple import config
Expand Down Expand Up @@ -81,6 +82,8 @@ def post(self, request, log_name):


class LoggerAPI(APIView):
authentication_classes = [CustomizePermission]

@role_required(
[RoleType.ADMIN.value, RoleType.FELLOW.value, RoleType.TECH_TEAM.value]
)
Expand All @@ -95,3 +98,11 @@ def get(self, request):
log_handler = logHandler()
formatted_errors = log_handler.parse_logs(log_data)
return CustomResponse(response=formatted_errors).get_success_response()

@role_required(
[RoleType.ADMIN.value, RoleType.FELLOW.value, RoleType.TECH_TEAM.value]
)
def patch(self, request, error_id):
logger = logging.getLogger("django")
logger.error(f"PATCHED : {error_id}")
return CustomResponse(response="Updated patch list").get_success_response()
52 changes: 38 additions & 14 deletions api/dashboard/error_log/log_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ def parse_logs(self, log_data: str) -> list[dict]:
Returns:
list[dict]: formatted errors
"""
self.patch_pattern = (
r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}) ERROR PATCHED : (\w+)"
)
self.patched_errors = self.extract_patches(log_data)

# Extract all logs in string format
matches = reversed(re.findall(self.log_pattern, log_data, re.DOTALL))
formatted_errors = {}
Expand All @@ -43,6 +48,12 @@ def parse_logs(self, log_data: str) -> list[dict]:

return formatted_errors.values()

def extract_patches(self, log_data):
return {
patch[2]: self.get_formatted_time(patch[1])
for patch in re.finditer(self.patch_pattern, log_data)
}

def extract_log_entry(self, error: str) -> dict:
"""fetch the value from the details of how to
find it provided by the regex
Expand All @@ -58,6 +69,7 @@ def extract_log_entry(self, error: str) -> dict:

for key, value in values.items():
entry_type = self.log_entries[key]["type"]

if entry_type == datetime:
result_dict[key] = self.get_formatted_time(value)
elif entry_type == dict and value:
Expand Down Expand Up @@ -116,23 +128,35 @@ def get_patterns(self) -> list:
values = self.log_entries.values()
return [value["regex"] for value in values]

def aggregate_log_entry(self, formatted_errors: list[dict], log_entry: dict) -> None:
def already_patched(self, log_entry: dict) -> bool:
"""checks if log entry id is in patched
errors and its timestamp is before the error was patched
"""
return (
log_entry["id"] in self.patched_errors
and log_entry["timestamp"] < self.patched_errors[log_entry["id"]]
)

def aggregate_log_entry(
self, formatted_errors: list[dict], log_entry: dict
) -> None:
"""combines all fetched error into one
Args:
formatted_errors (list[dict]): the list to add everything into
log_entry (dict): current log entry
"""
log_id = log_entry["id"]
log_keys = self.log_entries.keys()
if log_id not in formatted_errors:
formatted_errors[log_id] = {
key: [] if key != "id" else log_id for key in log_keys
}
for key in log_keys:
if (
key != "id"
and log_entry[key]
and log_entry[key] not in formatted_errors[log_id][key]
):
formatted_errors[log_id][key].append(log_entry[key])
if not self.already_patched(log_entry):
log_id = log_entry["id"]
log_keys = self.log_entries.keys()
if log_id not in formatted_errors:
formatted_errors[log_id] = {
key: [] if key != "id" else log_id for key in log_keys
}
for key in log_keys:
if (
key != "id"
and log_entry[key]
and log_entry[key] not in formatted_errors[log_id][key]
):
formatted_errors[log_id][key].append(log_entry[key])
1 change: 1 addition & 0 deletions api/dashboard/error_log/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

urlpatterns = [
path('', error_view.LoggerAPI.as_view()),
path('patch/<str:error_id>/', error_view.LoggerAPI.as_view()),
path('<str:log_name>/', error_view.DownloadErrorLogAPI.as_view()),
path('view/<str:log_name>/', error_view.ViewErrorLogAPI.as_view()),
path('clear/<str:log_name>/', error_view.ClearErrorLogAPI.as_view()),
Expand Down
2 changes: 1 addition & 1 deletion api/dashboard/lc/dash_lc_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ def get_previous_meetings(self, obj):
return previous_meetings


class LearningCircleDataSerializer(serializers.ModelSerializer):
class LearningCircleStatsSerializer(serializers.ModelSerializer):
interest_group = serializers.SerializerMethodField()
college = serializers.SerializerMethodField()
learning_circle = serializers.SerializerMethodField()
Expand Down
6 changes: 3 additions & 3 deletions api/dashboard/lc/dash_lc_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from utils.utils import send_template_mail, DateTimeUtils
from .dash_lc_serializer import LearningCircleSerializer, LearningCircleCreateSerializer, LearningCircleDetailsSerializer, \
LearningCircleUpdateSerializer, LearningCircleJoinSerializer, \
LearningCircleMainSerializer, LearningCircleNoteSerializer, LearningCircleDataSerializer, \
LearningCircleMainSerializer, LearningCircleNoteSerializer, LearningCircleStatsSerializer, \
LearningCircleMemberListSerializer, MeetRecordsCreateEditDeleteSerializer, IgTaskDetailsSerializer, \
ScheduleMeetingSerializer, ListAllMeetRecordsSerializer, AddMemberSerializer

Expand Down Expand Up @@ -90,7 +90,7 @@ def post(self, request):
).get_success_response()


class LearningCircleDataAPI(APIView):
class LearningCircleStatsAPI(APIView):
"""
API endpoint for retrieving basic data about all learning circles.
Expand All @@ -103,7 +103,7 @@ class LearningCircleDataAPI(APIView):
def get(self, request):
learning_circle = LearningCircle.objects.all()

serializer = LearningCircleDataSerializer(
serializer = LearningCircleStatsSerializer(
learning_circle,
many=False
)
Expand Down
2 changes: 1 addition & 1 deletion api/dashboard/lc/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

urlpatterns = [
path('user-list/', dash_lc_view.UserLearningCircleListApi.as_view(), name='main'), # list all lc's of user
path('stats/', dash_lc_view.LearningCircleStatsAPI.as_view(), name='data'),
path('<str:circle_id>/details/', dash_lc_view.LearningCircleDetailsApi.as_view(), name='lc-detailed'), # individual ls details
# dashboard search listing
path('<str:circle_id>/schedule-meet/', dash_lc_view.ScheduleMeetAPI.as_view(), name='schedule-meet'),
Expand All @@ -25,7 +26,6 @@
path('list/', dash_lc_view.LearningCircleMainApi.as_view(), name='list'), # public page listing
path('list-all/', dash_lc_view.TotalLearningCircleListApi.as_view(), name='list-all'), # dashboard search listing

# path('data/', dash_lc_view.LearningCircleDataAPI.as_view(), name='data'),
# path('list-members/<str:circle_id>/', dash_lc_view.LearningCircleListMembersApi.as_view(), name='list-members'),
# path('invite/', dash_lc_view.LearningCircleInviteLeadAPI.as_view()),
# path('meet-record/list-all/<str:circle_id>/', dash_lc_view.SingleReportDetailAPI.as_view(), name='list-all-meet-record'), # optim
Expand Down
8 changes: 6 additions & 2 deletions api/dashboard/profile/profile_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ def create_karma_activity_log(task_title, karma_value):
task = TaskList.objects.filter(title=task_title).first()
if task:
if karma_value > 0:
KarmaActivityLog.objects.create(
karma_log = KarmaActivityLog.objects.create(
task_id=task.id,
karma=karma_value,
user_id=user_id,
Expand All @@ -401,13 +401,17 @@ def create_karma_activity_log(task_title, karma_value):

dl = WebHookActions.SEPARATOR.value
discord_id = User.objects.get(id=user_id).discord_id
value = f"{task.hashtag}{dl}{karma_value}{dl}{discord_id}{dl}{task.id}"
value = f"{task.hashtag}{dl}{karma_value}{dl}{discord_id}{dl}{karma_log.id}"

DiscordWebhooks.general_updates(
WebHookCategory.KARMA_INFO.value,
WebHookActions.UPDATE.value,
value
)
else:
KarmaActivityLog.objects.filter(
task_id=task.id, user_id=user_id
).delete()
Wallet.objects.filter(user_id=user_id).update(
karma=F("karma") + karma_value,
updated_by_id=user_id
Expand Down
7 changes: 2 additions & 5 deletions api/dashboard/profile/profile_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,8 @@ def patch(self, request):

def delete(self, request):
user_id = JWTUtils.fetch_user_id(request)
user = User.objects.get(id=user_id)
user.deleted_by = user
user.deleted_at = DateTimeUtils.get_current_utc_time()
user.save()

user = User.objects.get(id=user_id).delete()

return CustomResponse(
general_message="User deleted successfully"
).get_success_response()
Expand Down
8 changes: 4 additions & 4 deletions api/dashboard/roles/dash_roles_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ def validate(self, attrs):
)
if users.count() != len(attrs):
raise serializers.ValidationError("One or more user IDs are invalid.")
else:
data["users"] = users
return data

data["users"] = users
return data

def create(self, validated_data):
users = validated_data.pop("users")
Expand All @@ -57,7 +57,7 @@ def create(self, validated_data):
validated_data["role"].title,
",".join(list(users.values_list("id", flat=True))),
)
return user_roles_to_create
return user_roles_to_create, validated_data["role"]


class RoleDashboardSerializer(serializers.ModelSerializer):
Expand Down
43 changes: 33 additions & 10 deletions api/dashboard/roles/dash_roles_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,7 @@ def get(self, request, role_id):
Lists all the users with a given role
"""
users = (
User.objects.filter(user_role_link_user__role__pk=role_id)
.distinct()
.all()
User.objects.filter(user_role_link_user__role__pk=role_id).distinct().all()
)
serialized_users = dash_roles_serializer.UserRoleLinkManagementSerializer(
users, many=True
Expand Down Expand Up @@ -204,19 +202,44 @@ def patch(self, request):
Assigns a large bunch of users a certain role
"""
request_data = request.data.copy()
request_data[
"created_by"
] = JWTUtils.fetch_user_id(request)
request_data["created_by"] = JWTUtils.fetch_user_id(request)
serialized_users = dash_roles_serializer.RoleAssignmentSerializer(
data=request_data
)
if serialized_users.is_valid():
serialized_users.save()
users, role = serialized_users.save()
return CustomResponse(
general_message="Successfully gave all users the requested role"
general_message=f"Successfully gave {len(users)} users '{role.title}' role"
).get_success_response()
return CustomResponse(response=serialized_users.errors).get_failure_response()

@role_required([RoleType.ADMIN.value])
def delete(self, request):
"""
Removes a role from a large bunch of users
"""
role = Role.objects.get(pk=request.data.get("role"))
user_role_links = UserRoleLink.objects.filter(
user__pk__in=request.data.get("users"),
role=role,
)
number = user_role_links.count()

DiscordWebhooks.general_updates(
WebHookCategory.BULK_ROLE.value,
WebHookActions.DELETE.value,
role.title,
",".join(list(user_role_links.values_list("user_id", flat=True))),
)

user_role_links.delete()

return CustomResponse(
general_message=(
f"Successfully removed the '{role.title}' role from {number} users"
)
).get_success_response()


class UserRole(APIView):
authentication_classes = [CustomizePermission]
Expand Down Expand Up @@ -421,12 +444,12 @@ def post(self, request):
else:
error_rows.append(user_roles_serializer.errors)

for role,user_set in users_by_role.items():
for role, user_set in users_by_role.items():
DiscordWebhooks.general_updates(
WebHookCategory.BULK_ROLE.value,
WebHookActions.UPDATE.value,
role,
",".join(user_set)
",".join(user_set),
)

return CustomResponse(
Expand Down
3 changes: 2 additions & 1 deletion api/dashboard/user/dash_user_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class UserDetailsSerializer(serializers.ModelSerializer):
organizations = serializers.SerializerMethodField(read_only=True)
interest_groups = serializers.SerializerMethodField(read_only=True)
role = serializers.SerializerMethodField(read_only=True)
district = serializers.CharField(source="district.name", allow_null=True)
district = serializers.CharField(source="district.id", allow_null=True)

class Meta:
model = User
Expand Down Expand Up @@ -251,6 +251,7 @@ class Meta:
"department",
"graduation_year",
"admin",
"district"
]

def to_representation(self, instance):
Expand Down
6 changes: 2 additions & 4 deletions api/dashboard/user/dash_user_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,8 @@ def delete(self, request, user_id):
return CustomResponse(
general_message="User Not Available"
).get_failure_response()

user.deleted_by = User.objects.get(pk=JWTUtils.fetch_user_id(request))
user.deleted_at = DateTimeUtils.get_current_utc_time()
user.save()

user.delete()

return CustomResponse(
general_message="User deleted successfully"
Expand Down
20 changes: 1 addition & 19 deletions api/register/register_helper.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,7 @@
import decouple
import requests

from db.user import User
from utils.exception import CustomException
from utils.response import CustomResponse


def get_full_name(first_name, last_name):
return f"{first_name}{last_name or ''}".replace(" ", "").lower()[:85]


def generate_muid(first_name, last_name):
full_name = get_full_name(first_name, last_name)
muid = f"{full_name}@mulearn"

counter = 0
while User.objects.filter(muid=muid).exists():
counter += 1
muid = f"{full_name}-{counter}@mulearn"

return muid


def get_auth_token(muid, password):
Expand All @@ -32,4 +14,4 @@ def get_auth_token(muid, password):
if response.get("statusCode") != 200:
raise CustomException(response.get("message"))

return response.get("response")
return response.get("response")
3 changes: 0 additions & 3 deletions api/register/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,6 @@ class UserSerializer(serializers.ModelSerializer):
def create(self, validated_data):
role = validated_data.pop("role", None)

validated_data["muid"] = register_helper.generate_muid(
validated_data["first_name"], validated_data.get('last_name', '')
)
password = validated_data.pop("password")
hashed_password = make_password(password)
validated_data["password"] = hashed_password
Expand Down
Loading

0 comments on commit aa1621f

Please sign in to comment.