diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/api/groups.py')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/api/groups.py | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/api/groups.py b/packages/meshbay-hub/src/meshbay_hub/api/groups.py index 49902de..fcf0360 100644 --- a/packages/meshbay-hub/src/meshbay_hub/api/groups.py +++ b/packages/meshbay-hub/src/meshbay_hub/api/groups.py @@ -7,7 +7,8 @@ from sqlalchemy import func, or_, select, update from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.asyncio import AsyncSession -from meshbay_hub import hub_settings +from meshbay_hub import hub_settings, mail +from meshbay_hub.auth import decrypt_email from meshbay_hub.api.deps import get_current_user, require_user_scope from meshbay_hub.api.netutil import client_ip from meshbay_hub.db.engine import get_db @@ -671,3 +672,53 @@ async def delete_group( return {"status": "deleted", "group_id": group_id} +class InviteNotifyRequest(BaseModel): + username: str + code: str + group_name: str + + +@router.post("/{group_id}/invite-notify") +async def invite_notify( + group_id: str, + body: InviteNotifyRequest, + current_user: User = Depends(require_user_scope), + db: AsyncSession = Depends(get_db), +): + """Send an invitation email to a member who was just invited. + + The invite code was created on the node — the hub only knows about it + because the inviter's browser sends it here. The hub looks up the + invitee's encrypted email, decrypts it, and sends the notification. + The inviter never sees the email address. + """ + group = await db.get(Group, group_id) + if not group: + raise HTTPException(status_code=404, detail="Group not found") + if group.admin_id != current_user.id: + raise HTTPException(status_code=403, + detail="Only the group owner can send invitations") + + target = (await db.execute( + select(User).where(User.username == body.username))).scalar_one_or_none() + if not target: + raise HTTPException(status_code=404, detail="User not found") + + email = "" + try: + email = decrypt_email(target.email) if target.email else "" + except Exception: + pass + + if not email: + return {"status": "no_email"} + + try: + mail.send_invite_notification( + email, body.code, current_user.username, body.group_name) + except Exception: + return {"status": "send_failed"} + + return {"status": "sent"} + + |