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
125 changes: 124 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,126 @@
/target
.kiro
.env

### dotenv ###
.env

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test
.env.production

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

# End of https://mrkandreev.name/snippets/gitignore-generator/#Node
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ sudo -u postgres psql -d school_db -f migrations/001_init.sql
### 4. Configure Environment

The `.env` file is already configured with:

```
DATABASE_URL=postgres://postgres:postgres@localhost:5432/school_db
```
Expand All @@ -68,6 +69,7 @@ cargo run
The server will start on `http://localhost:3000`

You should see output like:

```
INFO school_backend: Database migrations completed successfully
INFO school_backend: Server running on http://127.0.0.1:3000
Expand All @@ -86,9 +88,10 @@ cargo build --release

Once the server is running, access the interactive API documentation at:

**http://localhost:3000/docs**
**http://localhost:3000/swagger-ui/**

The Swagger UI provides:

- Complete API endpoint documentation
- Interactive "Try it out" functionality
- Request/response schemas with examples
Expand All @@ -104,11 +107,13 @@ The raw OpenAPI 3.0 specification is available at:
## API Endpoints

### Health Check

- `GET /health` - Check API health status

### Authentication

**Public Endpoints:**

- `POST /auth/admin/register` - Register new admin user
- `POST /auth/admin/login` - Admin login
- `POST /auth/student/register` - Register new student user
Expand All @@ -118,18 +123,21 @@ The raw OpenAPI 3.0 specification is available at:
- `POST /auth/refresh` - Refresh access token

**Protected Endpoints:**

- `POST /auth/logout` - Logout (requires authentication)
- `GET /auth/me` - Get current user profile
- `POST /auth/verify` - Verify token validity

### Admin Operations (Requires Admin Role)

- `GET /admin/dashboard` - Get admin dashboard
- `GET /admin/users` - List all users
- `GET /admin/statistics` - Get user statistics
- `POST /admin/users/{user_id}/activate` - Activate user account
- `POST /admin/users/{user_id}/deactivate` - Deactivate user account

### School Management (Requires Admin Role)

- `GET /admin/schools` - List all schools
- `POST /admin/schools/create` - Create new school
- `GET /admin/schools/{school_id}` - Get school details
Expand All @@ -138,6 +146,7 @@ The raw OpenAPI 3.0 specification is available at:
- `GET /admin/schools/{school_id}/statistics` - Get school statistics

### Student Operations (Requires Student Role)

- `GET /student/dashboard` - Get student dashboard
- `GET /student/profile` - Get student profile
- `GET /student/courses` - Get enrolled courses
Expand All @@ -146,6 +155,7 @@ The raw OpenAPI 3.0 specification is available at:
- `POST /student/messages/mentor` - Send message to mentor

### Mentor Operations (Requires Mentor Role)

- `GET /mentor/dashboard` - Get mentor dashboard
- `GET /mentor/profile` - Get mentor profile
- `GET /mentor/students` - Get assigned students
Expand All @@ -162,13 +172,15 @@ The API uses JWT (JSON Web Tokens) for authentication.
### Getting a Token

1. Register or login using the appropriate endpoint:

```bash
curl -X POST http://localhost:3000/auth/admin/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@school.com","password":"your_password"}'
```

2. The response will include an `access_token`:

```json
{
"user": {...},
Expand Down Expand Up @@ -198,6 +210,7 @@ curl -X GET http://localhost:3000/admin/dashboard \
## Database Schema

### Users Table

- `id` - UUID primary key
- `email` - VARCHAR, required, unique
- `password_hash` - VARCHAR, required
Expand All @@ -209,18 +222,21 @@ curl -X GET http://localhost:3000/admin/dashboard \
- `updated_at` - TIMESTAMP

### Schools Table (Placeholder)

- `id` - UUID primary key
- `name` - VARCHAR, required
- `location` - VARCHAR
- `principal` - VARCHAR

### Students Table (Placeholder)

- `id` - UUID primary key
- `user_id` - Foreign key to users table
- `school_id` - Foreign key to schools table
- `enrollment_date` - VARCHAR

### Mentors Table (Placeholder)

- `id` - UUID primary key
- `user_id` - Foreign key to users table
- `school_id` - Foreign key to schools table
Expand All @@ -239,6 +255,7 @@ All error responses follow a standardized format:
```

Common HTTP status codes:

- `200 OK` - Successful GET, PUT, DELETE
- `201 Created` - Successful POST
- `400 Bad Request` - Invalid request data
Expand All @@ -253,21 +270,23 @@ Common HTTP status codes:
### Database Connection Issues

If you see "password authentication failed", ensure:

1. PostgreSQL is running: `sudo systemctl status postgresql`
2. Password is set correctly: `sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'postgres';"`
3. `.env` file has the correct DATABASE_URL

### Port Already in Use

If port 3000 is already in use, you can change it in `src/main.rs`:

```rust
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await?; // Change 3000 to your preferred port
```

### Swagger UI Not Loading

1. Ensure the server is running on port 3000
2. Navigate to `http://localhost:3000/docs` (not `/swagger`)
2. Navigate to `http://localhost:3000/swagger-ui/`
3. Check server logs for any errors
4. Verify the OpenAPI spec is accessible at `http://localhost:3000/api-docs/openapi.json`

Expand All @@ -279,7 +298,7 @@ You may see false errors from rust-analyzer about "struct is not supported in tr

- **API Documentation**: See [SWAGGER_INTEGRATION.md](SWAGGER_INTEGRATION.md) for detailed information about the Swagger/OpenAPI integration
- **Authentication**: See [AUTH_DOCUMENTATION.md](AUTH_DOCUMENTATION.md) for authentication details
- **Interactive API Docs**: http://localhost:3000/docs (when server is running)
- **Interactive API Docs**: http://localhost:3000/swagger-ui/ (when server is running)

## Technology Stack

Expand Down
15 changes: 5 additions & 10 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,10 @@ pub fn build_app(pool: PgPool) -> Router {
.merge(admin_protected)
.merge(student_mentor_protected)
// Swagger UI
.merge({
let mut openapi = ApiDoc::openapi();
let base_url = std::env::var("BASE_URL")
.unwrap_or_else(|_| "http://localhost:3000".to_string());
openapi.servers = Some(vec![
utoipa::openapi::ServerBuilder::new().url(base_url).build()
]);
SwaggerUi::new("/docs").url("/api-docs/openapi.json", openapi)
})
.merge(
SwaggerUi::new("/swagger-ui")
.url("/api-docs/openapi.json", ApiDoc::openapi()),
)
// CORS
.layer(CorsLayer::permissive())
}
}
3 changes: 3 additions & 0 deletions src/controllers/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,6 @@ pub async fn reject_application(

Ok(application)
}



2 changes: 1 addition & 1 deletion src/controllers/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub async fn login_user(
})
}

/// Verify a refresh token and generate a new access token.
/// Verify a refresh token and generate a new access token.6
pub async fn refresh_access_token(
pool: &PgPool,
refresh_token_str: &str,
Expand Down
3 changes: 3 additions & 0 deletions src/models/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub struct ApplicationResponse {
pub created_at: DateTime<Utc>,
}


impl From<Application> for ApplicationResponse {
fn from(a: Application) -> Self {
ApplicationResponse {
Expand All @@ -83,3 +84,5 @@ impl From<Application> for ApplicationResponse {
}
}
}


Loading