-
Notifications
You must be signed in to change notification settings - Fork 594
Initial #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Initial #12
Changes from all commits
5e224b4
2d965c1
4e11cca
29610bd
e08d5b5
952cf6a
f1b0c0d
0e5f691
a46b140
8431896
5ae8d5b
7d8636f
7b85afd
f7f63f7
4d34a94
d66acea
222dcbe
a0a3d29
aeb7342
ca7392a
27610c3
c7cc00e
4d2ca01
bd99590
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Virtual environment | ||
venv/ | ||
|
||
# Python cache files | ||
__pycache__/ | ||
*.pyc | ||
*.pyo | ||
*.pyd | ||
|
||
# Logs & temp files | ||
*.log | ||
*.tmp | ||
*.swp | ||
*.swo | ||
|
||
# IDE/Editor files | ||
.vscode/ | ||
.idea/ | ||
|
||
# Environment variables (if needed) | ||
.env | ||
|
||
# OS-specific files | ||
.DS_Store | ||
Thumbs.db |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from fastapi import FastAPI | ||
from fastapi.middleware.cors import CORSMiddleware | ||
from app.routes import auth, donor, organisation | ||
|
||
app = FastAPI() | ||
|
||
# CORS Middleware Configuration (Allow React Frontend to Access API) | ||
app.add_middleware( | ||
CORSMiddleware, | ||
allow_origins=["http://localhost:3000"], # React frontend URL | ||
allow_credentials=True, | ||
allow_methods=["*"], # Allow all HTTP methods (GET, POST, PUT, DELETE, etc.) | ||
allow_headers=["*"], # Allow all headers (e.g., Authorization, Content-Type) | ||
) | ||
|
||
# Include API routers | ||
app.include_router(auth.router, prefix="/auth", tags=["Auth"]) | ||
app.include_router(donor.router, prefix="/donor", tags=["Donor"]) | ||
app.include_router(organisation.router, prefix="/organisation", tags=["Organisation"]) | ||
|
||
# Test Endpoint to check if backend is running | ||
@app.get("/") | ||
def home(): | ||
return {"message": "Welcome to the FastAPI Backend (No Database)"} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,75 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from fastapi import APIRouter, HTTPException, Depends | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from pydantic import BaseModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from passlib.context import CryptContext | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from datetime import datetime, timedelta | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from typing import Optional | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from jose import JWTError, jwt | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+1
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unused imports and secure JWT configuration. The static analysis identified unused imports. Additionally, the JWT configuration needs to be secured. Apply this diff: -from fastapi import APIRouter, HTTPException, Depends
+from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from passlib.context import CryptContext
from datetime import datetime, timedelta
from typing import Optional
-from jose import JWTError, jwt
+from jose import jwt
+from app.config import settings # Create this file to manage environment variables 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.8.2)1-1: Remove unused import: (F401) 6-6: Remove unused import: (F401) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# FastAPI Router for Authentication | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
router = APIRouter() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Password Hashing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# In-memory storage (Temporary, use a database in production) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
users = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+14
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace in-memory storage with a database. Using in-memory storage is not suitable for production as data will be lost when the server restarts. Consider implementing a proper database solution:
Would you like me to help you set up a database solution? |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# JWT Token Settings | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SECRET_KEY = "your_secret_key_here" # Replace with a strong secret key | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ALGORITHM = "HS256" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ACCESS_TOKEN_EXPIRE_MINUTES = 30 # Token expires in 30 minutes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Pydantic Models | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class UserCreate(BaseModel): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
email: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
password: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+23
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add input validation for user fields. The current model lacks validation for email format and password strength. Apply this diff to add validation: +from pydantic import BaseModel, EmailStr, Field
+import re
+
+def validate_password(v: str) -> str:
+ if not re.match(r'^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$', v):
+ raise ValueError('Password must be at least 8 characters long and contain both letters and numbers')
+ return v
+
class UserCreate(BaseModel):
name: str
- email: str
- password: str
+ email: EmailStr
+ password: str = Field(..., min_length=8)
+
+ @validator('password')
+ def password_validation(cls, v):
+ return validate_password(v)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class UserLogin(BaseModel): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
email: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
password: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class TokenData(BaseModel): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
email: Optional[str] = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Utility Functions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Generates a JWT access token.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
to_encode = data.copy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expire = datetime.utcnow() + (expires_delta if expires_delta else timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
to_encode.update({"exp": expire}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return encoded_jwt | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def verify_password(plain_password, hashed_password): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Verifies if a password matches its hashed version.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return pwd_context.verify(plain_password, hashed_password) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_password_hash(password): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Hashes the password.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return pwd_context.hash(password) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Routes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@router.post("/register") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def register(user: UserCreate): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Registers a new user.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for u in users: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if u["email"] == user.email: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise HTTPException(status_code=400, detail="Email already exists") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hashed_password = get_password_hash(user.password) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new_user = {"name": user.name, "email": user.email, "password": hashed_password} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
users.append(new_user) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return {"message": "User registered successfully"} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+54
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add response model and improve error handling. The registration endpoint needs a proper response model and better error handling. Apply this diff: -@router.post("/register")
-def register(user: UserCreate):
+from fastapi import status
+from pydantic import BaseModel
+
+class UserResponse(BaseModel):
+ name: str
+ email: str
+
+@router.post("/register", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
+async def register(user: UserCreate):
"""Registers a new user."""
for u in users:
if u["email"] == user.email:
- raise HTTPException(status_code=400, detail="Email already exists")
+ raise HTTPException(
+ status_code=status.HTTP_409_CONFLICT,
+ detail="A user with this email already exists"
+ )
hashed_password = get_password_hash(user.password)
new_user = {"name": user.name, "email": user.email, "password": hashed_password}
users.append(new_user)
- return {"message": "User registered successfully"}
+ return UserResponse(name=user.name, email=user.email) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@router.post("/login") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def login(user: UserLogin): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Logs in a user and returns a JWT token.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for u in users: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if u["email"] == user.email and verify_password(user.password, u["password"]): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Create JWT Token | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
access_token = create_access_token(data={"sub": user.email}, expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return {"access_token": access_token, "token_type": "bearer"} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise HTTPException(status_code=400, detail="Invalid email or password") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+66
to
+75
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add rate limiting and improve login security. The login endpoint needs rate limiting to prevent brute force attacks. Apply this diff: +from fastapi import Request
+from fastapi.security import OAuth2PasswordRequestForm
+from slowapi import Limiter
+from slowapi.util import get_remote_address
+
+limiter = Limiter(key_func=get_remote_address)
+
-@router.post("/login")
-def login(user: UserLogin):
+@router.post("/login")
+@limiter.limit("5/minute")
+async def login(request: Request, form_data: OAuth2PasswordRequestForm = Depends()):
"""Logs in a user and returns a JWT token."""
for u in users:
- if u["email"] == user.email and verify_password(user.password, u["password"]):
+ if u["email"] == form_data.username and verify_password(form_data.password, u["password"]):
# Create JWT Token
- access_token = create_access_token(data={"sub": user.email}, expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
+ access_token = create_access_token(
+ data={"sub": form_data.username},
+ expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
+ )
return {"access_token": access_token, "token_type": "bearer"}
- raise HTTPException(status_code=400, detail="Invalid email or password")
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Invalid credentials",
+ headers={"WWW-Authenticate": "Bearer"},
+ ) 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,15 @@ | ||||||||||||||||||||||||||||||||
from fastapi import APIRouter | ||||||||||||||||||||||||||||||||
from pydantic import BaseModel | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
router = APIRouter() | ||||||||||||||||||||||||||||||||
donors = [] # In-memory storage | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
class DonorCreate(BaseModel): | ||||||||||||||||||||||||||||||||
name: str | ||||||||||||||||||||||||||||||||
age: int | ||||||||||||||||||||||||||||||||
contact: str | ||||||||||||||||||||||||||||||||
Comment on lines
+7
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add input validation for age and contact fields. The current model lacks validation constraints. Consider adding:
Apply this diff to add validation: class DonorCreate(BaseModel):
name: str
- age: int
- contact: str
+ age: int = Field(..., gt=0, lt=150)
+ contact: str = Field(..., regex=r'^\+?1?\d{9,15}$') 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@router.post("/register") | ||||||||||||||||||||||||||||||||
def register_donor(donor: DonorCreate): | ||||||||||||||||||||||||||||||||
donors.append(donor.dict()) | ||||||||||||||||||||||||||||||||
return {"message": "Donor registered successfully", "donor": donor} | ||||||||||||||||||||||||||||||||
Comment on lines
+12
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling and implement GET endpoint. The current implementation lacks error handling and a way to retrieve donor information. Add error handling and a GET endpoint: +@router.get("/")
+def get_donors():
+ return {"donors": donors}
+
@router.post("/register")
-def register_donor(donor: DonorCreate):
+async def register_donor(donor: DonorCreate):
+ try:
donors.append(donor.dict())
return {"message": "Donor registered successfully", "donor": donor}
+ except Exception as e:
+ raise HTTPException(status_code=500, detail=str(e)) 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,19 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from fastapi import APIRouter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from pydantic import BaseModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
router = APIRouter() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
organisations = [] # In-memory storage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class OrganisationCreate(BaseModel): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
description: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
contact: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+7
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add input validation for organisation fields. The current model lacks validation constraints for contact and description fields. Apply this diff to add validation: class OrganisationCreate(BaseModel):
- name: str
- description: str
- contact: str
+ name: str = Field(..., min_length=1, max_length=100)
+ description: str = Field(..., min_length=10, max_length=1000)
+ contact: str = Field(..., regex=r'^\+?1?\d{9,15}$') 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@router.post("/register") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def register_organisation(org: OrganisationCreate): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
organisations.append(org.dict()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return {"message": "Organisation registered successfully", "organisation": org} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@router.get("/") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_organisations(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return {"organisations": organisations} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+12
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling and CRUD operations. The current implementation lacks error handling and complete CRUD operations. Add error handling and additional endpoints: +from fastapi import HTTPException
+
@router.post("/register")
-def register_organisation(org: OrganisationCreate):
+async def register_organisation(org: OrganisationCreate):
+ try:
organisations.append(org.dict())
return {"message": "Organisation registered successfully", "organisation": org}
+ except Exception as e:
+ raise HTTPException(status_code=500, detail=str(e))
@router.get("/")
-def get_organisations():
+async def get_organisations():
return {"organisations": organisations}
+
+@router.put("/{org_id}")
+async def update_organisation(org_id: int, org: OrganisationCreate):
+ if org_id >= len(organisations):
+ raise HTTPException(status_code=404, detail="Organisation not found")
+ organisations[org_id] = org.dict()
+ return {"message": "Organisation updated successfully"}
+
+@router.delete("/{org_id}")
+async def delete_organisation(org_id: int):
+ if org_id >= len(organisations):
+ raise HTTPException(status_code=404, detail="Organisation not found")
+ organisations.pop(org_id)
+ return {"message": "Organisation deleted successfully"} 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Getting Started with Create React App | ||
|
||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). | ||
|
||
## Available Scripts | ||
|
||
In the project directory, you can run: | ||
|
||
### `npm start` | ||
|
||
Runs the app in the development mode.\ | ||
Open [http://localhost:3000](http://localhost:3000) to view it in your browser. | ||
|
||
The page will reload when you make changes.\ | ||
You may also see any lint errors in the console. | ||
|
||
### `npm test` | ||
|
||
Launches the test runner in the interactive watch mode.\ | ||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. | ||
|
||
### `npm run build` | ||
|
||
Builds the app for production to the `build` folder.\ | ||
It correctly bundles React in production mode and optimizes the build for the best performance. | ||
|
||
The build is minified and the filenames include the hashes.\ | ||
Your app is ready to be deployed! | ||
|
||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. | ||
|
||
### `npm run eject` | ||
|
||
**Note: this is a one-way operation. Once you `eject`, you can't go back!** | ||
|
||
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. | ||
|
||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. | ||
|
||
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. | ||
|
||
## Learn More | ||
|
||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). | ||
|
||
To learn React, check out the [React documentation](https://reactjs.org/). | ||
|
||
### Code Splitting | ||
|
||
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) | ||
|
||
### Analyzing the Bundle Size | ||
|
||
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) | ||
|
||
### Making a Progressive Web App | ||
|
||
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) | ||
|
||
### Advanced Configuration | ||
|
||
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) | ||
|
||
### Deployment | ||
|
||
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) | ||
|
||
### `npm run build` fails to minify | ||
|
||
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Secure CORS configuration for production.
The current CORS configuration allows requests only from the development frontend. For production, consider:
Apply this diff:
📝 Committable suggestion