diff --git a/cmd/web/main.go b/cmd/web/main.go index 37a555b..fb280af 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -11,13 +11,11 @@ import ( "github.com/Pomog/ForumFFF/internal/models" "github.com/Pomog/ForumFFF/internal/renderer" "github.com/Pomog/ForumFFF/internal/repository" - "github.com/google/uuid" ) const Port = ":8080" var app config.AppConfig -var sessionID uuid.UUID func main() { @@ -43,10 +41,6 @@ func main() { func run() (*repository.DataBase, error) { fmt.Println("Starting application") - sessionID = uuid.New() - - app.UserLogin = &sessionID - // gob.Register() function is used to inform the encoding/gob package about custom types that may be encoded or decoded using the gob encoding format. gob.Register(models.User{}) gob.Register(models.Thread{}) diff --git a/internal/config/config.go b/internal/config/config.go index df0a076..f92404c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -14,5 +14,5 @@ type AppConfig struct { InfoLog *log.Logger InProduction bool ErrorLog *log.Logger - UserLogin *uuid.UUID // This field can hold a UUID value + UserLogin uuid.UUID // This field can hold a UUID value } diff --git a/internal/handler/handlers.go b/internal/handler/handlers.go index f3e95c7..fd8e570 100644 --- a/internal/handler/handlers.go +++ b/internal/handler/handlers.go @@ -1,7 +1,6 @@ package handler import ( - "fmt" "io" "log" "net/http" @@ -9,6 +8,7 @@ import ( "os" "path" "path/filepath" + "strconv" "time" "github.com/Pomog/ForumFFF/internal/config" @@ -17,6 +17,7 @@ import ( "github.com/Pomog/ForumFFF/internal/renderer" "github.com/Pomog/ForumFFF/internal/repository" "github.com/Pomog/ForumFFF/internal/repository/dbrepo" + "github.com/google/uuid" ) // Repo the repository used by the handlers @@ -89,9 +90,17 @@ func (m *Repository) LoginHandler(w http.ResponseWriter, r *http.Request) { } // Check if User is Presaent in the DB, ERR should be handled - result, _ := m.DB.UserPresentLogin(loginData.Email, loginData.Password) - fmt.Println("UserPresentLogin: ", result) - if result { + userID, _ := m.DB.UserPresentLogin(loginData.Email, loginData.Password) + if userID != 0 { + m.App.UserLogin = uuid.New() + m.DB.InsertSessionintoDB(m.App.UserLogin.String(), userID) + + cookie := &http.Cookie{ + Name: strconv.Itoa(userID), + Value: m.App.UserLogin.String(), + } + http.SetCookie(w, cookie) + http.Redirect(w, r, "/home", http.StatusSeeOther) } else { setErrorAndRedirect(w, r, "Wrong email or password", "/error-page") @@ -202,10 +211,25 @@ func (m *Repository) RegisterHandler(w http.ResponseWriter, r *http.Request) { // MainHandler is a method of the Repository struct that handles requests to the main page. // It renders the "home.page.html" template to the provided HTTP response writer. func (m *Repository) HomeHandler(w http.ResponseWriter, r *http.Request) { + var UserID int + for _, cookie := range r.Cookies() { + if cookie.Value != "" { + userID, err := m.DB.GetUserIDForSessionID(cookie.Value) + if err != nil { + setErrorAndRedirect(w, r, "Could not get UserID from Cookies m.DB.GetUserIDForSessionID", "/error-page") + } + UserID = userID + } + } + + if UserID == 0 { + setErrorAndRedirect(w, r, "Could not verify User, Please LogIN", "/error-page") + } + if r.Method == http.MethodGet { threads, err := m.DB.GetAllThreads() if err != nil { - log.Fatal(err) + setErrorAndRedirect(w, r, "Could not get Threads m.DB.GetAllThreads", "/error-page") } var threadsInfo []models.ThreadDataForMainPage @@ -240,25 +264,19 @@ func (m *Repository) HomeHandler(w http.ResponseWriter, r *http.Request) { } else if r.Method == http.MethodPost { thread := models.Thread{ Subject: r.FormValue("message-text"), - UserID: getUserFromCookies(r), + UserID: UserID, } err := m.DB.CreateThread(thread) if err != nil { setErrorAndRedirect(w, r, "Could not create a thread", "/error-page") } + http.Redirect(w, r, "/theme", http.StatusPermanentRedirect) } } -func getUserFromCookies(r *http.Request) int { - beaves := models.User{ - ID: 4, - } - return beaves.ID -} - func getUserThatCreatedLastPost(posts []models.Post) int { var id int timeOfLastPost, _ := time.Parse("2006-01-02 15:04:05", "2006-01-02 15:04:05") diff --git a/internal/repository/db_funcs_test.go b/internal/repository/db_funcs_test.go index bf4f81c..73e62d4 100644 --- a/internal/repository/db_funcs_test.go +++ b/internal/repository/db_funcs_test.go @@ -6,7 +6,7 @@ import ( ) var ObligatoryTables = []string{ - "users", "thread", "votes", "post", + "users", "thread", "votes", "post", "sessionId", } func Test_GetDB(t *testing.T) { diff --git a/internal/repository/dbrepo/sqllite.go b/internal/repository/dbrepo/sqllite.go index 1f5d1b5..295287d 100644 --- a/internal/repository/dbrepo/sqllite.go +++ b/internal/repository/dbrepo/sqllite.go @@ -31,28 +31,25 @@ func (m *SqliteBDRepo) UserPresent(userName, email string) (bool, error) { return true, nil } -func (m *SqliteBDRepo) UserPresentLogin(email, password string) (bool, error) { +func (m *SqliteBDRepo) UserPresentLogin(email, password string) (int, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - query := `select count(id) + query := `select id from users where email = $1 and password = $2 ` - var numRows int + row := m.DB.QueryRowContext(ctx, query, email, password) - err := row.Scan(&numRows) + userID := 0 + err := row.Scan(&userID) if err != nil { - return false, nil - } - - if numRows == 0 { - return false, nil + return userID, err } - return true, nil + return userID, nil } func (m *SqliteBDRepo) GetUserByID(ID int) (models.User, error) { @@ -239,3 +236,65 @@ func (m *SqliteBDRepo) GetAllThreads() ([]models.Thread, error) { return threads, nil } + +func (m *SqliteBDRepo) GetSessionIDForUserID(userID int) (string, error) { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + query := `select sessionID + from sessionId WHERE + userID = $1 + ` + sessionID := "" + + row := m.DB.QueryRowContext(ctx, query, userID) + + err := row.Scan(&sessionID) + if err != nil { + return sessionID, err + } + + return sessionID, nil +} + +func (m *SqliteBDRepo) GetUserIDForSessionID(sessionID string) (int, error) { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + query := `select userID + from sessionId WHERE + sessionID = $1 + ` + var userID int + + row := m.DB.QueryRowContext(ctx, query, sessionID) + + err := row.Scan(&userID) + if err != nil { + return 0, err + } + + return userID, nil +} + +func (m *SqliteBDRepo) InsertSessionintoDB(sessionID string, userID int) error { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + stmt := `insert into sessionId + (sessionID, userID) + values ($1, $2 + ) + ` + + _, err := m.DB.ExecContext(ctx, stmt, + sessionID, + userID, + ) + + if err != nil { + return err + } + return nil + +} diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 2b272f9..7ef54b7 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -4,7 +4,7 @@ import "github.com/Pomog/ForumFFF/internal/models" type DatabaseInt interface { UserPresent(userName, email string) (bool, error) - UserPresentLogin(email, password string) (bool, error) + UserPresentLogin(email, password string) (int, error) CreateUser(r models.User) error CreateThread(thread models.Thread) error CreatePost(post models.Post) error @@ -13,4 +13,7 @@ type DatabaseInt interface { GetUserByID(ID int) (models.User, error) GetAllThreads() ([]models.Thread, error) GetThreadByID(ID int) (models.Thread, error) + GetSessionIDForUserID(userID int) (string, error) + GetUserIDForSessionID(sessionID string) (int, error) + InsertSessionintoDB(sessionID string, userID int) error } diff --git a/internal/repository/sql.go b/internal/repository/sql.go index 18c449b..37d61a2 100644 --- a/internal/repository/sql.go +++ b/internal/repository/sql.go @@ -41,11 +41,19 @@ var votesTable = `CREATE TABLE IF NOT EXISTS votes ( FOREIGN KEY (userID) REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE );` +var sessionIdTable = `CREATE TABLE IF NOT EXISTS sessionId ( + id INTEGER PRIMARY KEY, + userID INTEGER, + sessionID TEXT, + FOREIGN KEY (userID) REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE +);` + func getQuerys() []string { var sqlQuerys []string sqlQuerys = append(sqlQuerys, userTable) sqlQuerys = append(sqlQuerys, threadTable) sqlQuerys = append(sqlQuerys, postTable) sqlQuerys = append(sqlQuerys, votesTable) + sqlQuerys = append(sqlQuerys, sessionIdTable) return sqlQuerys -} \ No newline at end of file +}