Input Validation
Relevant source files
The following files were used as context for generating this wiki page:
Input validation is a critical security and data integrity measure within the Smart Absen application. It ensures that all data submitted by users, whether through web forms or API endpoints, is correct, properly formatted, and safe before being processed or stored in the database. This prevents common vulnerabilities such as SQL injection, Cross-Site Scripting (XSS), and protects against invalid data corrupting the system's state.
The project employs a multi-layered validation strategy, combining client-side checks for immediate user feedback with robust server-side validation for security. This approach includes:
- Client-Side Validation: Using standard HTML5 attributes and custom JavaScript to guide users and catch errors in the browser.
- Server-Side Validation: Using Python decorators in
validators.pyto protect API endpoints and business logic. - API Schema Definition: Using an
openapi.yamlspecification to formally define data contracts for API consumers.
Sources: SECURITY.md, templates/add_employee_form.html, validators.py
Client-Side Validation
Client-side validation is primarily implemented in the application's HTML forms to provide a responsive user experience. It catches basic input errors before a request is ever sent to the server. This is handled through a combination of HTML5 form attributes and custom JavaScript logic.
Sources: templates/add_employee_form.html
HTML5 Form Attributes
The "Add Employee" form (add_employee_form.html) uses standard HTML5 attributes to enforce basic validation rules directly in the markup. This allows the browser to perform checks automatically.
The diagram below shows the flow of how HTML5 validation works on the Add Employee form.
Key attributes used in the employee form are summarized below:
| Field | Attribute | Rule | Source File |
|---|---|---|---|
| Nama Lengkap | required | Field must not be empty. | templates/add_employee_form.html:616 |
| NIK | required, maxlength="16" | Field must not be empty and must have a maximum length of 16 characters. | templates/add_employee_form.html:624 |
required, type="email" | Field must not be empty and must be a valid email format. | templates/add_employee_form.html:659 | |
| Tanggal Lahir | required, type="date", max | Field must be a valid date and not in the future (set by JS). | templates/add_employee_form.html:645, templates/add_employee_form.html:813-815 |
| Tanggal Bergabung | required, type="date", max | Field must be a valid date and not after today (set by JS). | templates/add_employee_form.html:716, templates/add_employee_form.html:810 |
JavaScript Custom Validation
For more complex rules that HTML5 cannot handle alone, custom JavaScript is used. In add_employee_form.html, a submit event listener intercepts the form submission to perform additional checks after the browser's built-in validation passes.
The following sequence diagram illustrates the client-side validation process, including both HTML5 and JavaScript checks.
The custom validation rules are:
- NIK Validation: Checks if the NIK consists of exactly 16 digits using the regex
/^\d{16}$/. - Phone Number Validation: Ensures the phone number starts with
0and has at least 10 digits using the regex/^0\d{9,}$/.
// templates/add_employee_form.html:838-849
// Custom validation
const nik = document.getElementById('nik').value;
const phone = document.getElementById('phone').value;
// NIK validation (16 digit)
if (!/^\d{16}$/.test(nik)) {
showAlert('NIK harus 16 digit', 'danger');
return;
}
// Phone validation
if (!/^0\d{9,}$/.test(phone)) {
showAlert('Nomor telepon harus dimulai dengan 0 dan minimal 10 digit', 'danger');
return;
}
Server-Side Validation
Server-side validation is the most critical layer of defense, as it cannot be bypassed by a malicious user. In this project, it is implemented using Python decorators defined in validators.py. These decorators are applied to Flask routes in app.py to validate incoming request data before it reaches the main logic of the endpoint.
Sources: SECURITY.md, validators.py
Decorator-Based Architecture
The system uses a decorator-based approach to keep validation logic separate from the business logic of the API endpoints. This makes the code cleaner and easier to maintain.
The general flow for a request to a protected endpoint is as follows:
This diagram illustrates the decorator chain for adding a new employee.
Sources: SECURITY.md
Core Validators
The SECURITY.md file outlines the key validators created for the system.
| Validator | Description | Source File |
|---|---|---|
@validate_json | Ensures the incoming request has the Content-Type: application/json header. | SECURITY.md |
@validate_employee_data | Validates the fields required for adding or updating an employee (e.g., name, NIK format). | SECURITY.md |
@validate_attendance_data | Validates the data submitted for marking attendance (e.g., mode, image data). | SECURITY.md |
An example from SECURITY.md shows how these decorators are applied to a Flask route:
# Inferred from SECURITY.md
from validators import validate_employee_data, validate_json
@app.route('/api/employees', methods=['POST'])
@validate_json
@validate_employee_data
def add_employee():
data = request.get_json()
# Data is already validated here
# ...
Sources: SECURITY.md
API Schema Validation
The static/openapi.yaml file provides a formal specification for the API, acting as a contract for data validation. It defines the expected data types, formats, and required fields for each endpoint. While not an active validation mechanism itself, it is a crucial part of the validation strategy for documentation and for generating client-side code or setting up API gateway validation.
Sources: static/openapi.yaml
Example: Mobile Attendance Endpoint
The /mark_attendance_mobile endpoint is defined with specific constraints on its request body.
| Parameter | Type | Description | Required |
|---|---|---|---|
mode | string (enum) | The attendance mode. Must be either masuk or pulang. | Yes |
image_data | string | Base64 encoded image of the user's face. | Yes |
device_id | string | A unique identifier for the mobile device. | Yes |
Sources: static/openapi.yaml:168-185
Here is the corresponding snippet from the OpenAPI specification:
# static/openapi.yaml:168-185
/mark_attendance_mobile:
post:
tags:
- Attendance
summary: Mark attendance from mobile
description: Submit absensi dari HP dengan capture foto wajah
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
mode:
type: string
enum: [masuk, pulang]
image_data:
type: string
description: Base64 encoded image
device_id:
type: string
Conclusion
The Smart Absen application implements a robust, multi-layered input validation strategy. It combines immediate client-side feedback using HTML5 and JavaScript with secure, non-bypassable server-side validation through Python decorators. This is further supported by a clear API contract defined in openapi.yaml. This comprehensive approach ensures high data integrity, enhances security by mitigating common web vulnerabilities, and provides a good user experience by catching errors early.
Sources: SECURITY.md, templates/add_employee_form.html, validators.py