go 44 lines · 6 steps

Building a protected admin area in Gin

A single route group applies Basic Auth once, then hangs a dashboard and user-management handlers off it.

Explained by highlit
1package admin
2 
3import (
4 "net/http"
5 
6 "github.com/gin-gonic/gin"
7)
8 
9func RegisterRoutes(r *gin.Engine, deps *Dependencies) {
10 admin := r.Group("/admin")
11 admin.Use(gin.BasicAuth(gin.Accounts{
12 deps.Config.AdminUser: deps.Config.AdminPassword,
13 }))
14 
15 admin.GET("/", func(c *gin.Context) {
16 c.HTML(http.StatusOK, "admin/dashboard.tmpl", gin.H{
17 "user": c.MustGet(gin.AuthUserKey).(string),
18 "stats": deps.Metrics.Snapshot(),
19 })
20 })
21 
22 admin.GET("/users", func(c *gin.Context) {
23 users, err := deps.Users.List(c.Request.Context())
24 if err != nil {
25 c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to load users"})
26 return
27 }
28 c.JSON(http.StatusOK, users)
29 })
30 
31 admin.POST("/users/:id/ban", func(c *gin.Context) {
32 id := c.Param("id")
33 if err := deps.Users.Ban(c.Request.Context(), id); err != nil {
34 c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{"error": err.Error()})
35 return
36 }
37 c.JSON(http.StatusOK, gin.H{"banned": id})
38 })
39 
40 admin.DELETE("/cache", func(c *gin.Context) {
41 deps.Cache.Flush()
42 c.Status(http.StatusNoContent)
43 })
44}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Grouping routes lets you attach shared middleware like auth once instead of per-handler.
  2. 2Passing a dependencies struct keeps handlers testable and decoupled from global state.
  3. 3Aborting with a status on error keeps failures explicit and stops the handler chain cleanly.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building a protected admin area in Gin — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code