Skip to content

Commit 2dd0d0c

Browse files
committed
feat: add post request validation
1 parent eed0bf1 commit 2dd0d0c

File tree

3 files changed

+136
-91
lines changed

3 files changed

+136
-91
lines changed

app.py

Lines changed: 78 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
from models import Education, Experience, Skill
1010

11+
from helper import validate_fields
12+
1113

1214
app = Flask(__name__)
1315

@@ -65,9 +67,9 @@ def experience():
6567
"description",
6668
"logo",
6769
]
68-
# Validating User Input
69-
if not all(field in user_input for field in required_fields):
70-
return jsonify({"error": "Missing required fields"}), 400
70+
is_valid, missing = validate_fields(user_input, required_fields)
71+
if not is_valid:
72+
return jsonify({"error": f"Missing required field: {missing}"}), 400
7173

7274
# Create a new Experience instance
7375
# Using the length of the of the experience list and the index of the new experience
@@ -81,7 +83,6 @@ def experience():
8183
if request.method == "POST":
8284
return jsonify({})
8385

84-
8586
return jsonify({})
8687

8788

@@ -99,122 +100,114 @@ def get_single_experience(pk):
99100
return jsonify({})
100101

101102

102-
103103
@app.route("/resume/education", methods=["GET", "POST"])
104104
def education():
105105
"""
106106
Handles education requests
107107
"""
108108
if request.method == "GET":
109-
return jsonify({})
110-
111-
if request.method == "POST":
112-
return jsonify({})
113-
114-
115-
if request.method == 'GET':
116109
existing_education_records = data["education"]
117-
return jsonify(
118-
{
119-
"message": "list of education records returned successfully",
120-
"data": existing_education_records,
121-
}
122-
), 200
123-
124-
110+
return (
111+
jsonify(
112+
{
113+
"message": "list of education records returned successfully",
114+
"data": existing_education_records,
115+
}
116+
),
117+
200,
118+
)
125119

126120
if request.method == "POST":
127-
128121
body = request.get_json()
129-
payload = {
130-
"course": body.get("course"),
131-
"school": body.get("school"),
132-
"start_date": body.get("start_date"),
133-
"end_date": body.get("end_date"),
134-
"grade": body.get("grade"),
135-
"logo": body.get("logo"),
136-
}
137-
138-
for key, value in payload.items():
139-
if value is None:
140-
message = f"{key} must not be empty"
141-
return jsonify(
142-
{
143-
"message": message,
144-
}
145-
), 400
122+
required_fields = [
123+
"course",
124+
"school",
125+
"start_date",
126+
"end_date",
127+
"grade",
128+
"logo",
129+
]
130+
is_valid, missing = validate_fields(body, required_fields)
131+
if not is_valid:
132+
return (
133+
jsonify({"message": f"{missing} must not be empty"}),
134+
400,
135+
)
146136

147137
new_record = Education(
148-
payload[ "course" ],
149-
payload["school"],
150-
payload["start_date"],
151-
payload["end_date"],
152-
payload["grade"],
153-
payload["logo"],
138+
body["course"],
139+
body["school"],
140+
body["start_date"],
141+
body["end_date"],
142+
body["grade"],
143+
body["logo"],
154144
)
155145

156146
existing_education_records = data["education"]
157147
length_of_exisiting_records = len(existing_education_records)
158148
existing_education_records.append(new_record)
159149

160-
return jsonify(
161-
{
162-
"message": "education added successfully",
163-
"data": length_of_exisiting_records,
164-
}
165-
),201
150+
return (
151+
jsonify(
152+
{
153+
"message": "education added successfully",
154+
"data": length_of_exisiting_records,
155+
}
156+
),
157+
201,
158+
)
166159

167-
168160
return jsonify({})
169161

170162

171163
@app.route("/resume/education/<int:education_id>", methods=["GET"])
172164
def get_education(education_id):
173-
'''
174-
Handles retrieving specific education
175-
'''
165+
"""
166+
Handles retrieving specific education
167+
"""
176168
existing_education_records = data["education"]
177-
if education_id > len(existing_education_records) - 1 :
178-
return jsonify(
169+
if education_id > len(existing_education_records) - 1:
170+
return (
171+
jsonify(
172+
{
173+
"message": "education does not exist",
174+
}
175+
),
176+
404,
177+
)
178+
179+
record = existing_education_records[education_id]
180+
return (
181+
jsonify(
179182
{
180-
"message": "education does not exist",
183+
"message": "education record returned successfully",
184+
"data": record,
181185
}
182-
), 404
183-
184-
record = existing_education_records[education_id]
185-
return jsonify(
186-
{
187-
"message": "education record returned successfully",
188-
"data": record,
189-
}
190-
), 200
191-
186+
),
187+
200,
188+
)
192189

193190

194191
@app.route("/resume/skill", methods=["POST"])
195192
def skill():
196-
json_data = request.json
197-
try:
198-
name = json_data["name"]
199-
proficiency = json_data["proficiency"]
200-
logo = json_data["logo"]
201-
202-
new_skill = Skill(name, proficiency, logo)
193+
json_data = request.get_json()
194+
required_fields = ["name", "proficiency", "logo"]
195+
is_valid, missing = validate_fields(json_data, required_fields)
196+
if not is_valid:
197+
return jsonify({"error": f"Missing required field: {missing}"}), 400
203198

199+
try:
200+
new_skill = Skill(
201+
json_data["name"], json_data["proficiency"], json_data["logo"]
202+
)
203+
data["skill"].append(new_skill)
204+
return jsonify({"id": len(data["skill"]) - 1}), 201
204205

205-
data["skill"].append(new_skill)
206-
207-
return jsonify(
208-
{"id": len(data["skill"]) - 1}
209-
), 201
206+
except Exception as e:
207+
return jsonify({"error": str(e)}), 400
210208

211-
except KeyError:
212-
return jsonify({"error": "Invalid request"}), 400
213209

214-
except TypeError as e:
215-
return jsonify({"error": str(e)}), 400
216-
217-
@app.route('/resume/skill/<int:skill_id>', methods=['GET'])
210+
@app.route("/resume/skill/<int:skill_id>", methods=["GET"])
218211
def get_skill(skill_id):
219212
try:
220213
skill = data["skill"][skill_id]

helper.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
def validate_fields(json_data, required_fields):
2+
"""
3+
Validates that all required fields are present in the json_data.
4+
Returns (True, None) if valid, (False, missing_field) if not.
5+
"""
6+
for field in required_fields:
7+
if field not in json_data or json_data[field] is None:
8+
return False, field
9+
return True, None

test_pytest.py

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ def test_experience():
3434
app.test_client()
3535
.post("/resume/experience", json=example_experience)
3636
.json["index"]
37-
3837
)
3938
response = app.test_client().get("/resume/experience")
4039
assert response.json[item_id] == example_experience
@@ -72,7 +71,6 @@ def test_skill():
7271
"name": "JavaScript",
7372
"proficiency": "2-4 years",
7473
"logo": "example-logo.png",
75-
7674
}
7775

7876
item_id = app.test_client().post("/resume/skill", json=example_skill).json["id"]
@@ -85,15 +83,60 @@ def test_get_skill_by_id():
8583
example_skill = {
8684
"name": "Blowing Bubbles an Fighting Crime",
8785
"proficiency": "5+ years",
88-
"logo": "some-logo.png"
89-
86+
"logo": "some-logo.png",
9087
}
9188

9289
item_id = app.test_client().post("/resume/skill", json=example_skill).json["id"]
9390

94-
95-
response = app.test_client().get(f'/resume/skill/{item_id}')
91+
response = app.test_client().get(f"/resume/skill/{item_id}")
9692
data = response.json
9793

9894
assert response.status_code == 200
9995
assert data == example_skill
96+
97+
98+
def test_experience_missing_fields():
99+
'''
100+
Test POST /resume/experience with missing required fields
101+
'''
102+
incomplete_experience = {
103+
"title": "Software Developer",
104+
"start_date": "October 2022",
105+
"end_date": "Present",
106+
"description": "Writing Python Code"
107+
# missing 'company' and 'logo'
108+
}
109+
response = app.test_client().post('/resume/experience', json=incomplete_experience)
110+
assert response.status_code == 400
111+
assert "Missing fields" in response.json["error"]
112+
113+
114+
def test_education_missing_fields():
115+
'''
116+
Test POST /resume/education with missing required fields
117+
'''
118+
incomplete_education = {
119+
"degree": "Engineering",
120+
"start_date": "October 2022",
121+
"end_date": "August 2024",
122+
"grade": "86%",
123+
"logo": "example-logo.png"
124+
# missing 'school'
125+
}
126+
response = app.test_client().post('/resume/education', json=incomplete_education)
127+
assert response.status_code == 400
128+
assert "Missing fields" in response.json["error"]
129+
130+
131+
def test_skill_missing_fields():
132+
'''
133+
Test POST /resume/skill with missing required fields
134+
'''
135+
incomplete_skill = {
136+
"name": "JavaScript",
137+
"proficiency": "2-4 years"
138+
# missing 'logo'
139+
}
140+
response = app.test_client().post('/resume/skill', json=incomplete_skill)
141+
assert response.status_code == 400
142+
assert "Missing fields" in response.json["error"]

0 commit comments

Comments
 (0)