celise88 commited on
Commit
2b80df9
1 Parent(s): 0726b70

add user registration/login/SQL database

Browse files
db_utils.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import create_engine
2
+ from sqlalchemy.ext.declarative import declarative_base
3
+ from sqlalchemy.orm import sessionmaker
4
+
5
+ SQLALCHEMY_DATABASE_URL = "sqlite:///./embedding_db.db"
6
+
7
+ engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
8
+ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
9
+ Base = declarative_base()
10
+
11
+ def get_db():
12
+ db = SessionLocal()
13
+ try:
14
+ yield db
15
+ finally:
16
+ db.close()
embedding_db.db ADDED
Binary file (12.3 kB). View file
 
main.py CHANGED
@@ -7,14 +7,21 @@
7
  # License: MIT License
8
 
9
  # IMPORTS
10
- from fastapi import FastAPI, Request, Form, File, UploadFile, BackgroundTasks
11
  from fastapi.templating import Jinja2Templates
12
  from fastapi.staticfiles import StaticFiles
13
  from fastapi.responses import HTMLResponse, Response
 
14
  import pandas as pd
 
 
15
  from scrape_onet import get_onet_code, get_onet_description, get_onet_tasks
16
  from match_utils import neighborhoods, get_resume, skillNER, sim_result_loop, get_links
17
- import time
 
 
 
 
18
 
19
  # APP SETUP
20
  app = FastAPI()
@@ -24,6 +31,43 @@ templates = Jinja2Templates(directory="templates/")
24
  # LOAD DATA
25
  onet = pd.read_csv('static/ONET_JobTitles.csv')
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  ### JOB INFORMATION CENTER ###
28
  # GET
29
  @app.get("/")
@@ -61,13 +105,11 @@ def get_matches(request: Request):
61
  # POST
62
  @app.post('/find-my-match/', response_class=HTMLResponse)
63
  async def post_matches(request: Request, resume: UploadFile = File(...)):
64
- t = time.time()
65
  resume = get_resume(resume)
66
  skills = await skillNER(resume)
67
  simResults = await sim_result_loop(resume)
68
- links = get_links(simResults)
69
- print(time.time() - t)
70
- return templates.TemplateResponse('find_my_match.html', context={'request': request, 'resume': resume, 'skills': skills, 'simResults': simResults, 'links': links})
71
 
72
  @app.get("/find-match/", response_class=HTMLResponse)
73
  def find_match(request: Request):
 
7
  # License: MIT License
8
 
9
  # IMPORTS
10
+ from fastapi import FastAPI, Request, Form, File, UploadFile, BackgroundTasks, Depends
11
  from fastapi.templating import Jinja2Templates
12
  from fastapi.staticfiles import StaticFiles
13
  from fastapi.responses import HTMLResponse, Response
14
+ from sqlalchemy.orm.session import Session
15
  import pandas as pd
16
+ import time
17
+ from uuid import uuid1
18
  from scrape_onet import get_onet_code, get_onet_description, get_onet_tasks
19
  from match_utils import neighborhoods, get_resume, skillNER, sim_result_loop, get_links
20
+ from db_utils import get_db, Base, engine
21
+ from user_utils import DBUsers, Hash
22
+
23
+ # DB SETUP
24
+ Base.metadata.create_all(engine)
25
 
26
  # APP SETUP
27
  app = FastAPI()
 
31
  # LOAD DATA
32
  onet = pd.read_csv('static/ONET_JobTitles.csv')
33
 
34
+ @app.get("/register/", response_class=HTMLResponse)
35
+ def get_register(request: Request):
36
+ return templates.TemplateResponse('register.html', context={'request': request})
37
+
38
+ @app.get("/login/", response_class=HTMLResponse)
39
+ def get_login(request: Request):
40
+ return templates.TemplateResponse('login.html', context={'request': request})
41
+
42
+ @app.post('/register/', response_class=HTMLResponse)
43
+ def post_register(request: Request, username: str = Form(...), password: str = Form(...), email: str = Form(...), db: Session = Depends(get_db)):
44
+ new_user = DBUsers(id = str(uuid1()), username = username, email = email, password = Hash.bcrypt(password))
45
+ db.add(new_user)
46
+ db.commit()
47
+ db.refresh(new_user)
48
+ message = "You have registered successfully. Please log in to continue"
49
+ return templates.TemplateResponse('register.html', context={'request': request, 'message': message})
50
+
51
+ @app.post("/login/", response_class=HTMLResponse)
52
+ def post_login(request: Request, username: str = Form(...), password: str = Form(...), db: Session = Depends(get_db)):
53
+ un = db.query(DBUsers).filter(DBUsers.username == username).first()
54
+ pw = db.query(DBUsers).filter(DBUsers.username == username).first().password
55
+ if un and Hash.verify(password, pw) == True:
56
+ response = Response()
57
+ response.set_cookie(key="id", value=db.query(DBUsers).filter(DBUsers.username == username).first().id)
58
+ message = "You have been successfully logged in."
59
+ return templates.TemplateResponse('login.html', context={'request': request, "message": message})
60
+ else:
61
+ message = "Username or password not found. Please try again."
62
+ return templates.TemplateResponse('login.html', context={'request': request, "message": message})
63
+
64
+ @app.get("/logout/", response_class=HTMLResponse)
65
+ def get_logout(request: Request):
66
+ with open('static/log.txt', 'w') as l:
67
+ l.write('')
68
+ message = "You have been successfully logged out."
69
+ return templates.TemplateResponse('login.html', context={'request': request, "message": message})
70
+
71
  ### JOB INFORMATION CENTER ###
72
  # GET
73
  @app.get("/")
 
105
  # POST
106
  @app.post('/find-my-match/', response_class=HTMLResponse)
107
  async def post_matches(request: Request, resume: UploadFile = File(...)):
 
108
  resume = get_resume(resume)
109
  skills = await skillNER(resume)
110
  simResults = await sim_result_loop(resume)
111
+ links = get_links(simResults[0])
112
+ return templates.TemplateResponse('find_my_match.html', context={'request': request, 'resume': resume, 'skills': skills, 'simResults': simResults[0], 'links': links})
 
113
 
114
  @app.get("/find-match/", response_class=HTMLResponse)
115
  def find_match(request: Request):
match_utils.py CHANGED
@@ -91,7 +91,7 @@ async def sim_result_loop(resume):
91
  simResults.reset_index(drop=True, inplace=True)
92
  for x in range(len(simResults)):
93
  simResults.iloc[x,1] = format_sim(simResults.iloc[x,1])
94
- return simResults
95
 
96
  async def skillNER(resume):
97
  def clean_my_text(text):
 
91
  simResults.reset_index(drop=True, inplace=True)
92
  for x in range(len(simResults)):
93
  simResults.iloc[x,1] = format_sim(simResults.iloc[x,1])
94
+ return simResults, embeds
95
 
96
  async def skillNER(resume):
97
  def clean_my_text(text):
requirements.txt CHANGED
@@ -16,4 +16,7 @@ python-dotenv==0.21.1
16
  transformers==4.25.1
17
  torch==1.13.1
18
  accelerate==0.16.0
19
- plotly-express==0.4.1
 
 
 
 
16
  transformers==4.25.1
17
  torch==1.13.1
18
  accelerate==0.16.0
19
+ plotly-express==0.4.1
20
+ sqlalchemy==2.0.3
21
+ bcrypt==4.0.1
22
+ passlib==1.7.4
static/styles.css CHANGED
@@ -230,6 +230,19 @@ html {
230
  align-content: left;
231
  }
232
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  .output__table-item {
234
  font-size: 14px;
235
  color: #2c2161;
 
230
  align-content: left;
231
  }
232
 
233
+ .form__login {
234
+ display: flex;
235
+ flex-direction: column;
236
+ justify-content: center;
237
+ align-items: center;
238
+ }
239
+
240
+ .form__login-label {
241
+ font-size: 14px;
242
+ color: #2c2161;
243
+ text-align: center;
244
+ }
245
+
246
  .output__table-item {
247
  font-size: 14px;
248
  color: #2c2161;
templates/candidate_matcher.html CHANGED
@@ -17,6 +17,7 @@
17
  <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
  <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
  <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
 
20
  </ul>
21
  </header>
22
  <main class="main">
 
17
  <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
  <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
  <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
20
+ <li class="navbar__navigation-item"><a href="/login/" class="navbar__link">Login</a></li>
21
  </ul>
22
  </header>
23
  <main class="main">
templates/find_hire.html CHANGED
@@ -17,6 +17,7 @@
17
  <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
  <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
  <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
 
20
  </ul>
21
  </header>
22
  <main class="main">
 
17
  <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
  <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
  <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
20
+ <li class="navbar__navigation-item"><a href="/login/" class="navbar__link">Login</a></li>
21
  </ul>
22
  </header>
23
  <main class="main">
templates/find_match.html CHANGED
@@ -17,6 +17,7 @@
17
  <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
  <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
  <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
 
20
  </ul>
21
  </header>
22
  <main class="main">
 
17
  <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
  <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
  <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
20
+ <li class="navbar__navigation-item"><a href="/login/" class="navbar__link">Login</a></li>
21
  </ul>
22
  </header>
23
  <main class="main">
templates/find_my_match.html CHANGED
@@ -17,6 +17,7 @@
17
  <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
  <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
  <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
 
20
  </ul>
21
  </header>
22
  <main class="main">
 
17
  <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
  <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
  <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
20
+ <li class="navbar__navigation-item"><a href="/login/" class="navbar__link">Login</a></li>
21
  </ul>
22
  </header>
23
  <main class="main">
templates/job_list.html CHANGED
@@ -17,6 +17,7 @@
17
  <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
  <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
  <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
 
20
  </ul>
21
  </header>
22
  <main class="main">
 
17
  <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
  <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
  <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
20
+ <li class="navbar__navigation-item"><a href="/login/" class="navbar__link">Login</a></li>
21
  </ul>
22
  </header>
23
  <main class="main">
templates/login.html ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Dashboard</title>
8
+ <link rel="stylesheet" href="/static/styles.css">
9
+ </head>
10
+ <body>
11
+ <header class="navbar">
12
+ <div class="navbar__brand">
13
+ <img src="/static/PF.png" class="navbar__logo" alt="Pathfinder logo" />
14
+ <a href="/" class="navbar__logo">Pathfinder</a>
15
+ </div>
16
+ <ul class="navbar__navigation">
17
+ <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
+ <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
+ <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
20
+ <li class="navbar__navigation-item"><a href="/login/" class="navbar__link">Login</a></li>
21
+ </ul>
22
+ </header>
23
+ <main class="main">
24
+ <h1 class="pagetitle">User Login</h1>
25
+ <h2 class="pagesubtitle">Welcome to Pathfinder!</h2>
26
+ <h2 class="pagesubtitle">Enter your username and password below to get started</h2>
27
+ <section>
28
+ <form class="form__login" method="POST" enctype="application/x-www-form-urlencoded">
29
+ <label for="username" class="form__login-label" style="color: #2c2161">username:</label>
30
+ <input type="text" name="username" id="username" style="margin-bottom: 20px" class="form__input-field" />
31
+ <label for="password" class="form__login-label" style="color: #2c2161">password:</label>
32
+ <input type="text" name="password" id="password" class="form__input-field" />
33
+ <br>
34
+ <br>
35
+ <br>
36
+ <button type="submit" class="form__submit">Submit</button>
37
+ <br>
38
+ <button formaction="/register/" formmethod="GET" type="submit" class="form__submit">Create a new account</button>
39
+ </form>
40
+ <br>
41
+ <br>
42
+ {% if message %}
43
+ <h2 class="pagesubtitle">{{ message }}</h2>
44
+ {% endif %}
45
+ </section>
46
+ <br>
47
+ <br>
48
+ </main>
49
+ <footer class="footer">
50
+ <ul class="footer__text">
51
+ <li class="footer__text-item">© 2023 Pathfinder</li>
52
+ </ul>
53
+ </footer>
54
+ </body>
55
+ </html>
templates/register.html ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Dashboard</title>
8
+ <link rel="stylesheet" href="/static/styles.css">
9
+ </head>
10
+ <body>
11
+ <header class="navbar">
12
+ <div class="navbar__brand">
13
+ <img src="/static/PF.png" class="navbar__logo" alt="Pathfinder logo" />
14
+ <a href="/" class="navbar__logo">Pathfinder</a>
15
+ </div>
16
+ <ul class="navbar__navigation">
17
+ <li class="navbar__navigation-item"><a href="/explore-job-neighborhoods/" class="navbar__link">Explore Job Neighborhoods</a></li>
18
+ <li class="navbar__navigation-item"><a href="/find-my-match/" class="navbar__link">Find My Match</a></li>
19
+ <li class="navbar__navigation-item"><a href="/find-my-hire/" class="navbar__link">Find My Next Hire</a></li>
20
+ <li class="navbar__navigation-item"><a href="/login/" class="navbar__link">Login</a></li>
21
+ </ul>
22
+ </header>
23
+ <main class="main">
24
+ <h1 class="pagetitle">User Registration</h1>
25
+ <h2 class="pagesubtitle">Welcome to Pathfinder!</h2>
26
+ <h2 class="pagesubtitle">Fill out the form below to register for an account</h2>
27
+ <section>
28
+ <form class="form__login" method="POST">
29
+ <label for="username" class="form__login-label" style="color: #2c2161;">username:</label>
30
+ <input type="text" name="username" id="username" style="margin-bottom: 20px" class="form__input-field" />
31
+ <label for="password" class="form__login-label" style="color: #2c2161;">password:</label>
32
+ <input type="text" name="password" id="password" style="margin-bottom: 20px" class="form__input-field" />
33
+ <label for="email" class="form__login-label" style="color: #2c2161;">email:</label>
34
+ <input type="text" name="email" id="email" style="margin-bottom: 20px" class="form__input-field" />
35
+ <br>
36
+ <br>
37
+ <button type="submit" class="form__submit">Submit</button>
38
+ </form>
39
+ <br>
40
+ <br>
41
+ {% if message %}
42
+ <h2 class="pagesubtitle">{{ message }}</h2>
43
+ {% endif %}
44
+ <br>
45
+ <br>
46
+ </section>
47
+ </main>
48
+ <footer class="footer">
49
+ <ul class="footer__text">
50
+ <li class="footer__text-item">© 2023 Pathfinder</li>
51
+ </ul>
52
+ </footer>
53
+ </body>
54
+ </html>
user_utils.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from db_utils import Base
2
+ from sqlalchemy import Column, String
3
+ from passlib.context import CryptContext
4
+
5
+ pwd_cxt = CryptContext(schemes=['bcrypt'], deprecated="auto")
6
+
7
+ class Hash():
8
+ def bcrypt(password: str):
9
+ return pwd_cxt.hash(password)
10
+
11
+ def verify(plain_password: str, hashed_password: str):
12
+ return pwd_cxt.verify(plain_password, hashed_password)
13
+
14
+ class DBUsers(Base):
15
+ __tablename__ = 'users'
16
+ id = Column(String, primary_key=True)
17
+ username = Column(String)
18
+ password = Column(String)
19
+ email = Column(String)