Skip to content

Commit

Permalink
Merge pull request #5 from itishrishikesh/auth
Browse files Browse the repository at this point in the history
custom authentication mechanism added
  • Loading branch information
itishrishikesh authored Dec 9, 2023
2 parents 3e83aa8 + 96c7216 commit 8ff51ed
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 6 deletions.
25 changes: 25 additions & 0 deletions auth/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package auth

import (
"errors"
"net/http"
"strings"
)

// GetAPIKey extracts an API key from the header of an HTTP request
// Example:
// Authorization: ApiKey {insert apikey here}
func GetAPIKey(header http.Header) (string, error) {
val := header.Get("Authorization")
if val == "" {
return "", errors.New("E#1OTELT - No authentication info found!")
}
vals := strings.Split(val, " ")
if len(vals) != 2 {
return "", errors.New("E#1OTEM0 - Malformed auth header")
}
if vals[0] != "ApiKey" {
return "", errors.New("E#1OTEM5 - Malformed auth header")
}
return vals[1], nil
}
1 change: 1 addition & 0 deletions internal/database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 21 additions & 3 deletions internal/database/users.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func main() {
v1Router.Get("/healthz", healthCheckHandler)
v1Router.Get("/err", errorHandler)
v1Router.Post("/users", apiCfg.createUserHandler)
v1Router.Get("/users", apiCfg.getUserHandler)
router.Mount("/v1", v1Router)

server := &http.Server{
Expand Down
26 changes: 26 additions & 0 deletions models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package main

import (
"time"

"github.com/google/uuid"
"github.com/itishrishikesh/gofeed/internal/database"
)

type User struct {
ID uuid.UUID `json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Name string `json:"name"`
ApiKey string `json:"api_key"`
}

func databaseUserToUser(dbUser database.User) User {
return User{
ID: dbUser.ID,
CreatedAt: dbUser.CreatedAt,
UpdatedAt: dbUser.UpdatedAt,
Name: dbUser.Name,
ApiKey: dbUser.ApiKey,
}
}
9 changes: 6 additions & 3 deletions sql/queries/users.sql
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
-- name: CreateUser :one
INSERT INTO users (id, created_at, updated_at, name)
VALUES ($1, $2, $3, $4)
RETURNING *;
INSERT INTO users (id, created_at, updated_at, name, api_key)
VALUES ($1, $2, $3, $4, encode(sha256(random()::text::bytea), 'hex'))
RETURNING *;

-- name: GetUserByAPIKey :one
SELECT * FROM users WHERE api_key = $1;
7 changes: 7 additions & 0 deletions sql/schema/002_users_apikey.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- +goose Up
ALTER TABLE users ADD COLUMN api_key VARCHAR(64) UNIQUE NOT NULL DEFAULT (
encode(sha256(random()::text::bytea), 'hex')
);

-- +goose Down
ALTER TABLE users DROP COLUMN api_key;
16 changes: 16 additions & 0 deletions user_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/google/uuid"
"github.com/itishrishikesh/gofeed/auth"
"github.com/itishrishikesh/gofeed/constants"
"github.com/itishrishikesh/gofeed/internal/database"
)
Expand Down Expand Up @@ -38,5 +39,20 @@ func (apiCfg *apiConfig) createUserHandler(writer http.ResponseWriter, request *
return
}

respondWithJSON(writer, constants.HTTP_SUCCESS, databaseUserToUser(user))
}

func (apiCfg *apiConfig) getUserHandler(writer http.ResponseWriter, request *http.Request) {
apiKey, err := auth.GetAPIKey(request.Header)
if err != nil {
respondWithError(writer, 403, fmt.Sprintf("E#1OTELA - Auth Error: %v", err))
return
}
user, err := apiCfg.DB.GetUserByAPIKey(request.Context(), apiKey)
if err != nil {
respondWithError(writer, constants.HTTP_ERROR, fmt.Sprintf("E#1OTELI - Couldn't get user: %v", err))
return
}

respondWithJSON(writer, constants.HTTP_SUCCESS, user)
}

0 comments on commit 8ff51ed

Please sign in to comment.