Skip to content

Commit 69fa7da

Browse files
committed
initial dev on appllication list with search
1 parent 97541a3 commit 69fa7da

6 files changed

Lines changed: 102 additions & 17 deletions

File tree

api/src/controller/userSearch.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from flask_restful import Resource, reqparse
2+
from flask import request
3+
from data.users import getUsers
4+
from utils.authentication import authenticate
5+
from data.permissions import canAccessUserData
6+
7+
8+
class UserSearch(Resource):
9+
PATH = '/user/search'
10+
11+
def get(self):
12+
authenticationPayload = authenticate(request.headers)
13+
if authenticationPayload is None:
14+
return {"message": "Must be logged in"}, 401
15+
auth0_id = authenticationPayload['sub']
16+
17+
permissions = canAccessUserData(auth0_id)
18+
if permissions is None:
19+
return {"message": "Internal Server Error"}, 500
20+
if not permissions:
21+
return {"message": "Permission Denied"}, 403
22+
23+
parser = reqparse.RequestParser()
24+
parser.add_argument('firstName', type=str, required=False)
25+
parser.add_argument('lastName', type=str, required=False)
26+
parser.add_argument('email', type=str, required=False)
27+
parser.add_argument('applicationId', type=str, required=False)
28+
parser.add_argument('userId', type=str, required=False)
29+
parser.add_argument('recipientStatusFilter', type=str, required=False, action="append")
30+
args = parser.parse_args()
31+
32+
matchingUsers = getUsers(applicationStatusFilterList=args['recipientStatusFilter'],
33+
firstName=args['firstName'],
34+
lastName=args['lastName'],
35+
email=args['email'],
36+
applicationId=args['applicationId'],
37+
userId=args['userId'])
38+
39+
if matchingUsers is None:
40+
return {"Message": "Internal Server Error"}, 500
41+
return matchingUsers

api/src/data/users.py

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,60 @@ def getUserQuery():
2020
"LEFT JOIN Sponsors as s ON u.sponsor_id = s.sponsor_id "
2121

2222

23-
def getUsers(status=None, is_virtual=None) -> list:
23+
def getUsers(applicationStatusFilterList: List[str] = None, is_virtual=None, firstName=None, lastName=None, userId=None,
24+
email=None, applicationId=None) -> list:
2425
"""
2526
Get a filtered list of all users in json/dictionary format
26-
:param status: string matching user application status
27+
:param applicationId:
28+
:param email:
29+
:param userId:
30+
:param lastName:
31+
:param firstName:
32+
:param applicationStatusFilterList: list of statuses to match
2733
:param is_virtual: boolean for if you want all virtual/in person users
28-
:return: list of dictionaries with user information
34+
:return: list of dictionaries with user information, None if error
2935
"""
30-
3136
sql = getUserQuery()
37+
firstWhereClause = True
3238
args = ()
33-
if status is not None:
34-
sql += "WHERE app.status = %s"
35-
args = args + (status,)
36-
if is_virtual is not None:
37-
sql += "AND WHERE app.is_virtual = %s"
38-
args = args + (is_virtual,)
39-
elif is_virtual is not None:
40-
sql += "WHERE app.is_virtual = %s"
39+
40+
if applicationStatusFilterList is not None:
41+
sql += f" WHERE app.status in ({','.join(['%s'] * len(applicationStatusFilterList))}) "
42+
args = args + (tuple(applicationStatusFilterList),)
43+
if is_virtual is not None:
44+
sql += getOptionalAnd(firstWhereClause) + " WHERE app.is_virtual = %s "
4145
args = args + (is_virtual,)
46+
if firstName is not None:
47+
sql += getOptionalAnd(firstWhereClause) + " WHERE u.first_name = %s "
48+
args = args + (firstName,)
49+
if lastName is not None:
50+
sql += getOptionalAnd(firstWhereClause) + " WHERE u.last_name = %s "
51+
args = args + (lastName,)
52+
if userId is not None:
53+
sql += getOptionalAnd(firstWhereClause) + " WHERE u.user_id = %s "
54+
args = args + (userId,)
55+
if email is not None:
56+
sql += getOptionalAnd(firstWhereClause) + " WHERE u.email = %s "
57+
args = args + (email,)
58+
if applicationId is not None:
59+
sql += getOptionalAnd(firstWhereClause) + " WHERE app.application_id = %s "
60+
args = args + (applicationId,)
4261

4362
return exec_get_all(sql, args)
4463

4564

65+
def getOptionalAnd(isFirstWhereClause) -> str:
66+
"""
67+
Helper function, returns "AND " if clause isn't the first and empty string if it is
68+
:param isFirstWhereClause:
69+
:return:
70+
"""
71+
if isFirstWhereClause:
72+
return ""
73+
else:
74+
return " AND "
75+
76+
4677
def getUserByAuthID(auth_id) -> dict:
4778
"""
4879
wrapper for getting user using auth0 id
@@ -94,7 +125,7 @@ def getUserById(auth_id=None, user_id=None) -> dict:
94125
if auth_id is not None:
95126
sql += "WHERE u.auth0_id = %s"
96127
args = args + (auth_id,)
97-
if user_id is not None:
128+
elif user_id is not None:
98129
sql += "WHERE u.user_id = %s"
99130
args = args + (user_id,)
100131

@@ -121,4 +152,3 @@ def getUserEmailsWithFilter(applicationStatusFilterList: List[str]):
121152
if len(u['email']) > 1:
122153
emailList.append(u['email'])
123154
return emailList
124-

api/src/db/db_utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def exec_get_one(sql, args={}) -> (dict, bool):
109109
return None, True
110110

111111

112-
def exec_get_all(sql, args={}) -> dict:
112+
def exec_get_all(sql, args={}) -> list:
113113
"""
114114
Retrieves many records from the dictionary
115115
:param sql:
@@ -118,6 +118,7 @@ def exec_get_all(sql, args={}) -> dict:
118118
"""
119119
conn = connect()
120120
if conn is None:
121+
logger.error("SQL Connection Error")
121122
return None
122123
cur = conn.cursor(dictionary=True)
123124
try:

api/src/db/migration/migration.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import db.db_utils as db_utils
44
import glob
55
import logging
6+
67
logger = logging.getLogger("Migrations")
78

89
version = None
@@ -17,18 +18,24 @@ def initializeMigrations() -> bool:
1718
global version
1819
global dirtyVersion
1920
migrationInformation = getCurrentMigration()
21+
if migrationInformation is None:
22+
# db error
23+
return False
2024
version = migrationInformation["version"]
2125
dirtyVersion = migrationInformation["dirtyVersion"]
2226
return not dirtyVersion
2327

28+
2429
def getCurrentMigration() -> dict:
2530
sql = "SELECT version, dirtyVersion FROM Migrations ORDER BY version DESC LIMIT 1;"
2631
migrationInformation, didError = db_utils.exec_get_one(sql)
2732
if migrationInformation is None or didError:
28-
logger.error("Migration Information is None")
29-
return None, True
33+
logger.error("Migration Information is None migrationInformation: %s didError: %s", migrationInformation,
34+
didError)
35+
return None
3036
return migrationInformation
3137

38+
3239
def up() -> bool:
3340
global version
3441
global dirtyVersion
@@ -38,6 +45,8 @@ def up() -> bool:
3845

3946
# get current state of migrations
4047
migrationInformation = getCurrentMigration()
48+
if migrationInformation is None:
49+
return False
4150
version = migrationInformation["version"]
4251
dirtyVersion = migrationInformation["dirtyVersion"]
4352

@@ -85,6 +94,8 @@ def down(rollbackNumber=1) -> bool:
8594

8695
# get current state of migrations
8796
migrationInformation = getCurrentMigration()
97+
if migrationInformation is None:
98+
return False
8899
version = migrationInformation["version"]
89100
dirtyVersion = migrationInformation["dirtyVersion"]
90101

api/src/server.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from controller.email import Email
1818
from controller.emailPreset import EmailPreset
1919
from controller.confirmation import Confirmation
20+
from controller.userSearch import UserSearch
2021
from db.migration import migration
2122
import logging
2223
from dotenv import load_dotenv
@@ -51,6 +52,7 @@
5152
api.add_resource(Email, Email.PATH)
5253
api.add_resource(EmailPreset, EmailPreset.PATH)
5354
api.add_resource(Confirmation, Confirmation.PATH)
55+
api.add_resource(UserSearch, UserSearch.PATH)
5456

5557
if not initializeAWSClients():
5658
logger.error("AWS Client Initialization Failure")

ui/src/pages/manage/checkin.js

Whitespace-only changes.

0 commit comments

Comments
 (0)