Skip to content

Commit

Permalink
added celery task to send email initation
Browse files Browse the repository at this point in the history
  • Loading branch information
ami-wtag committed Mar 3, 2024
1 parent f8117d8 commit 6e1d864
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 48 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Now, the project will be running on `http://localhost:8000`

### Pgadmin4

`http://localhost:5050`
http://localhost:5050

## Testing

Expand All @@ -78,6 +78,10 @@ To run tests using Pytest, execute the following command within the virtual envi
$ make test
```

## Flower

Navigate to http://localhost:5556 to view the dashboard. You should see one worker ready to go.

## Documentation

```
Expand Down
22 changes: 13 additions & 9 deletions app/api/invitation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from core.config import settings
from app.models import User
from core.logger import logger
from app.worker.celery import send_email_task


invitation_router = APIRouter(prefix='/invitation', tags=['Invitation'])
Expand Down Expand Up @@ -89,6 +90,7 @@ async def accept_invitation(

@invitation_router.get("/resend/{email}")
async def resend_invitation(
background_tasks: BackgroundTasks,
email: str,
db: Session = Depends(get_db),
current_user = Depends(get_current_user)
Expand All @@ -113,15 +115,17 @@ async def resend_invitation(
invitation.resent_count += 1
_ = invitation_crud.update(db=db, obj_in=invitation)

await send_email_async(
subject=f'Invitation to Join {invitation.organization}',
email_to=invitation.email,
body={
"full_name": invitation.full_name,
"email": invitation.email,
"organization": invitation.organization,
"created_by_name": created_by.full_name,
"invitation_url": f"{settings.BASE_URL}/accept-invitation/{unique_token}"}
# Inside your FastAPI route
send_email_task.delay(
subject=f'Invitation to Join {invitation.organization}',
email_to=invitation.email,
body={
"full_name": invitation.full_name,
"email": invitation.email,
"organization": invitation.organization,
"created_by_name": created_by.full_name,
"invitation_url": f"{settings.BASE_URL}/accept-invitation/{unique_token}"
}
)

return {'message': 'Invitation resent successfully'}
6 changes: 5 additions & 1 deletion app/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,8 @@ databases[postgresql]
faker
factory-boy
pytest-asyncio
pytest-mock
pytest-mock
aiofiles
celery
redis
flower
33 changes: 17 additions & 16 deletions app/services/oauth2.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
from app.db.base import engine
from app.db.base import get_db

import casbin
import casbin_sqlalchemy_adapter
# import casbin
# import casbin_sqlalchemy_adapter


oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/oauth-login")
adapter = casbin_sqlalchemy_adapter.Adapter(engine)
# adapter = casbin_sqlalchemy_adapter.Adapter(engine)


def get_current_user(
Expand All @@ -33,22 +33,23 @@ def get_current_user_authorization(
db: Session = Depends(get_db),
current_user: schemas.TokenData = Depends(get_current_user),
):
enforcer = casbin.Enforcer("core/model.conf", adapter)
sub = current_user.email
dom = current_user.organization_name
obj = req.url.path
act = req.method

if not (enforcer.enforce(sub, dom, obj, act)):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Method not authorized for this user")
# enforcer = casbin.Enforcer("core/model.conf", adapter)
# sub = current_user.email
# dom = current_user.organization_name
# obj = req.url.path
# act = req.method

# if not (enforcer.enforce(sub, dom, obj, act)):
# raise HTTPException(
# status_code=status.HTTP_401_UNAUTHORIZED,
# detail="Method not authorized for this user")
return current_user


def add_new_role_in_org(
email: str, role: str, dom: str, db: Session = Depends(get_db)
) -> None:
enforcer = casbin.Enforcer("core/model.conf", adapter)
enforcer.add_role_for_user_in_domain(email, role, dom)
db.commit() # Ensure changes are persisted
# enforcer = casbin.Enforcer("core/model.conf", adapter)
# enforcer.add_role_for_user_in_domain(email, role, dom)
# db.commit() # Ensure changes are persisted
pass
1 change: 1 addition & 0 deletions app/worker/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from app.worker.celery import *
18 changes: 18 additions & 0 deletions app/worker/celery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import os
import asyncio

from celery import Celery

from app.services.mail import send_email_async


celery = Celery(__name__)
celery.conf.broker_url = os.environ.get("CELERY_BROKER_URL", "redis://localhost:6379")
celery.conf.result_backend = os.environ.get("CELERY_RESULT_BACKEND", "redis://localhost:6379")


@celery.task(name="send_email_task")
def send_email_task(subject, email_to, body):
loop = asyncio.get_event_loop()
loop.run_until_complete(send_email_async(subject, email_to, body))
return True
48 changes: 48 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ services:
depends_on:
- db
- test-db
- redis
environment:
- DATABASE_URL=postgresql://postgres:postgres@db/db
- TEST_DATABASE_URL=postgresql://postgres:postgres@test-db/test-db
Expand All @@ -27,6 +28,8 @@ services:
- INVITATION_URL_SECRET_KEY=INVITATION_URL_SECRET_KEY_HERE
- INVITATION_URL_SECURITY_PASSWORD_SALT=INVITATION_URL_SECURITY_PASSWORD_SALT_HERE
- INVITATION_URL_MAX_AGE=172800
- CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
build:
context: .
dockerfile: Dockerfile
Expand Down Expand Up @@ -58,6 +61,51 @@ services:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=test-db

worker:
build: .
command: celery -A app.worker.celery worker --loglevel=info
environment:
- DATABASE_URL=postgresql://postgres:postgres@db/db
- TEST_DATABASE_URL=postgresql://postgres:postgres@test-db/test-db
- BASE_URL=http://localhost:8000
- APP_ENV=development
- JWT_REFRESH_SECRET_KEY=JWT_REFRESH_SECRET_KEY_HERE
- JWT_SECRET_KEY=WT_SECRET_KEY_HERE
- ROLLBAR_ACCESS_TOKEN=ROLLBAR_ACCESS_TOKEN_HERE
- BUCKET_NAME=BUCKET_NAME
- OAUTH_CLIENT_ID=CLIENT_IDw
- OAUTH_CLIENT_SECRET=OAUTH_CLIENT_SECRET
- [email protected]
- MAIL_PASSWORD=NupfGHXtsUdgx36VuK
- [email protected]
- MAIL_PORT=587
- MAIL_SERVER=smtp.ethereal.email
- MAIL_FROM_NAME=Norval Hahn
- INVITATION_URL_SECRET_KEY=INVITATION_URL_SECRET_KEY_HERE
- INVITATION_URL_SECURITY_PASSWORD_SALT=INVITATION_URL_SECURITY_PASSWORD_SALT_HERE
- INVITATION_URL_MAX_AGE=172800
- CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
depends_on:
- web
- redis

redis:
image: redis:7

dashboard:
build: .
command: celery --broker=redis://redis:6379/0 flower --port=5555
ports:
- 5556:5555
environment:
- CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
depends_on:
- web
- redis
- worker

volumes:
db:
Expand Down
2 changes: 0 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from app.db.base import engine

from app.db.base_class import Base
from scheduler.invitation import invitation_scheduler
from app.routes import router as api_router


Expand Down Expand Up @@ -38,5 +37,4 @@ async def lifespan(app: FastAPI):
app.include_router(api_router)

if __name__ == "__main__":
invitation_scheduler.start()
uvicorn.run("main:app", host="0.0.0.0", port=8000)
19 changes: 0 additions & 19 deletions scheduler/invitation.py

This file was deleted.

0 comments on commit 6e1d864

Please sign in to comment.