Skip to content

Commit

Permalink
Merge pull request #6 from harisheoran/user-auth
Browse files Browse the repository at this point in the history
User auth implemented
  • Loading branch information
harisheoran authored Dec 13, 2024
2 parents 958f825 + d003c81 commit 7798b45
Show file tree
Hide file tree
Showing 17 changed files with 192 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tmp
2 changes: 2 additions & 0 deletions chat-server/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.env
tmp
bin
Binary file removed chat-server/bin/api
Binary file not shown.
1 change: 0 additions & 1 deletion chat-server/bin/tmp/build-errors.log

This file was deleted.

1 change: 1 addition & 0 deletions chat-server/cmd/server/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type app struct {
errorlogger *log.Logger
redisConnection *redis.Client
messageController postgre.MessageController
userController postgre.UserController
kafkaProducer *kafka.Writer
}

Expand Down
90 changes: 78 additions & 12 deletions chat-server/cmd/server/handlers.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package main

import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"text/template"

"github.com/gorilla/websocket"
"golang.org/x/crypto/bcrypt"
)

/*
Expand Down Expand Up @@ -71,26 +74,89 @@ func (app *app) homeHandler(w http.ResponseWriter, request *http.Request) {
}
}

func (app *app) authPageHandler(w http.ResponseWriter, request *http.Request) {
mytemplate := "ui/auth.html"
func (app *app) authHandler(w http.ResponseWriter, request *http.Request) {
method := request.Method
if method != "POST" {
sendJSONResponse(w, http.StatusMethodNotAllowed, ErrorResponse{
Error: "method_not_allowed",
Message: "method not allowed",
})
return
}

templates, err := template.ParseFiles(mytemplate)
reqBodyContent, err := io.ReadAll(request.Body)
if err != nil {
app.errorlogger.Println("ERROR: parsing the template files", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
sendJSONResponse(w, http.StatusInternalServerError, ErrorResponse{
Error: err.Error(),
Message: "Internal Server Error",
})
return
}
err = templates.Execute(w, nil)
defer request.Body.Close()

var requestBody AuthRequestBody
err = json.Unmarshal(reqBodyContent, &requestBody)
if err != nil {
app.errorlogger.Println(err.Error())
http.Error(w, "Internal server error", http.StatusInternalServerError)
sendJSONResponse(w, http.StatusInternalServerError, ErrorResponse{
Error: err.Error(),
Message: "Internal Server Error",
})
return
}
}

func (app *app) authHandler(w http.ResponseWriter, request *http.Request) {
err := request.ParseForm()
// create hash of password
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(requestBody.Password), 10)
if err != nil {
app.errorlogger.Print("unable to parse the form", err)
sendJSONResponse(w, http.StatusBadRequest, ErrorResponse{
Error: "bad_request",
Message: err.Error(),
})
return
}

// check existing user
user := app.userController.CheckUserExists(requestBody.Email)
if user != nil {
// compare password with hashedPassword
err = bcrypt.CompareHashAndPassword(hashedPassword, []byte(requestBody.Password))
if err != nil {
sendJSONResponse(w, http.StatusBadRequest, ErrorResponse{
Error: "bad_request",
Message: err.Error(),
})
return
}
if userMap, ok := user.(map[string]interface{}); ok {
username := userMap["username"].(string)
email := userMap["email"].(string)
sendJSONResponse(w, http.StatusBadRequest, SuccessResponse{
Message: "user found",
Data: map[string]interface{}{
"username": username,
"email": email,
"type": "login",
},
})
} else {
sendJSONResponse(w, http.StatusBadRequest, ErrorResponse{
Error: "bad_request",
Message: "Internal Server Error",
})
}
return
} else {
// create new user
user, err := app.userController.CreateNewUser(requestBody.Name, requestBody.Email, string(requestBody.Password))
if err != nil {
sendJSONResponse(w, http.StatusBadRequest, ErrorResponse{
Error: "bad_request",
Message: err.Error(),
})
return
}
sendJSONResponse(w, http.StatusCreated, SuccessResponse{
Message: "user created",
Data: user,
})
}
}
7 changes: 5 additions & 2 deletions chat-server/cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func main() {
// create database connection pool
databaseConnection, err := createDbConnectionPool(dsn)
if err != nil {
errorlogger.Println("unable to get a database connection from the pool")
errorlogger.Println("unable to get a database connection from the pool", err)
}

// establish the redis connection
Expand All @@ -96,6 +96,9 @@ func main() {
messageController: postgre.MessageController{
DbConnection: databaseConnection,
},
userController: postgre.UserController{
DbConnection: databaseConnection,
},
kafkaProducer: createProducer(),
}

Expand Down Expand Up @@ -132,7 +135,7 @@ func createDbConnectionPool(dsn string) (*gorm.DB, error) {
}

// Run the automigration for Project Model
if err := dbConnectionPool.AutoMigrate(&model.Message{}); err != nil {
if err := dbConnectionPool.AutoMigrate(&model.Message{}, &model.User{}); err != nil {
return nil, err
}

Expand Down
3 changes: 1 addition & 2 deletions chat-server/cmd/server/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ func (app *app) router() http.Handler {
mainRouter.HandleFunc("/v1/home", app.homeHandler)
mainRouter.HandleFunc("/v1/health", app.healthHandler)
mainRouter.HandleFunc("/v1/chat", app.chatHandler)
mainRouter.HandleFunc("/v1/authpage", app.authPageHandler)
mainRouter.HandleFunc("v1/auth", app.authHandler)
mainRouter.HandleFunc("/v1/auth", app.authHandler)

return mainRouter
}
17 changes: 17 additions & 0 deletions chat-server/cmd/server/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

type AuthRequestBody struct {
Email string `json:"email"`
Name string `json:"name"`
Password string `json:"password"`
}

type ErrorResponse struct {
Error string `json:"error"`
Message string `json:"message"`
}

type SuccessResponse struct {
Message string `json:"message"`
Data any `json:"data,omitempty"` // Use `any` for generic data
}
12 changes: 12 additions & 0 deletions chat-server/cmd/server/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import (
"encoding/json"
"net/http"
)

func sendJSONResponse(w http.ResponseWriter, statusCode int, response any) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statusCode)
json.NewEncoder(w).Encode(response)
}
2 changes: 1 addition & 1 deletion chat-server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ require (
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/net v0.31.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/text v0.21.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions chat-server/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
Expand Down
8 changes: 7 additions & 1 deletion chat-server/pkg/model/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import (
)

type User struct {
username string `json:"username"`
gorm.Model
ID uint `gorm:"primaryKey"`
Username string
Name string
Email string `gorm:"unique"`
Password string
CreatedAt time.Time
}

type Message struct {
Expand Down
7 changes: 7 additions & 0 deletions chat-server/pkg/model/postgre/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package postgre

type AuthRequestBody struct {
Email string `json:"email"`
Name string `json:"name"`
Password string `json:"password"`
}
57 changes: 57 additions & 0 deletions chat-server/pkg/model/postgre/user_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package postgre

import (
"strings"

"github.com/harisheoran/my-chat-system/pkg/model"
"gorm.io/gorm"
)

type UserController struct {
DbConnection *gorm.DB
}

func (uc *UserController) CheckUserExists(email string) interface{} {
var user model.User

// check for existing user with email
query := uc.DbConnection.Where("email = ?", email).First(&user)

if query.Error != nil {
return nil
}

// send existing user
response := map[string]interface{}{
"username": user.Username,
"email": user.Email,
"password": user.Password,
"type": "login",
}
return response

}

func (uc *UserController) CreateNewUser(name string, email string, password string) (interface{}, error) {
newUser := model.User{
Name: name,
Username: strings.Split(email, "@")[0],
Email: email,
Password: password,
}

query := uc.DbConnection.Create(&newUser)

if query.Error != nil {
return nil, query.Error
}

// send user data
response := map[string]interface{}{
"username": newUser.Username,
"email": newUser.Email,
"name": newUser.Name,
"type": "signup",
}
return response, nil
}
2 changes: 1 addition & 1 deletion chat-server/tmp/build-errors.log
Original file line number Diff line number Diff line change
@@ -1 +1 @@
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
1 change: 0 additions & 1 deletion tmp/build-errors.log

This file was deleted.

0 comments on commit 7798b45

Please sign in to comment.