summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwikiapiserver2026-06-25 14:59:59 +0200
committerwikiapiserver2026-06-25 14:59:59 +0200
commit857fc8bd77e36a45b249b83419c7ba3dde2b792a (patch)
treed568befb95470aced90c6a121200871d4b6957b3
parentcc960860e4109b4eb50721d0b3338df4b859d559 (diff)
downloadwikiapiserver-857fc8bd77e36a45b249b83419c7ba3dde2b792a.tar.gz
feat: GET /token?username=... returns access_token and valid_until
Returns the stored access_token and the timestamp when it was created (access_token_created). Returns 401 for unknown users.
-rw-r--r--api/handlers.go36
-rw-r--r--db/db.go5
-rw-r--r--main.go1
3 files changed, 41 insertions, 1 deletions
diff --git a/api/handlers.go b/api/handlers.go
index f98dd6b..3b09d22 100644
--- a/api/handlers.go
+++ b/api/handlers.go
@@ -2,6 +2,8 @@ package api
import (
"context"
+ "database/sql"
+ "errors"
"encoding/json"
"log"
"net/http"
@@ -37,7 +39,11 @@ type loginReq struct {
Username string `json:"username"`
Password string `json:"password"`
}
-
+// tokenResp is returned by GET /token.
+type tokenResp struct {
+ AccessToken string `json:"access_token"`
+ ValidUntil string `json:"valid_until"`
+}
// --- helper writers ---
func writeJSON(w http.ResponseWriter, code int, v any) {
@@ -168,3 +174,31 @@ func (h *Handler) Health(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
}
+
+// --- Get Token: GET /token?username=... ---
+
+func (h *Handler) GetToken(w http.ResponseWriter, r *http.Request) {
+ ctx, cancel := context.WithTimeout(r.Context(), defaultTimeout)
+ defer cancel()
+
+ username := r.URL.Query().Get("username")
+ if username == "" {
+ badRequest(w, "username query parameter is required")
+ return
+ }
+
+ acct, err := h.db.GetAccount(ctx, username)
+ if err != nil {
+ if errors.Is(err, sql.ErrNoRows) {
+ unauthorized(w)
+ return
+ }
+ serverError(w, "could not retrieve token")
+ return
+ }
+
+ writeJSON(w, http.StatusOK, tokenResp{
+ AccessToken: acct.AccessToken,
+ ValidUntil: acct.AccessTokenExpiry.Format(time.RFC3339),
+ })
+}
diff --git a/db/db.go b/db/db.go
index 6fed1b0..228a655 100644
--- a/db/db.go
+++ b/db/db.go
@@ -315,6 +315,11 @@ func (d *DB) getAccountByUsername(ctx context.Context, username string) (*Accoun
return &acct, nil
}
+// GetAccount fetches the current tokens for a username.
+func (d *DB) GetAccount(ctx context.Context, username string) (*Account, error) {
+ return d.getAccountByUsername(ctx, username)
+}
+
// HealthCheck runs a trivial query to verify DB liveness.
func (d *DB) HealthCheck(ctx context.Context) error {
_, err := d.conn.ExecContext(ctx, "SELECT 1")
diff --git a/main.go b/main.go
index 6662d90..f2cf44d 100644
--- a/main.go
+++ b/main.go
@@ -86,6 +86,7 @@ func main() {
mux.HandleFunc("POST /login", handler.Login)
mux.HandleFunc("POST /refresh", handler.Refresh)
mux.HandleFunc("GET /health", handler.Health)
+ mux.HandleFunc("GET /token", handler.GetToken)
addr := fmt.Sprintf(":%d", cfg.Server.Port)
srv := &http.Server{