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
66 changes: 20 additions & 46 deletions docs/api-testing.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,46 @@
# Testing the API

Once the api is running (via `air` or running it manually), you can use `xh` or `curl` to test the api from the command line. You probably already have `curl` installed, but `xh` is provided in the dev shell.
We recommend using `xh` as it is the more modern option.
If you prefer to use a GUI instead, Postman is a popular option.
Once the api is running (via `air` or running it manually), you can use `xh` or `curl` to test the api from the command line. We recommend using `xh` over `curl`, and it's provided in the dev shell.
If you prefer to use a GUI, Postman is a popular option.

## Using Swagger Documentation
## Using OpenAPI/Swagger Documentation

The API includes comprehensive Swagger documentation that provides an interactive interface for exploring and testing endpoints. When the server is running, you can access the Swagger UI at:
The API includes comprehensive OpenAPI2 (Swagger) documentation that provides an interactive interface for exploring and testing endpoints. When the server is running, you can access the Swagger UI at:

```
http://localhost:8080/swagger
http://localhost:8080/docs
```

The Swagger documentation includes:
- Complete API endpoint documentation for all available routes
- Interactive forms to test API calls directly from the browser
- Request/response schemas and examples
- Parameter descriptions and validation rules

This is often the easiest way to explore the API and understand what endpoints are available without needing to dive into the source code. You can also use it to make test requests without needing to construct `curl` or `xh` commands manually.

## Using `xh` and `curl`
Comment thread
GaballaGit marked this conversation as resolved.
These examples use `xh`, but you can get the equivalent `curl` command by appending the `--curl` flag to any example command.

### Sending a GET request
The following requests will request an event called "event1" from the APIs `events` endpoint. You'll probably have to create this event yourself if you want to use this exact command (see the POST section below).
```sh
# assuming the server is running on localhost:8080
xh :8080/v1/events/event1

# or with curl:
curl localhost:8080/v1/events/event1
```
Both `xh` and `curl` send a GET request by default, so you don't need to specify which method to use.
Note: `curl` won't give you formatted output by default, so it might be helpful to pipe to `jq` (also provided in dev shell) to make it look pretty.
### Sending a POST request
This creates a resource in the database that we can later query for with a GET request.
The OAuth2 middleware expects a `dev-token` passed with the Authorization middleware while in dev mode. See `oauth-authenticaion.md` for details.
```sh
curl localhost:8080/v1/events/event1 | jq
xh post :8080/v1/board/officers -A bearer -a dev-token \
full_name="Bob" \
picture="example.com/picture.webp" \
discord="discord.com/users/bob" \
github="github.com/bob" \
uuid="123"
```


### Sending a POST request
### Sending a GET request
This queries the database for the resource we just created:
```sh
xh POST :8080/v1/events \
uuid="event1" \
location="tsu" \
start_at="1712851200000" \
end_at="1712851200000" \
is_all_day:=false \
host="ACM"

# same thing with curl:
curl -X POST localhost:8080/v1/events \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-d '{"uuid":"event1","location":"tsu","start_at":"1712851200000","end_at":"1712851200000","is_all_day":false,"host":"ACM"}'
xh :8080/v1/board/officers/123
```

As you can see, `xh` provides a more concise way to do the same thing.
There are lots of other routes, check out the OpenAPI docs for more info.

### Using fixtures
In the `fixtures` directory of this project, there's some JSON payloads that we can use for testing so we don't have to write them out each time. Feel free to create any that might be useful to yourself and/or the team.

Here's an example using one to send a POST request:
```sh
xh POST :8080/v1/events @fixtures/event.json

# same thing with curl:
curl -X POST localhost:8080/v1/events \
-H "Content-Type: application/json" \
-d @payload.json
xh post :8080/v1/events -A -a dev-token @fixtures/event_create.json
```

53 changes: 12 additions & 41 deletions docs/oauth-authentication.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# OAuth Authentication

The ACM CSUF API uses Discord OAuth2 for authentication and authorization. This ensures that only authorized Discord server members with appropriate roles can access protected API endpoints.

## Overview

The API implements a role-based access control (RBAC) system that:
Expand All @@ -14,7 +12,7 @@ The API implements a role-based access control (RBAC) system that:

### Server-Side: API Middleware

The API uses Discord OAuth2 middleware defined in [`internal/api/middleware/oauth.go`](../internal/api/middleware/oauth.go) to protect all `/v1` routes.
The API uses Discord OAuth2 middleware defined in [`internal/api/middleware/oauth.go`](../internal/api/middleware/oauth.go) to protect state-changing `/v1` routes.

**How it works:**

Expand Down Expand Up @@ -60,21 +58,21 @@ The CLI client (defined in [`utils/requests/request_with_auth.go`](../utils/requ
└────┬────┘ └──────┬──────┘
│ │
│ 1. Start local callback server │
│ on random port (e.g., :61234) │
│ on hardcoded port (:61234)
│ │
│ 2. Open browser with OAuth URL │
├──────────────────────────────────────────> │
│ https://discord.com/oauth2/authorize │
│ ?client_id=... │
│ &redirect_uri=http://localhost:54321
│ &redirect_uri=http://localhost:61234
│ &scope=identify │
│ &response_type=code │
│ │
│ User approves in browser │
│ │
│ 3. Discord redirects to callback │
│ <────────────────────────────────────────── │
│ http://localhost:54321/?code=... │
│ http://localhost:61234/?code=... │
│ │
│ 4. Exchange code for token │
├──────────────────────────────────────────> │
Expand Down Expand Up @@ -108,23 +106,7 @@ See [`developer-docs/env-vars.md`](./env-vars.md) for the complete list, but OAu

## Development Mode

During development (`ENV=development`), authentication is bypassed:

**API Server:**
```go
// Any request with this header will bypass OAuth
Authorization: Bearer dev-token
```

**CLI Client:**
```go
// Automatically uses dev-token when ENV=development
// No OAuth flow occurs, no tokens are exchanged
```

To test the actual OAuth flow during development, temporarily set `ENV=production` in your `.env` file.

## Testing with OAuth
During development (`ENV=development`), authentication is bypassed by supplying `dev-token` to the `Authorization header`. The CLI will do this automatically.

### Using the CLI

Expand All @@ -141,20 +123,17 @@ The CLI handles OAuth automatically:

### Using curl/xh with OAuth

If testing manually with `curl` or `xh`, you need a valid Discord access token:

You need to manually pass the token when using a standard http client:
```bash
# Development mode (no real auth needed)
xh :8080/v1/events Authorization:"Bearer dev-token"

# Production mode (need real Discord token)
xh :8080/v1/events Authorization:"Bearer <discord_access_token>"
xh post :8080/v1/events --auth-type bearer --auth dev-token
# Or with short flags:
xh post :8080/v1/events -A bearer -a dev-token
# Or defining the header manually:
xh :8080/v1/events Authorization:'Bearer dev-token'
```

To get a real Discord access token for testing:
1. Run the CLI once to complete the OAuth flow
2. Extract the token from `~/.config/acmcsuf-cli/token.json`
3. Use that token in your curl/xh commands
To get a real Discord access token for testing, run the OAuth flow with the CLI and extract the token from `~/.config/acmcsuf-cli/token.json`

### Token Expiry

Expand All @@ -163,14 +142,6 @@ Discord access tokens expire after a period (typically 1 week). When a token exp
**CLI**: The OAuth flow automatically re-runs on the next command
**Manual testing**: You'll receive a `401 Unauthorized` response and need a new token

## Security Considerations

1. **Never commit tokens**: Token files (`~/.config/acmcsuf-cli/token.json`) contain sensitive credentials
2. **HTTPS in production**: The API should only run behind HTTPS in production to protect tokens in transit
3. **Client secrets**: Keep `DISCORD_CLIENT_SECRET` secure and never commit to git
4. **Rate limiting**: The middleware caches role information for 5 minutes to respect Discord's rate limits
5. **Token storage**: CLI tokens are stored with `0600` permissions (read/write for owner only)

## Role Configuration

To add or modify roles, edit the `RoleMap` in [`internal/api/middleware/oauth.go`](../internal/api/middleware/oauth.go):
Expand Down
21 changes: 11 additions & 10 deletions docs/project-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
This document provides an overview of the project's directory structure and the responsibility of each main package.

- `cmd/`: Main applications for the project.
- `acmcsuf-api/`: The main entry point for the API server. It handles command-line flags and graceful shutdown.
- `acmcsuf-cli/`: A command-line interface for interacting with the API.
- `acmcsuf-api/`: The main entry point for the API server. It handles command-line flags and graceful shutdown.
- `acmcsuf-cli/`: A command-line interface for interacting with the API.
- `internal/`: Private application and library code.
- `api/`: Contains all the API server logic.
- `handlers/`: Gin handlers for processing HTTP requests.
- `routes/`: API route definitions.
- `services/`: Business logic for the API.
- `cli/`: Logic for the CLI application.
- `db/`: Database-related code, including schema, queries, and models.
- `developer-docs/`: Documentation for developers.
- `docs/`: Swagger/OpenAPI documentation.
- `api/`: Contains all the API server logic.
- `server.go`: Initializes and starts server.
- `routes/`: API route definitions.
- `handlers/`: Gin handlers for processing HTTP requests.
- `services/`: Business logic for the API.
- `middleware/`: Contains middleware like the rate limiter and OAuth implementation.
- `dbmodels/`: sqlc generated database models. Do not edit manually.
- `config/`: Loads environment vars and defines defaults.
- `cli/`: Logic for the CLI application.
- `fixtures/`: JSON payloads for testing.
- `nix/`: Nix dev shell and package definitions.
- `utils/`: Shared utility functions.
6 changes: 2 additions & 4 deletions internal/api/handlers/swagger.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package handlers

import (
docs "github.com/acmcsufoss/api.acmcsuf.com/internal/api/docs"
"github.com/acmcsufoss/api.acmcsuf.com/utils"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"

"github.com/acmcsufoss/api.acmcsuf.com/internal/api/docs"
)

func NewSwaggerHandler() gin.HandlerFunc {
docs.SwaggerInfo.Title = "ACM CSUF API"
docs.SwaggerInfo.Version = "1.0"
docs.SwaggerInfo.Host = "localhost:8080"
docs.SwaggerInfo.Schemes = []string{"http", "https"}
docs.SwaggerInfo.Description = utils.SwaggerDescription
return ginSwagger.WrapHandler(swaggerFiles.Handler)
}
111 changes: 0 additions & 111 deletions utils/api_description.md

This file was deleted.

6 changes: 0 additions & 6 deletions utils/swagger_helper.go

This file was deleted.