copied the code from the working repo

This commit is contained in:
2024-11-30 16:00:48 +03:00
parent f22b92869b
commit 15ac0cb9b8
148 changed files with 23342 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
from fastapi import APIRouter, Depends, status, HTTPException, Response
from fastapi.security.oauth2 import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from .. import database, schemas, models, security, utils
router = APIRouter(tags=['Authentication'])
@router.post('/login', response_model=schemas.Token)
def login(user_credentials: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(database.get_db)):
user = db.query(models.Users).filter(
models.Users.Email == user_credentials.username).first()
if not user:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, detail="Invalid Credentials")
if not utils.verify(user_credentials.password, user.Hashed_password):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, detail="Invalid Credentials")
access_token = security.create_access_token(data={
"UserID": user.UserID,
"Email": user.Email
})
refresh_token = security.create_refresh_token(data={
"UserID": user.UserID,
})
return {"access_token": access_token, "refresh_token": refresh_token}
@router.post('/refresh', response_model=schemas.Token, response_model_exclude_none=True )
def refresh_access_token(refresh_token: str, db: Session = Depends(database.get_db)):
user_id = security.verify_refresh_token(refresh_token)
user = db.query(models.Users).filter(
models.Users.UserID == user_id).first()
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
access_token = security.create_access_token(data={
"UserID": user.UserID,
"Email": user.Email
})
return {"access_token": access_token}

View File

@@ -0,0 +1,247 @@
from fastapi import status, HTTPException, Response, APIRouter, Depends, BackgroundTasks, Query
from sqlalchemy.orm import Session
from sqlalchemy import not_, func
from typing import List, Annotated
from ..database import get_db
from .. import models, schemas, security, crud
router = APIRouter(
prefix="/jobs",
dependencies=[Depends(security.verify_access_token)],
responses={401: {"description": "Unauthorized"}},
tags=['Jobs']
)
@router.get("/", response_model=List[schemas.JobGet])
def get_jobs(db: Session = Depends(get_db)):
jobs = db.query(models.Jobs).all()
if not jobs:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
response: List[schemas.JobGet] = []
for job in jobs:
hardskills = db.query(models.JobsHard_skills.Hard_skillID, models.Hard_skills.Title).\
join(models.Hard_skills, models.JobsHard_skills.Hard_skillID == models.Hard_skills.Hard_skillID).\
filter(models.JobsHard_skills.JobID == job.JobID).all()
Hardskills = [hardskill.Title for hardskill in hardskills]
response += [schemas.JobGet(JobID=job.JobID, UserID = job.UserID, Job_name=job.Job_name, Company_name=job.Company_name,
Link_to_job=job.Link_to_job, Year=job.Year, Qualification=job.Qualification, Time=job.Time,
Salary_after_interview=job.Salary_after_interview, Salary=job.Salary, Email=job.Email, Archive=job.Archive,
Responsibilities=job.Responsibilities, Hardskills=Hardskills)]
return response
@router.get("/{id}", response_model=schemas.JobGet)
def get_job(id: int, db: Session = Depends(get_db)):
job = db.query(models.Jobs).filter(models.Jobs.JobID == id).first()
if not job:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
hardskills = db.query(models.JobsHard_skills.Hard_skillID, models.Hard_skills.Title).\
join(models.Hard_skills, models.JobsHard_skills.Hard_skillID == models.Hard_skills.Hard_skillID).\
filter(models.JobsHard_skills.JobID == id).all()
Hardskills = [hardskill.Title for hardskill in hardskills]
response = schemas.JobGet(JobID=job.JobID, UserID = job.UserID, Job_name=job.Job_name, Company_name=job.Company_name,
Link_to_job=job.Link_to_job, Year=job.Year, Qualification=job.Qualification, Time=job.Time,
Salary_after_interview=job.Salary_after_interview, Salary=job.Salary, Email=job.Email, Archive=job.Archive,
Responsibilities=job.Responsibilities, Hardskills=Hardskills)
return response
@router.get("/matches/{id}", response_model=List[schemas.MatchJob])
def get_matches(id: int, db: Session = Depends(get_db)):
matches = db.query(models.Matches).filter(models.Matches.JobID == id).order_by(models.Matches.Match.desc()).all()
matches = db.query(
models.Students.StudentID,
models.Students.Name,
models.Students.Type,
models.Students.Faculties,
models.Students.Group,
models.Students.Year,
models.Students.Experience_specialty,
models.Students.Time,
models.Students.Soft_skills,
models.Students.Link,
models.Students.Email,
models.Students.Phone_number,
models.Matches.Match
).join(models.Matches, models.Students.StudentID == models.Matches.StudentID).\
filter(models.Matches.JobID == id).\
order_by(models.Matches.Match.desc()).\
all()
if not matches:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return matches
@router.get("/hardskills/{id}", response_model=List[schemas.JobsHardskill])
def get_jobs_hardskills(id: int, db: Session = Depends(get_db)):
hardskills = db.query(models.JobsHard_skills.Hard_skillID, models.Hard_skills.Title).\
join(models.Hard_skills, models.JobsHard_skills.Hard_skillID == models.Hard_skills.Hard_skillID).\
filter(models.JobsHard_skills.JobID == id).all()
if not hardskills:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return hardskills
@router.get("/students-search/", response_model=List[schemas.StudentUpdate])
def get_students(
year: int = None,
time: Annotated[list[str], Query()] = [],
hardskills: Annotated[list[str], Query()] = [],
faculties: str = None,
experience_specialty: bool = None,
db: Session = Depends(get_db)
):
if hardskills:
students = db.query(
models.Students.StudentID,
models.Students.Name,
models.Students.Type,
models.Students.Faculties,
models.Students.Group,
models.Students.Уear,
models.Students.Experience_specialty,
models.Students.Time,
models.Students.Soft_skills,
models.Students.Link,
models.Students.Email,
models.Students.Phone_number,
).join(models.StudentsHard_skills, models.Students.StudentID == models.StudentsHard_skills.StudentID).\
join(models.Hard_skills, models.StudentsHard_skills.Hard_skillID == models.Hard_skills.Hard_skillID).\
filter(models.Hard_skills.Title.in_(hardskills)).distinct(models.Students.StudentID)
else:
students = db.query(models.Students).filter(models.Students.Experience_specialty == experience_specialty)
if time:
students = students.filter(models.Students.Time.op("&&")(time))
if year:
students = students.filter(models.Students.Year >= year)
if faculties:
students = students.filter(models.Students.Faculties.ilike("%" + faculties + "%"))
response: List[schemas.StudentUpdate] = []
for student in students:
hardskills = db.query(models.StudentsHard_skills.Hard_skillID, models.Hard_skills.Title).\
join(models.Hard_skills, models.StudentsHard_skills.Hard_skillID == models.Hard_skills.Hard_skillID).\
filter(models.StudentsHard_skills.StudentID == student.StudentID).all()
Hardskills = [hardskill.Title for hardskill in hardskills]
response += [schemas.StudentUpdate(Name=student.Name, Type=student.Type, Faculties=student.Faculties,
Group=student.Group, Year=student.Year, Experience_specialty=student.Experience_specialty,
Time=student.Time, Soft_skills=student.Soft_skills, Link=student.Link, Email=student.Email,
Phone_number=student.Phone_number, Hardskills=Hardskills)]
return response
@router.get("/responses/{id}", response_model=List[schemas.Response])
def get_responses(id: int, db: Session = Depends(get_db)):
responses = db.query(models.Responses).filter(models.Responses.JobID == id).all()
if not responses:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return responses
@router.get("/responses/", response_model=List[schemas.Response])
def get_responses_all_unprocessed(db: Session = Depends(get_db)):
responses = db.query(
models.Responses.ResponseID,
models.Responses.StudentID,
models.Responses.JobID,
models.Responses.Status,
models.Responses.Comment,
models.Responses.Link,
).join(models.Students, models.Students.StudentID == models.Responses.StudentID).\
filter(models.Responses.Status == "Ожидает рассмотрения").\
order_by(models.Students.Year.asc()).\
all() # order_by работате и на буквы в начале группы. Так, сейчас должен работать по идеи
if not responses:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return responses
@router.post("/", status_code=status.HTTP_201_CREATED, response_model=schemas.Job)
def create_job(
job: schemas.JobCreate,
background_tasks: BackgroundTasks,
db: Session = Depends(get_db),
current_user: models.Users = Depends(security.get_current_user)
):
new_job = models.Jobs(UserID=current_user.UserID, **job.model_dump(exclude='Hardskills'))
db.add(new_job)
db.flush()
crud.update_hardskills(new_job.JobID, job.Hardskills, is_job=True, db=db)
if not new_job.Archive:
crud.update_matches(new_job.JobID, is_job=True, db=db, background_tasks=background_tasks)
crud.commit_transaction(db)
return new_job
@router.put("/{id}", response_model=schemas.Job)
def update_job(
id: int,
updated_job: schemas.JobUpdate,
background_tasks: BackgroundTasks,
db: Session = Depends(get_db),
current_user: models.Users = Depends(security.get_current_user)
):
job_query = db.query(models.Jobs).filter(models.Jobs.JobID == id)
job = job_query.first()
if not job:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
updated_data = updated_job.model_dump(exclude='Hardskills')
updated_data["UserID"] = current_user.UserID
job_query.update(updated_data, synchronize_session=False)
db.flush()
crud.update_hardskills(id, updated_job.Hardskills, is_job=True, db=db)
if not updated_job.Archive:
crud.update_matches(id, is_job=True, db=db, background_tasks=background_tasks)
else:
db.query(models.Matches).filter(models.Matches.JobID == id).delete()
db.flush()
crud.commit_transaction(db)
return job_query.first()
@router.put("/responses/{id}", status_code=status.HTTP_200_OK)
def update_response(id: int, updated_response: schemas.ResponseUpdate, background_tasks: BackgroundTasks, db: Session = Depends(get_db)):
updated_record = crud.update_record(models.Responses, id, updated_response.model_dump(), db, background_tasks)
return updated_record
@router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_job(id: int, db: Session = Depends(get_db)):
job_query = db.query(models.Jobs).filter(models.Jobs.JobID == id)
job = job_query.first()
if not job:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
job_query.delete()
crud.commit_transaction(db)
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@@ -0,0 +1,55 @@
from fastapi import status, HTTPException, APIRouter, Depends, UploadFile
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from minio import Minio
from typing import List
from io import BytesIO
from os import remove
from starlette.background import BackgroundTask
from ..database import get_db
from ..storage import get_client
from .. import models, schemas, security
router = APIRouter(
prefix="/services",
dependencies=[Depends(security.verify_api_key)],
tags=['Services']
)
@router.get("/resume/{filename}")
def get_resume(filename: str, client: Minio = Depends(get_client)):
response = client.fget_object("tgjobs", filename, filename)
if not response:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
task = BackgroundTask(remove, filename)
return FileResponse(path=filename, filename=response.object_name, media_type=response.content_type, background=task)
@router.get("/hardskills/", response_model=List[schemas.Hard_skill])
def get_all_hardskills(db: Session = Depends(get_db)):
hardskills = db.query(models.Hard_skills).filter(models.Hard_skills.Title.ilike("%")).all()
if not hardskills:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return hardskills
@router.get("/hardskills/{title}", response_model=List[schemas.Hard_skill])
def get_hardskills(title: str, db: Session = Depends(get_db)):
hardskills = db.query(models.Hard_skills).filter(models.Hard_skills.Title.ilike("%" + title + "%")).all()
if not hardskills:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return hardskills
@router.post("/resume/")
async def upload_resume_to_cloud(file: UploadFile, client: Minio = Depends(get_client)):
response = client.put_object("tgjobs", file.filename, BytesIO(await file.read()), file.size, file.content_type)
if not response:
raise HTTPException(status_code=status.HTTP_409_CONFLICT)
return {"filename": response.object_name}

View File

@@ -0,0 +1,197 @@
from fastapi import status, HTTPException, Response, APIRouter, Depends, Query, BackgroundTasks
from sqlalchemy.orm import Session
from typing import List, Annotated
from ..database import get_db
from .. import models, schemas, security, crud
router = APIRouter(
prefix="/students",
dependencies=[Depends(security.verify_api_key)],
tags=['Students']
)
@router.get("/", response_model=List[schemas.Student])
def get_students(db: Session = Depends(get_db)):
students = db.query(models.Students)
return students
@router.get("/{id}", response_model=schemas.Student)
def get_student(id: int, db: Session = Depends(get_db)):
student = db.query(models.Students).filter(models.Students.StudentID == id).first()
if not student:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return student
@router.get("/responses/{id}", response_model=List[schemas.Response])
def get_responses(id: int, db: Session = Depends(get_db)):
responses = db.query(models.Responses).filter(models.Responses.StudentID == id).all()
if not responses:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return responses
@router.get("/matches/{id}", response_model=List[schemas.MatchStudent])
def get_matches(id: int, db: Session = Depends(get_db)):
matches = db.query(
models.Jobs.JobID,
models.Jobs.Company_name,
models.Jobs.Link_to_job,
models.Jobs.Job_name,
models.Jobs.Year,
models.Jobs.Qualification,
models.Jobs.Time,
models.Jobs.Salary_after_interview,
models.Jobs.Salary,
models.Jobs.Email,
models.Jobs.Responsibilities,
models.Matches.Match
).join(models.Matches, models.Jobs.JobID == models.Matches.JobID).\
filter(models.Matches.StudentID == id).\
order_by(models.Matches.Match.desc()).\
all()
if not matches:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return matches
@router.get("/hardskills/{id}", response_model=List[schemas.StudentsHardskill])
def get_students_hardskills(id: int, db: Session = Depends(get_db)):
hardskills = db.query(models.StudentsHard_skills.Hard_skillID, models.Hard_skills.Title).\
join(models.Hard_skills, models.StudentsHard_skills.Hard_skillID == models.Hard_skills.Hard_skillID).\
filter(models.StudentsHard_skills.StudentID == id).all()
if not hardskills:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return hardskills
@router.get("/jobs-search/", response_model=List[schemas.Jobs_search])
def get_jobs(year: str = None, qualification: bool = None, time: Annotated[list[str], Query()] = [], salary: int = None, hardskills: Annotated[list[str], Query()] = [], search: str = None, db: Session = Depends(get_db)):
if hardskills:
jobs = db.query(
models.Jobs.Job_name,
models.Jobs.Company_name,
models.Jobs.Link_to_job,
models.Jobs.Year,
models.Jobs.Qualification,
models.Jobs.Time,
models.Jobs.Salary,
models.Jobs.Salary_after_interview,
models.Jobs.Email,
models.Jobs.Responsibilities,
models.Jobs.JobID,
models.JobsHard_skills.JobID,
models.Hard_skills.Title
).join(models.JobsHard_skills, models.Jobs.JobID == models.JobsHard_skills.JobID).\
join(models.Hard_skills, models.JobsHard_skills.Hard_skillID == models.Hard_skills.Hard_skillID).\
filter(models.Hard_skills.Title.in_(hardskills), models.Jobs.Qualification == qualification, models.Jobs.Archive == False).distinct(models.Jobs.JobID)
else:
jobs = db.query(models.Jobs).filter(models.Jobs.Qualification == qualification, models.Jobs.Archive == False)
if year:
jobs = jobs.filter(models.Jobs.Year >= year)
if salary:
jobs = jobs.filter(models.Jobs.Salary >= salary)
if time:
jobs = jobs.filter(models.Jobs.Time.op("&&")(time))
if search:
jobs = jobs.filter(models.Jobs.Job_name.match(search))
return jobs.all()
@router.post("/", status_code=status.HTTP_201_CREATED, response_model=schemas.Student)
def create_student(student: schemas.StudentCreate, background_tasks: BackgroundTasks, db: Session = Depends(get_db)):
new_student = models.Students(**student.model_dump(exclude='Hardskills'))
db.add(new_student)
db.flush()
crud.update_hardskills(new_student.StudentID, student.Hardskills, is_job=False, db=db)
crud.update_matches(new_student.StudentID, is_job=False, db=db, background_tasks=background_tasks)
crud.commit_transaction(db)
return new_student
@router.post("/responses/", status_code=status.HTTP_201_CREATED, response_model=schemas.Response)
def add_to_responses(response: schemas.ResponseCreate, db: Session = Depends(get_db)):
new_response = models.Responses(**response.model_dump())
db.add(new_response)
crud.commit_transaction(db)
return new_response
@router.put("/{id}", response_model=schemas.Student)
def update_student(id: int, updated_student: schemas.StudentUpdate, background_tasks: BackgroundTasks, db: Session = Depends(get_db)):
student_query = db.query(models.Students).filter(models.Students.StudentID == id)
student = student_query.first()
if not student:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
student_query.update(updated_student.model_dump(exclude='Hardskills'))
db.flush()
crud.update_hardskills(id, updated_student.Hardskills, is_job=False, db=db)
crud.update_matches(id, is_job=False, db=db, background_tasks=background_tasks)
crud.commit_transaction(db)
return student_query.first()
@router.put("/responses/{id}", status_code=status.HTTP_200_OK)
def update_response(id: int, updated_response: schemas.ResponseUpdate, background_tasks: BackgroundTasks, db: Session = Depends(get_db)):
updated_record = crud.update_record(models.Responses, id, updated_response.model_dump(), db, background_tasks)
return updated_record
@router.patch("/{id}", status_code=status.HTTP_200_OK)
def update_students_link(id: int, Link: str, db: Session = Depends(get_db)):
student_query = db.query(models.Students).filter(models.Students.StudentID == id)
student = student_query.first()
if not student:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
student_query.update({models.Students.Link: Link})
db.flush()
crud.commit_transaction(db)
return student_query.first()
@router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_student(id: int, db: Session = Depends(get_db)):
student_query = db.query(models.Students).filter(models.Students.StudentID == id)
student = student_query.first()
if not student:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
student_query.delete()
crud.commit_transaction(db)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.delete("/responses/{id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_responses(id: int, db: Session = Depends(get_db)):
responses_query = db.query(models.Responses).filter(models.Responses.ResponseID == id)
response = responses_query.first()
if not response:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
responses_query.delete()
crud.commit_transaction(db)
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@@ -0,0 +1,60 @@
from fastapi import FastAPI, status, HTTPException, Depends, APIRouter
from sqlalchemy.orm import Session
from .. import models, schemas, security, utils
from ..database import get_db
router = APIRouter(
prefix="/users",
tags=['Users']
)
@router.post("/", status_code=status.HTTP_201_CREATED, response_model=schemas.User)
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
existing_user = db.query(models.Users).filter(models.Users.Email == user.Email).first()
if existing_user:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="User with this email already exists"
)
hashed_password = utils.hash(user.Hashed_password)
user_data = user.model_dump()
user_data["Hashed_password"] = hashed_password
new_user = models.Users(**user_data)
db.add(new_user)
db.commit()
db.refresh(new_user)
return new_user
@router.put("/{email}", response_model=schemas.User)
def update_user(email: str, updated_user: schemas.UserUpdate, db: Session = Depends(get_db), current_user: models.Users = Depends(security.get_current_user)):
if current_user.Email != email:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
existing_user = db.query(models.Users).filter(models.Users.Email == email).first()
if not existing_user:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
if updated_user.Email:
email_user = db.query(models.Users).filter(models.Users.Email == updated_user.Email).first()
if email_user and email_user.Email != email:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Email already in use")
if updated_user.Hashed_password:
hashed_password = utils.hash(updated_user.Hashed_password)
updated_user.Hashed_password = hashed_password
for key, value in updated_user.model_dump(exclude_unset=True).items():
setattr(existing_user, key, value)
db.commit()
db.refresh(existing_user)
return existing_user