Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,17 @@ JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
JWT_ACCESS_TOKEN_EXPIRY=3600
JWT_REFRESH_TOKEN_EXPIRY=604800

# SMTP Configuration (Gmail example)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-specific-password
FROM_EMAIL=noreply@school.com
FROM_NAME=School API

# Email URLs
RESET_PASSWORD_URL=https://school.com/reset-password
VERIFY_EMAIL_URL=https://school.com/verify-email

# Logging
RUST_LOG=info
250 changes: 250 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions migrations/002_create_otp_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- Create OTP records table
CREATE TABLE IF NOT EXISTS otp_records (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
otp_code VARCHAR(6) NOT NULL,
otp_type VARCHAR(50) NOT NULL, -- 'login', 'password_reset', 'email_verification'
is_used BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
CONSTRAINT valid_otp_type CHECK (otp_type IN ('login', 'password_reset', 'email_verification'))
);

-- Create indexes for faster queries
CREATE INDEX idx_otp_user_id ON otp_records(user_id);
CREATE INDEX idx_otp_type ON otp_records(otp_type);
CREATE INDEX idx_otp_expires_at ON otp_records(expires_at);
CREATE INDEX idx_otp_user_type ON otp_records(user_id, otp_type);
Loading
Loading