Skip to content
Draft
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
70 changes: 57 additions & 13 deletions cmd/ft_activity_api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package main

import (
"42ActivityAPI/internal/accessdb"
"42ActivityAPI/internal/checkauth"
"42ActivityAPI/internal/handlers"
"42ActivityAPI/internal/loadconfig"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"log"
"net/http"
"os"
"encoding/json"
"strings"
)

func main() {
Expand All @@ -20,6 +23,7 @@ func main() {
}

router := gin.Default()

router.LoadHTMLGlob("web/templates/*")

// CORS Settings
Expand All @@ -29,26 +33,30 @@ func main() {

router.GET("/", ShowIndexPage)
router.GET("/new", RedirectToIndexWithUID)
router.GET("/callback", ShowCallbackPage)
// router.GET("/callback", ShowCallbackPage)
router.GET("/callback", handleCallback)

router.POST("/receive-uid", handlers.HandleUIDSubmission)
authGroup := router.Group("/", checkauth.CheckAuthHeader())
{
authGroup.POST("/receive-uid", handlers.HandleUIDSubmission)

router.GET("/shifts", handlers.GetShiftData)
router.POST("/shifts", handlers.AddShiftData)
router.POST("/shifts/exchange", handlers.ExchangeShiftData)
router.DELETE("/shifts", handlers.DeleteShiftData)
authGroup.GET("/shifts", handlers.GetShiftData)
authGroup.POST("/shifts", handlers.AddShiftData)
authGroup.POST("/shifts/exchange", handlers.ExchangeShiftData)
authGroup.DELETE("/shifts", handlers.DeleteShiftData)

router.POST("/activities", handlers.AddActivity)
router.GET("/activities/cleanings", handlers.GetActivityCleanData)
authGroup.POST("/activities", handlers.AddActivity)
authGroup.GET("/activities/cleanings", handlers.GetActivityCleanData)

router.POST("/roles", handlers.AddRole)
authGroup.POST("/roles", handlers.AddRole)

router.POST("/locations", handlers.AddLocation)
authGroup.POST("/locations", handlers.AddLocation)

router.POST("/m5sticks", handlers.AddM5Stick)
authGroup.POST("/m5sticks", handlers.AddM5Stick)

router.POST("/users", handlers.AddUsers)
router.PUT("/users", handlers.EditUser)
authGroup.POST("/users", handlers.AddUsers)
authGroup.PUT("/users", handlers.EditUser)
}

router.Run(":" + os.Getenv("PORT"))
}
Expand All @@ -73,3 +81,39 @@ func RedirectToIndexWithUID(c *gin.Context) {
func ShowCallbackPage(c *gin.Context) {
c.HTML(http.StatusOK, "callback.html", nil)
}

func handleCallback(c *gin.Context) {
uid := c.Query("uid")
code := c.Query("code")
if uid == "" || code == "" {
c.HTML(http.StatusBadRequest, "response.html", gin.H{"Message": "NFCタグとログインの紐付けに失敗しました。管理者に問い合わせてください。"})
return
}
client := &http.Client{}
data := map[string]string{ "uid": uid, "code": code }
body, err := json.Marshal(data)
if err != nil {
c.HTML(http.StatusInternalServerError, "response.html", gin.H{"Message": "NFCタグとログインの紐付けに失敗しました。管理者に問い合わせてください。"})
return
}
req, err := http.NewRequest("POST", "http://localhost:4242/receive-uid", strings.NewReader(string(body)))
if err != nil {
c.HTML(http.StatusInternalServerError, "response.html", gin.H{"Message": "NFCタグとログインの紐付けに失敗しました。管理者に問い合わせてください。"})
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer " + os.Getenv("API_KEY"))
res, err := client.Do(req)
if err != nil {
c.HTML(http.StatusInternalServerError, "response.html", gin.H{"Message": "NFCタグとログインの紐付けに失敗しました。管理者に問い合わせてください。"})
return
}
defer res.Body.Close()
if res.StatusCode == 200 {
c.HTML(http.StatusOK, "response.html", gin.H{"Message": "NFCタグとログインの紐付けが完了しました。ブラウザを閉じてください。"})
} else if res.StatusCode == 409 {
c.HTML(http.StatusConflict, "response.html", gin.H{"Message": "既に登録されているログインです。ブラウザを閉じてださい。"})
} else {
c.HTML(res.StatusCode, "response.html", gin.H{"Message": "NFCタグとログインの紐付けに失敗しました。管理者に問い合わせてください。"})
}
}
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ services:
CALLBACK_URL: ${CALLBACK_URL}
SECRET: ${SECRET}
PORT: ${API_PORT}
API_KEY: ${API_KEY}
CGO_ENABLED: 1
depends_on:
mariadb:
Expand Down
25 changes: 25 additions & 0 deletions internal/checkauth/checkauthheader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package checkauth

import (
"os"
"net/http"
"github.com/gin-gonic/gin"
)
// Validate the API key by matching the environment variables and the Authorization header.
func CheckAuthHeader() gin.HandlerFunc {
return func(c *gin.Context) {
expectedAPIKey := "Bearer " + os.Getenv("API_KEY")
if expectedAPIKey == "Bearer " {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal Server Error."})
c.Abort()
return
}
apiKey := c.GetHeader("Authorization")
if apiKey != expectedAPIKey {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
c.Abort()
return
}
c.Next()
}
}
12 changes: 12 additions & 0 deletions web/templates/response.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Callback page</title>
</head>
<body>
{{ if .Message }}
<p>{{ .Message }}</p>
{{ end }}
</body>