diff --git a/nephthys/actions/assign_tag.py b/nephthys/actions/assign_tag.py index d4b0cbe..5cf53cf 100644 --- a/nephthys/actions/assign_tag.py +++ b/nephthys/actions/assign_tag.py @@ -24,7 +24,7 @@ async def assign_tag_callback( channel_id = body["channel"]["id"] ts = body["message"]["ts"] - user = await env.db.user.find_unique(where={"id": user_id}) + user = await env.db.user.find_unique(where={"slackId": user_id}) if not user or not user.helper: await client.chat_postEphemeral( channel=channel_id, diff --git a/nephthys/actions/create_tag.py b/nephthys/actions/create_tag.py index a04cb32..0153782 100644 --- a/nephthys/actions/create_tag.py +++ b/nephthys/actions/create_tag.py @@ -14,7 +14,7 @@ async def create_tag_view_callback(ack: AsyncAck, body: dict, client: AsyncWebCl await ack() user_id = body["user"]["id"] - user = await env.db.user.find_unique(where={"id": user_id}) + user = await env.db.user.find_unique(where={"slackId": user_id}) if not user or not user.admin: await send_heartbeat(f"Attempted to create tag by non-admin user <@{user_id}>") return @@ -33,7 +33,7 @@ async def create_tag_btn_callback(ack: AsyncAck, body: dict, client: AsyncWebCli user_id = body["user"]["id"] trigger_id = body["trigger_id"] - user = await env.db.user.find_unique(where={"id": user_id}) + user = await env.db.user.find_unique(where={"slackId": user_id}) if not user or not user.admin: await send_heartbeat( f"Attempted to open create tag modal by non-admin user <@{user_id}>" diff --git a/nephthys/actions/resolve.py b/nephthys/actions/resolve.py index aac3389..836e7e0 100644 --- a/nephthys/actions/resolve.py +++ b/nephthys/actions/resolve.py @@ -11,7 +11,15 @@ from prisma.enums import TicketStatus async def resolve(ts: str, resolver: str, client: AsyncWebClient): - allowed = await can_resolve(resolver, ts) + resolving_user = await env.db.user.find_unique(where={"slackId": resolver}) + if not resolving_user: + await send_heartbeat( + f"User {resolver} attempted to resolve ticket with ts {ts} but isn't in the database.", + messages=[f"Ticket TS: {ts}", f"Resolver ID: {resolver}"], + ) + return + + allowed = await can_resolve(resolving_user.id, ts) if not allowed: await send_heartbeat( f"User {resolver} attempted to resolve ticket with ts {ts} without permission.", @@ -25,11 +33,12 @@ async def resolve(ts: str, resolver: str, client: AsyncWebClient): return now = datetime.now() + tkt = await env.db.ticket.update( where={"msgTs": ts}, data={ "status": TicketStatus.CLOSED, - "closedBy": {"connect": {"id": resolver}}, + "closedBy": {"connect": {"id": resolving_user.id}}, "closedAt": now, }, ) diff --git a/nephthys/actions/tag_subscribe.py b/nephthys/actions/tag_subscribe.py index 5ff6199..0a8f9aa 100644 --- a/nephthys/actions/tag_subscribe.py +++ b/nephthys/actions/tag_subscribe.py @@ -16,29 +16,29 @@ async def tag_subscribe_callback( Callback for the tag subscribe button """ await ack() - user_id = body["user"]["id"] + slack_id = body["user"]["id"] - user = await env.db.user.find_unique(where={"id": user_id}) + user = await env.db.user.find_unique(where={"slackId": slack_id}) if not user: await send_heartbeat( - f"Attempted to subscribe to tag by unknown user <@{user_id}>" + f"Attempted to subscribe to tag by unknown user <@{slack_id}>" ) return tag_id, tag_name = body["actions"][0]["value"].split(";") # check if user is subcribed if await env.db.usertagsubscription.find_first( - where={"userId": user_id, "tagId": tag_id} + where={"tagId": int(tag_id), "userId": user.id} ): await env.db.usertagsubscription.delete( - where={"userId_tagId": {"tagId": tag_id, "userId": user_id}} + where={"userId_tagId": {"tagId": int(tag_id), "userId": user.id}} ) else: await env.db.usertagsubscription.create( data={ - "user": {"connect": {"id": user_id}}, - "tag": {"connect": {"id": tag_id}}, + "user": {"connect": {"id": user.id}}, + "tag": {"connect": {"id": int(tag_id)}}, } ) - await open_app_home("tags", client, user_id) + await open_app_home("tags", client, slack_id) diff --git a/nephthys/commands/dm_magic_link.py b/nephthys/commands/dm_magic_link.py index f961eee..c9cc32e 100644 --- a/nephthys/commands/dm_magic_link.py +++ b/nephthys/commands/dm_magic_link.py @@ -16,7 +16,7 @@ async def dm_magic_link_cmd_callback( await ack() logging.info(f"Received command: {command}") user_id = body["user_id"] - user = await env.db.user.find_unique(where={"id": user_id}) + user = await env.db.user.find_unique(where={"slackId": user_id}) if not user or not user.helper: await client.chat_postEphemeral( channel=body["channel_id"], diff --git a/nephthys/events/app_home_opened.py b/nephthys/events/app_home_opened.py index c9a0a08..d2bb487 100644 --- a/nephthys/events/app_home_opened.py +++ b/nephthys/events/app_home_opened.py @@ -23,7 +23,7 @@ async def open_app_home(home_type: str, client: AsyncWebClient, user_id: str): try: await client.views_publish(view=get_loading_view(), user_id=user_id) - user = await env.db.user.find_unique(where={"id": user_id}) + user = await env.db.user.find_unique(where={"slackId": user_id}) if not user: user_info = await client.users_info(user=user_id) or {} diff --git a/nephthys/events/channel_left.py b/nephthys/events/channel_left.py index 8223449..61a424a 100644 --- a/nephthys/events/channel_left.py +++ b/nephthys/events/channel_left.py @@ -1,4 +1,5 @@ from slack_bolt.context.ack.async_ack import AsyncAck +from slack_sdk.errors import SlackApiError from slack_sdk.web.async_client import AsyncWebClient from nephthys.utils.env import env @@ -14,15 +15,23 @@ async def channel_left(ack: AsyncAck, event: dict, client: AsyncWebClient): users = await client.usergroups_users_list(usergroup=env.slack_user_group) new_users = users.get("users", []) - new_users.remove(user_id) + + try: + new_users.remove(user_id) + except ValueError: + return + await client.usergroups_users_update( usergroup=env.slack_user_group, users=new_users ) - await env.db.user.update(where={"id": user_id}, data={"helper": False}) + await env.db.user.update(where={"slackId": user_id}, data={"helper": False}) - match channel_id: - case env.slack_bts_channel: - await client.conversations_kick(channel=channel_id, user=user_id) - case env.slack_ticket_channel: - await client.conversations_kick(channel=channel_id, user=user_id) + try: + match channel_id: + case env.slack_bts_channel: + await client.conversations_kick(channel=channel_id, user=user_id) + case env.slack_ticket_channel: + await client.conversations_kick(channel=channel_id, user=user_id) + except SlackApiError: + pass diff --git a/nephthys/events/message.py b/nephthys/events/message.py index ecdd6e8..4bc9cf5 100644 --- a/nephthys/events/message.py +++ b/nephthys/events/message.py @@ -25,9 +25,9 @@ async def on_message(event: Dict[str, Any], client: AsyncWebClient): thread_url = f"https://hackclub.slack.com/archives/{env.slack_help_channel}/p{event['ts'].replace('.', '')}" - db_user = await env.db.user.find_first(where={"id": user}) + db_user = await env.db.user.find_first(where={"slackId": user}) if db_user: - past_tickets = await env.db.ticket.count(where={"openedById": user}) + past_tickets = await env.db.ticket.count(where={"openedById": db_user.id}) else: past_tickets = 0 user_info = await client.users_info(user=user) or {} @@ -41,11 +41,11 @@ async def on_message(event: Dict[str, Any], client: AsyncWebClient): ) db_user = await env.db.user.upsert( where={ - "id": user, + "slackId": user, }, data={ - "create": {"id": user, "username": username}, - "update": {"id": user, "username": username}, + "create": {"slackId": user, "username": username}, + "update": {"slackId": user, "username": username}, }, ) @@ -95,7 +95,7 @@ async def on_message(event: Dict[str, Any], client: AsyncWebClient): "description": text, "msgTs": event["ts"], "ticketTs": ticket["ts"], - "openedBy": {"connect": {"id": user}}, + "openedBy": {"connect": {"id": db_user.id}}, }, ) diff --git a/nephthys/tasks/update_helpers.py b/nephthys/tasks/update_helpers.py index 25bcd38..713ff5b 100644 --- a/nephthys/tasks/update_helpers.py +++ b/nephthys/tasks/update_helpers.py @@ -17,19 +17,19 @@ async def update_helpers(): # unset helpers not in the team await env.db.user.update_many( - where={"helper": True, "id": {"not_in": team_ids}}, + where={"helper": True, "slackId": {"not_in": team_ids}}, data={"helper": False}, ) # update existing users in the db await env.db.user.update_many( - where={"id": {"in": team_ids}}, + where={"slackId": {"in": team_ids}}, data={"helper": True}, ) # create new users not in the db - existing_users_in_db = await env.db.user.find_many(where={"id": {"in": team_ids}}) - existing_user_ids_in_db = {user.id for user in existing_users_in_db} + existing_users_in_db = await env.db.user.find_many(where={"slackId": {"in": team_ids}}) + existing_user_ids_in_db = {user.slackId for user in existing_users_in_db} new_member_data_to_create = [] for member_id in team_ids: @@ -41,7 +41,7 @@ async def update_helpers(): logging.info(f"User info for {member_id}: {user_info}") new_member_data_to_create.append( { - "id": member_id, + "slackId": member_id, "helper": True, "username": user_info.get("user", {}).get("name"), } diff --git a/nephthys/utils/permissions.py b/nephthys/utils/permissions.py index 2b48b7e..d2d21fc 100644 --- a/nephthys/utils/permissions.py +++ b/nephthys/utils/permissions.py @@ -1,12 +1,12 @@ from nephthys.utils.env import env -async def can_resolve(user_id: str, ts: str) -> bool: +async def can_resolve(user_id: int, ts: str) -> bool: """ Check if the user has permission to resolve tickets. Args: - user_id (str): The ID of the user to check permissions for. + user_id (str): The database ID of the user to check permissions for. ts (str): The timestamp of the ticket message to check. Returns: diff --git a/nephthys/views/home/tags.py b/nephthys/views/home/tags.py index 3324bb0..9182136 100644 --- a/nephthys/views/home/tags.py +++ b/nephthys/views/home/tags.py @@ -29,7 +29,13 @@ async def get_manage_tags_view(user: User) -> dict: f"Tag {tag.name} has {len(tag.userSubscriptions) if tag.userSubscriptions else 0} subscriptions" ) if tag.userSubscriptions: - subs = [user.userId for user in tag.userSubscriptions] + subIds = [user.userId for user in tag.userSubscriptions] + + subUsers = await env.db.user.find_many( + where={"id": {"in": subIds}} + ) + + subs = [user.slackId for user in subUsers] else: subs = [] stringified_subs = [f"<@{user}>" for user in subs] diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 74cc360..d79065e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -16,7 +16,8 @@ enum TicketStatus { } model User { - id String @id @unique + id Int @id @unique @default(autoincrement()) + slackId String @unique username String? @unique admin Boolean @default(false) @@ -31,7 +32,7 @@ model User { } model Ticket { - id String @id @unique @default(cuid()) + id Int @id @unique @default(autoincrement()) title String description String status TicketStatus @default(OPEN) @@ -40,14 +41,14 @@ model Ticket { ticketTs String @unique openedBy User @relation("OpenedTickets", fields: [openedById], references: [id]) - openedById String + openedById Int closedBy User? @relation("ClosedTickets", fields: [closedById], references: [id]) - closedById String? + closedById Int? closedAt DateTime? assignedTo User? @relation("AssignedTickets", fields: [assignedToId], references: [id]) - assignedToId String? + assignedToId Int? tagsOnTickets TagsOnTickets[] @@ -55,7 +56,7 @@ model Ticket { } model Tag { - id String @id @unique @default(cuid()) + id Int @id @unique @default(autoincrement()) name String @unique ticketsOnTags TagsOnTickets[] @@ -66,9 +67,9 @@ model Tag { model TagsOnTickets { ticket Ticket @relation(fields: [ticketId], references: [id], onDelete: Cascade) - ticketId String + ticketId Int tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade) - tagId String + tagId Int assignedAt DateTime @default(now()) @@ -78,9 +79,9 @@ model TagsOnTickets { model UserTagSubscription { user User @relation(fields: [userId], references: [id], onDelete: Cascade) - userId String + userId Int tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade) - tagId String + tagId Int subscribedAt DateTime @default(now())