Skip to content

Commit d6bf58d

Browse files
committed
Update README and remove some dead code
1 parent 2b71eee commit d6bf58d

File tree

3 files changed

+89
-104
lines changed

3 files changed

+89
-104
lines changed

README.md

Lines changed: 89 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,126 @@
11
# Cupcake
22

3-
A minimal server providing a read-only version of [cake](https://github.com/javaBin/cake-redux) for javaBin regions to
4-
be able to find possible speakers for local talks.
3+
A Kotlin/Ktor backend that aggregates JavaZone conference and session data from [Sleeping Pill](https://sleepingpill.javazone.no) and enriches speaker profiles with Norwegian postal code data from the Bring API. It serves as the API backend for [frosting](https://github.com/javaBin/frosting), enabling javaBin regions to discover potential speakers for local events.
54

6-
For frontend - see [frosting](https://github.com/javaBin/frosting)
5+
## Tech stack
76

8-
## Build
7+
- **Language**: Kotlin (JVM 22)
8+
- **Framework**: Ktor
9+
- **Build**: Gradle (Kotlin DSL)
10+
- **Caching**: Caffeine (conference/session data) + Cache4k (postal codes)
11+
- **Auth**: OIDC/JWT via configurable discovery endpoint
12+
- **Metrics**: Micrometer + Prometheus
913

10-
Gradle application using ktor.
14+
## API endpoints
1115

12-
## Local running
16+
| Method | Path | Description |
17+
|--------|------|-------------|
18+
| `GET` | `/api/conferences` | Lists conferences (filtered by year, sorted by name descending) |
19+
| `GET` | `/api/conferences/{id}/sessions` | Sessions for a conference, with speaker postal code/city/county data |
20+
| `GET` | `/api/me` | Authenticated user info from OIDC token |
1321

14-
You will require env variables:
22+
Additional endpoints (`/login`, `/refresh`) are handled by the OIDC layer.
1523

16-
SP_BASE_URL=https://sleepingpill.javazone.no
17-
SP_USER=<username>
18-
SP_PASSWORD=<password>
19-
BRING_API_KEY=<key>
20-
BRING_API_USER=<e-mail>
21-
OIDC_WELL_KNOWN_URL=<OIDC discovery endpoint URL, e.g. https://auth.example.com/realms/myrealm/.well-known/openid-configuration>
22-
OIDC_EXPECTED_AZP=<expected client ID - defaults to "cupcake-client">
23-
JWT_ENABLED=true/false
24+
## Build
2425

25-
The frontend OIDC authority and client ID can be overridden via `NUXT_PUBLIC_OIDC_AUTHORITY` and
26-
`NUXT_PUBLIC_OIDC_CLIENT_ID` (see [frontend README](https://github.com/javaBin/frosting/README.md)). They default to the
27-
development Keycloak realm and client, so no change is needed for local dev against that environment.
26+
```bash
27+
./gradlew clean build
28+
```
2829

29-
If you are not running with auth (`JWT_ENABLED=false`) then localhost is fine.
30+
Code quality checks (Detekt, Kotlinter, JaCoCo coverage) run as part of `check`:
3031

31-
## Local running with docker compose
32+
```bash
33+
./gradlew check
34+
```
3235

33-
You will need to provide the same environment variables as above in a file called `local.env` in the root directory.
36+
The output artifact is `build/libs/cupcake.jar` (fat JAR with all dependencies bundled).
3437

35-
Note - this file is also useful when running from Idea with the envfile plugin.
38+
## Local running
3639

37-
This file MUST NOT be committed to git (it is in .gitignore).
40+
Set the following environment variables (a `local.env` file in the root is gitignored and works well with the IntelliJ IDEA EnvFile plugin):
3841

39-
## Deploy
42+
| Variable | Description |
43+
|---|---|
44+
| `SP_BASE_URL` | Sleeping Pill base URL (e.g. `https://sleepingpill.javazone.no`) |
45+
| `SP_USER` | Sleeping Pill username |
46+
| `SP_PASSWORD` | Sleeping Pill password |
47+
| `BRING_API_KEY` | Bring API key |
48+
| `BRING_API_USER` | Bring API user (email) |
49+
| `OIDC_WELL_KNOWN_URL` | OIDC discovery endpoint (e.g. `https://auth.example.com/realms/myrealm/.well-known/openid-configuration`) |
50+
| `OIDC_EXPECTED_AZP` | Expected OIDC client ID (defaults to `cupcake-client`) |
51+
| `JWT_ENABLED` | `true` to enforce JWT authentication, `false` to disable |
4052

41-
Assuming we will build a docker container - add to [backend action](./.github/workflows/backend.yaml) when decided.
53+
Then run:
4254

43-
Currently it is setup for the frontend to proxy the backend - anything on `/api/*`
55+
```bash
56+
./gradlew run
57+
```
4458

45-
For example - let's say we setup:
59+
The server starts on port 8080. With `JWT_ENABLED=false`, no auth is required and `localhost` is fine.
4660

47-
https://cupcake_backend.javazone.no -> backend
48-
https://cupcake.javazone.no -> frontend
61+
## Docker
4962

50-
We would then need to set the host in the frontend for non development builds to `https://cupcake_backend.javazone.no` in
51-
the [proxy](https://github.com/javaBin/frosting/server/middleware/proxy.ts) file - but this is set using the CUPCAKE_BACKEND env var.
63+
Multi-platform images (`linux/amd64`, `linux/arm64`) are published to `ghcr.io/javabin/cupcake`.
5264

53-
All app configuration for the backend is done via the environment.
65+
To build locally:
5466

55-
If deploying with docker - you can place both on the same docker network and use the service name for the env var.
67+
```bash
68+
docker build -t cupcake .
69+
```
5670

57-
### JWT
71+
The image uses a multi-stage build (Eclipse Temurin JDK 22 build stage, JRE runtime stage) and runs on port 8080.
72+
73+
## CI/CD
74+
75+
| Trigger | Workflow | What it does |
76+
|---|---|---|
77+
| Push to `main` | `build.yaml` | Runs `check`, builds and pushes multi-platform Docker image, tags as `staging` |
78+
| Pull request | `pr.yaml` | Runs `check` (tests, linting, analysis) |
79+
| Tag `v*` | `release.yaml` | Promotes `staging` image to `release` and version tag |
80+
81+
## Deploy
5882

59-
JWT_ENABLED - true
83+
Example hostnames:
6084

61-
### Sleepingpill
85+
```
86+
https://cupcake-backend.java.no → backend (this service)
87+
https://cupcake.java.no → frontend (frosting)
88+
```
6289

63-
We use the same user and password for dev and deploy here but it must be set in the environment.
90+
If deploying with Docker Compose or a shared Docker network, or inside kubernetes with access, use the service name as the `CUPCAKE_BACKEND` value.
6491

65-
SP_USER
66-
SP_PASSWORD
92+
### Environment variables for deployment
6793

68-
### Bring
94+
#### JWT / OIDC (backend)
6995

70-
We use the same user and password for dev and deploy here but it must be set in the environment.
96+
| Variable | Value |
97+
|---|---|
98+
| `JWT_ENABLED` | `true` |
99+
| `OIDC_WELL_KNOWN_URL` | OIDC discovery endpoint |
100+
| `OIDC_EXPECTED_AZP` | Expected client ID (defaults to `cupcake-client`) |
71101

72-
BRING_API_USER
73-
BRING_API_KEY
102+
Users must have the `pkom` role assigned in the OIDC provider under the client specified by `OIDC_EXPECTED_AZP`.
74103

75-
### OIDC
104+
#### OIDC (frontend — must match backend)
76105

77-
This provides authentication and access checking. Users must have the `pkom` role assigned
78-
in the OIDC provider under the client specified by `OIDC_EXPECTED_AZP`.
106+
| Variable | Description |
107+
|---|---|
108+
| `NUXT_PUBLIC_OIDC_AUTHORITY` | OIDC authority URL (e.g. `https://auth.example.com/realms/myrealm`) |
109+
| `NUXT_PUBLIC_OIDC_CLIENT_ID` | OIDC client ID (defaults to `cupcake-client`) |
79110

80-
OIDC_WELL_KNOWN_URL - the OIDC discovery endpoint (e.g. https://auth.example.com/realms/myrealm/.well-known/openid-configuration)
81-
OIDC_EXPECTED_AZP - the expected client ID (defaults to "cupcake-client")
111+
See the [frosting README](https://github.com/javaBin/frosting/README.md) for full frontend configuration.
82112

83-
The backend fetches the JWKS from the discovery document and validates incoming tokens against it.
113+
#### Sleeping Pill
84114

85-
The frontend OIDC settings are configured via environment variables and must be kept in sync with
86-
the backend `OIDC_WELL_KNOWN_URL` and `OIDC_EXPECTED_AZP` settings:
115+
| Variable | Description |
116+
|---|---|
117+
| `SP_BASE_URL` | Sleeping Pill base URL |
118+
| `SP_USER` | Username |
119+
| `SP_PASSWORD` | Password |
87120

88-
NUXT_PUBLIC_OIDC_AUTHORITY - the OIDC authority URL (e.g. https://auth.example.com/realms/myrealm)
89-
NUXT_PUBLIC_OIDC_CLIENT_ID - the OIDC client ID (defaults to "cupcake-client")
121+
#### Bring
90122

123+
| Variable | Description |
124+
|---|---|
125+
| `BRING_API_USER` | Bring API user (email) |
126+
| `BRING_API_KEY` | Bring API key |

src/main/kotlin/no/java/cupcake/api/ApiError.kt

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,6 @@ data class SleepingPillCallFailed(
5353
systemName = "SleepingPill",
5454
)
5555

56-
data class SlackCallFailed(
57-
override val upstream: ErrorResponse,
58-
) : UpstreamError(
59-
upstream = upstream,
60-
systemName = "Slack",
61-
)
62-
6356
data object CallPrincipalMissing : ApiError(
6457
ErrorResponse(
6558
status = HttpStatusCode.Unauthorized,
@@ -81,15 +74,6 @@ data object TokenMissingUser : ApiError(
8174
),
8275
)
8376

84-
data class MissingChannelMembership(
85-
val channelName: String,
86-
) : ApiError(
87-
ErrorResponse(
88-
status = HttpStatusCode.Unauthorized,
89-
message = "User not in correct slack channel - please ask in #kodesmia for access to $channelName",
90-
),
91-
)
92-
9377
data object RefreshTokenInvalid : ApiError(
9478
ErrorResponse(
9579
status = HttpStatusCode.Unauthorized,

src/main/kotlin/no/java/cupcake/clients/SlackClient.kt

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)