-
Notifications
You must be signed in to change notification settings - Fork 99
feat: add api to invalid request in diff b/w server & req time #173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c4408fd
d3049f6
66380cb
416bf06
15171d1
876f60b
2b8a3e0
b9b9a66
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -1,18 +1,19 @@ | ||||
| // Package main is the entry point for the JWT-based user authentication service | ||||
| // using Gin framework and PostgreSQL database. It provides endpoints for | ||||
| // health check, token generation, and token validation. | ||||
| package main | ||||
|
Check warning on line 1 in go-jwt/main.go
|
||||
|
|
||||
| import ( | ||||
| "fmt" | ||||
| "log" | ||||
| "net/http" | ||||
| "os" | ||||
| "strconv" | ||||
| "time" | ||||
|
|
||||
| "github.com/dgrijalva/jwt-go" | ||||
| "github.com/gin-gonic/gin" | ||||
| "github.com/jinzhu/gorm" | ||||
| _ "github.com/jinzhu/gorm/dialects/postgres" | ||||
|
|
||||
| // Change: Imported MySQL dialect instead of Postgres | ||||
| _ "github.com/jinzhu/gorm/dialects/mysql" | ||||
| ) | ||||
|
|
||||
| var ( | ||||
|
|
@@ -36,12 +37,30 @@ | |||
| } | ||||
|
|
||||
| func initDB() { | ||||
| dsn := "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable" | ||||
| db, err = gorm.Open("postgres", dsn) | ||||
| if err != nil { | ||||
| log.Printf("Failed to connect to database: %s", err) | ||||
| dsn := "myuser:mypassword@tcp(localhost:3306)/mydb?charset=utf8&parseTime=True&loc=Local&timeout=60s&readTimeout=60s" | ||||
|
|
||||
| var connectionErr error | ||||
| // Attempt to connect 10 times, waiting 2 seconds between attempts | ||||
| for i := 0; i < 10; i++ { | ||||
| db, connectionErr = gorm.Open("mysql", dsn) | ||||
| if connectionErr == nil { | ||||
| // Success! Check if we can actually ping | ||||
| if err := db.DB().Ping(); err == nil { | ||||
| break | ||||
| } | ||||
| } | ||||
|
|
||||
| log.Printf("Database not ready yet (Attempt %d/10)... Waiting...", i+1) | ||||
| time.Sleep(2 * time.Second) | ||||
| } | ||||
|
|
||||
| if connectionErr != nil { | ||||
| log.Printf("Failed to connect to database after retries: %s", connectionErr) | ||||
| log.Println("Ensure Docker is running and the MySQL container is ready.") | ||||
| os.Exit(1) | ||||
| } | ||||
|
|
||||
| log.Println("Successfully connected to the database!") | ||||
| db.AutoMigrate(&User{}) | ||||
| } | ||||
|
|
||||
|
|
@@ -55,7 +74,7 @@ | |||
| // Normally, you'd get this from the request, but we're hardcoding it for simplicity | ||||
| username := "example_user" | ||||
| password := "example_password" | ||||
|
|
||||
| fmt.Println("here is the current time :", time.Now().Unix()) | ||||
| // Set token expiration time | ||||
| expirationTime := time.Now().Add(5 * time.Minute) | ||||
|
|
||||
|
|
@@ -82,6 +101,7 @@ | |||
| if db.Where("username = ?", username).First(&user).RecordNotFound() { | ||||
| user = User{Username: username, Password: password, Token: tokenString} | ||||
| db.Create(&user) | ||||
| fmt.Println("token getting saved :", user) | ||||
| } else { | ||||
| user.Password = password | ||||
| user.Token = tokenString | ||||
|
|
@@ -135,8 +155,62 @@ | |||
| c.JSON(http.StatusOK, gin.H{"username": claims.Username}) | ||||
| } | ||||
|
|
||||
| // CheckTimeHandler checks if a client-provided timestamp is within 1 second of the server time. | ||||
| // The timestamp should be provided as a Unix timestamp in the 'ts' query parameter. | ||||
| func CheckTimeHandler(c *gin.Context) { | ||||
| // 1. Get the timestamp string from the URL query parameter 'ts' | ||||
| clientTimeStr := c.Query("ts") | ||||
| if clientTimeStr == "" { | ||||
| c.JSON(http.StatusBadRequest, gin.H{"error": "Missing 'ts' query parameter"}) | ||||
| return | ||||
| } | ||||
|
|
||||
| // 2. Parse the string into an integer (Unix timestamp) | ||||
| clientTimestamp, err := strconv.ParseInt(clientTimeStr, 10, 64) | ||||
| if err != nil { | ||||
| c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid timestamp format. Must be a Unix timestamp in seconds."}) | ||||
| return | ||||
| } | ||||
|
|
||||
| // 3. Convert the integer timestamp to a time.Time object | ||||
| clientTime := time.Unix(clientTimestamp, 0) | ||||
| serverTime := time.Now() | ||||
|
|
||||
| // 4. Calculate the duration (difference) between server time and client time | ||||
| diff := serverTime.Sub(clientTime) | ||||
|
|
||||
| // 5. Get the absolute value of the duration, since the client could be ahead or behind | ||||
| if diff < 0 { | ||||
| diff = -diff | ||||
| } | ||||
|
|
||||
| log.Printf( | ||||
| "Server Time: %s", | ||||
| serverTime.String(), | ||||
| ) | ||||
|
|
||||
| log.Printf( | ||||
| "Time difference: %s", | ||||
| diff.String(), | ||||
| ) | ||||
|
|
||||
| // 6. Check if the difference is greater than 1 second | ||||
| if diff > time.Second { | ||||
| c.Status(http.StatusBadRequest) | ||||
| return | ||||
| } | ||||
|
|
||||
| time.Sleep(1 * time.Second) | ||||
|
|
||||
|
Comment on lines
+203
to
+204
|
||||
| time.Sleep(1 * time.Second) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| #!/bin/bash | ||
|
|
||
| # This script sends a request to the /check-time endpoint. | ||
| # - If run without arguments, it uses the current Unix timestamp (should succeed). | ||
| # - If run with a number as an argument, it uses that number as the timestamp. | ||
|
|
||
| # --- Configuration --- | ||
| HOSTNAME="localhost" | ||
| PORT="8000" | ||
| ENDPOINT="/check-time" | ||
| # --------------------- | ||
|
|
||
| # Check if a command-line argument (a custom timestamp) was provided | ||
| if [ -n "$1" ]; then | ||
| # Use the provided argument as the timestamp | ||
| TIMESTAMP_TO_SEND="$1" | ||
| echo "Using provided timestamp: $TIMESTAMP_TO_SEND" | ||
| else | ||
| # No argument provided, get the current Unix timestamp | ||
| TIMESTAMP_TO_SEND=$(date +%s) | ||
| echo "Using current timestamp: $TIMESTAMP_TO_SEND" | ||
| fi | ||
|
|
||
| # Construct the full URL | ||
| URL="http://${HOSTNAME}:${PORT}${ENDPOINT}?ts=${TIMESTAMP_TO_SEND}" | ||
|
|
||
| # Send the request using curl and print the result | ||
| echo "Sending request to: ${URL}" | ||
| curl -s "${URL}" # The -s flag makes curl silent (no progress meter) | ||
| echo # Add a newline for cleaner terminal output |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When rejecting requests due to time difference, the response body is empty. Consider providing an error message explaining why the request was rejected, similar to other error cases in this handler.