Coverage for src \ main.py: 94%
133 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-06 20:52 +0300
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-06 20:52 +0300
1from fastapi import FastAPI, Depends, HTTPException
2from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
3from sqlalchemy import create_engine, Column, Integer, String, DateTime
4from sqlalchemy.ext.declarative import declarative_base
5from sqlalchemy.orm import sessionmaker, Session
6from datetime import datetime, timedelta
7from jose import jwt
8from passlib.context import CryptContext
10# db
11SQLALCHEMY_DATABASE_URL = 'sqlite:///./tasks.db'
12engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={'check_same_thread': False})
13SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
14Base = declarative_base()
16class User(Base):
17 __tablename__ = 'users'
18 id = Column(Integer, primary_key=True, index=True)
19 username = Column(String, unique=True, index=True)
20 hashed_password = Column(String)
22class Task(Base):
23 __tablename__ = 'tasks'
24 id = Column(Integer, primary_key=True, index=True)
25 title = Column(String)
26 description = Column(String, nullable=True)
27 status = Column(String, default='pending')
28 priority = Column(String, default='medium')
29 created_at = Column(DateTime, default=datetime.now)
30 owner_id = Column(Integer)
32Base.metadata.create_all(bind=engine)
34#authentification
35SECRET_KEY = 'secret'
36ALGORITHM = 'HS256'
37pwd_context = CryptContext(schemes=['pbkdf2_sha256'], deprecated='auto')
38oauth2_scheme = OAuth2PasswordBearer(tokenUrl='token')
40def get_db():
41 db = SessionLocal()
42 try:
43 yield db
44 finally:
45 db.close()
47def get_password_hash(password):
48 return pwd_context.hash(password)
50def verify_password(plain_password, hashed_password):
51 return pwd_context.verify(plain_password, hashed_password)
53def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
54 try:
55 username = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]).get('sub')
56 if username is None:
57 raise HTTPException(status_code=401, detail='Invalid token')
58 user = db.query(User).filter(User.username == username).first()
59 if user is None:
60 raise HTTPException(status_code=401, detail='User not found')
61 return user
62 except:
63 raise HTTPException(status_code=401, detail='Invalid token')
65#fastapi
66app = FastAPI()
68@app.post('/register')
69def register(username: str, password: str, db: Session = Depends(get_db)):
70 existing_user = db.query(User).filter(User.username == username).first()
71 if existing_user:
72 raise HTTPException(status_code=400, detail='Username already exists')
74 new_user = User(username=username, hashed_password=get_password_hash(password))
75 db.add(new_user)
76 db.commit()
78 return {'id': new_user.id, 'username': new_user.username}
80@app.post('/token')
81def login(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
82 user = db.query(User).filter(User.username == form_data.username).first()
83 if not user or not verify_password(form_data.password, user.hashed_password):
84 raise HTTPException(status_code=401, detail='Incorrect username or password')
86 token_data = {'sub': user.username, 'exp': datetime.now() + timedelta(minutes=30)}
87 token = jwt.encode(token_data, SECRET_KEY, algorithm=ALGORITHM)
89 return {'access_token': token, 'token_type': 'bearer'}
91@app.post('/tasks')
92def create_task(title: str, description: str = None, priority: str = 'medium', db: Session = Depends(get_db),
93 current_user=Depends(get_current_user)):
94 new_task = Task(title=title, description=description, priority=priority, owner_id=current_user.id)
95 db.add(new_task)
96 db.commit()
97 db.refresh(new_task)
99 return {
100 'id': new_task.id,
101 'title': new_task.title,
102 'description': new_task.description,
103 'status': new_task.status,
104 'priority': new_task.priority,
105 'created_at': new_task.created_at,
106 'owner_id': new_task.owner_id
107 }
109@app.get('/tasks')
110def get_tasks(sort_by: str = None, sort_desc: bool = False, search: str = None, db: Session = Depends(get_db),
111 current_user=Depends(get_current_user)):
112 tasks_query = db.query(Task).filter(Task.owner_id == current_user.id)
114 if search:
115 tasks_query = tasks_query.filter(Task.title.contains(search) | Task.description.contains(search))
117 if sort_by:
118 if sort_by == 'title':
119 if sort_desc:
120 tasks_query = tasks_query.order_by(Task.title.desc())
121 else:
122 tasks_query = tasks_query.order_by(Task.title)
123 elif sort_by == 'status':
124 if sort_desc:
125 tasks_query = tasks_query.order_by(Task.status.desc())
126 else:
127 tasks_query = tasks_query.order_by(Task.status)
128 elif sort_by == 'created_at':
129 if sort_desc:
130 tasks_query = tasks_query.order_by(Task.created_at.desc())
131 else:
132 tasks_query = tasks_query.order_by(Task.created_at)
134 tasks = tasks_query.all()
135 return [
136 {
137 'id': task.id,
138 'title': task.title,
139 'description': task.description,
140 'status': task.status,
141 'priority': task.priority,
142 'created_at': task.created_at,
143 'owner_id': task.owner_id
144 }
145 for task in tasks
146 ]
148@app.get('/tasks/top/{n}')
149def get_top_tasks(n: int, db: Session = Depends(get_db), current_user=Depends(get_current_user)):
150 all_tasks = db.query(Task).filter(Task.owner_id == current_user.id).all()
151 priority_values = {'high': 1, 'medium': 2, 'low': 3}
152 all_tasks.sort(key=lambda task: priority_values.get(task.priority, float('inf')))
153 top_tasks = all_tasks[:n]
154 return [
155 {
156 'id': task.id,
157 'title': task.title,
158 'description': task.description,
159 'status': task.status,
160 'priority': task.priority,
161 'created_at': task.created_at,
162 'owner_id': task.owner_id
163 }
164 for task in top_tasks
165 ]
167@app.get('/tasks/{task_id}')
168def get_task(task_id: int, db: Session = Depends(get_db), current_user=Depends(get_current_user)):
169 task = db.query(Task).filter(Task.id == task_id, Task.owner_id == current_user.id).first()
171 if not task:
172 raise HTTPException(status_code=404, detail='Task not found')
174 return {
175 'id': task.id,
176 'title': task.title,
177 'description': task.description,
178 'status': task.status,
179 'priority': task.priority,
180 'created_at': task.created_at,
181 'owner_id': task.owner_id
182 }
184@app.put('/tasks/{task_id}')
185def update_task(task_id: int, title: str = None, description: str = None, status: str = None,
186 priority: str = None, db: Session = Depends(get_db), current_user=Depends(get_current_user)):
187 task = db.query(Task).filter(Task.id == task_id, Task.owner_id == current_user.id).first()
189 if not task:
190 raise HTTPException(status_code=404, detail='Task not found')
192 if title is not None:
193 task.title = title
194 if description is not None:
195 task.description = description
196 if status is not None:
197 task.status = status
198 if priority is not None:
199 task.priority = priority
201 db.commit()
202 db.refresh(task)
204 return {
205 'id': task.id,
206 'title': task.title,
207 'description': task.description,
208 'status': task.status,
209 'priority': task.priority,
210 'created_at': task.created_at,
211 'owner_id': task.owner_id
212 }
214@app.delete('/tasks/{task_id}')
215def delete_task(task_id: int, db: Session = Depends(get_db), current_user=Depends(get_current_user)):
216 task = db.query(Task).filter(Task.id == task_id, Task.owner_id == current_user.id).first()
218 if not task:
219 raise HTTPException(status_code=404, detail='Task not found')
221 db.delete(task)
222 db.commit()
224 return {'message': 'Task deleted successfully'}