diff --git a/assets/css/style.css b/assets/css/style.css
index 2cfa98f..dbf6822 100644
--- a/assets/css/style.css
+++ b/assets/css/style.css
@@ -28,7 +28,16 @@ body {
font-family: "Helvetica Neue", "Helvetica", serif;
margin: 0;
align-self: center;
+}
+
+.title-link {
font-size: 1.75rem;
+ color: #000;
+ text-decoration: none;
+}
+
+.title-link:hover {
+ color: #666;
}
.login-container {
diff --git a/auth/sessions.go b/auth/sessions.go
index 51c69f4..3505a5c 100644
--- a/auth/sessions.go
+++ b/auth/sessions.go
@@ -3,205 +3,33 @@ package auth
import (
"encoding/json"
"fmt"
- "github.com/gin-contrib/sessions"
- "github.com/gin-gonic/gin"
- "github.com/gorilla/securecookie"
- "github.com/markbates/goth"
- "log"
- "net/url"
- "sponsorahacker/config"
- "sponsorahacker/db"
"strconv"
- "time"
)
-type SessionStore interface {
- CreateSession(*gin.Context) error
- GetSession(string) (Session, error)
- DeleteSession(string) error
-}
-
-type SessionManager struct {
- DB *db.DBClient
-}
-
-type Session struct {
- sessionId string
- sessionData string
- createdOn string
- modifiedOn string
- expiresOn string
-}
-
type User struct {
NickName string `json:"NickName"`
Provider string `json:"Provider"`
Provider_userid string `json:"UserID"`
+ Sid string `json:"Sid"`
}
-var secureCookie *securecookie.SecureCookie
-
-func NewSessionManager(db *db.DBClient) SessionManager {
-
- return SessionManager{DB: db}
-}
-
-func (s *SessionManager) CreateSession(user goth.User, c *gin.Context) error {
- sessionData, err := json.Marshal(user)
- if err != nil {
- fmt.Printf("error marshalling user: %v", err)
- }
-
- auth := Session{
- sessionData: string(sessionData),
- createdOn: time.Now().Format("20060102150405"),
- modifiedOn: time.Now().Format("20060102150405"),
- expiresOn: user.ExpiresAt.Format("20060102150405"),
- }
-
- result, err := s.DB.Exec(`
- INSERT INTO sessions (sessionData, createdOn, modifiedOn, expiresOn)
- VALUES (?, ?, ?, ?);`, auth.sessionData, auth.createdOn, auth.modifiedOn, auth.expiresOn)
-
- if result == nil {
- fmt.Printf("error getting result from database while creating the session: %v", err)
- return err
- }
- spuser, err := GetUserFromSession(auth)
-
- err = s.SaveUserIfNotExist(spuser)
-
- if err != nil {
- log.Printf("error creating session: %v", err)
- return err
- }
-
- sessionId, err := result.LastInsertId()
-
- if err != nil {
- fmt.Printf("error getting session id from database while creating the session: %v", err)
- }
-
- hash := []byte(config.GetEnvVar("COOKIE_HASH"))
- block := []byte(config.GetEnvVar("COOKIE_BLOCK"))
- secureCookie = securecookie.New(hash, block)
- cookieValue := map[string]string{
- "sessionId": strconv.Itoa(int(sessionId)),
- }
-
- encoded, err := secureCookie.Encode("_session", cookieValue)
-
- if err != nil {
- fmt.Printf("error encoding cookie value: %v", err)
- return err
- }
-
- c.SetCookie("_session", encoded, 3600, "/", "localhost", false, true)
-
- return nil
-}
-
-func (s *SessionManager) GetSession(session sessions.Session) (Session, error) {
- // query for one row
- result, err := s.DB.Query(`SELECT sessionData FROM sessions WHERE sessionId=$1 LIMIT 1`, session.ID())
+func HydrateUser(userJson string) *User {
+ user := User{}
- // if err, then return an empty struct
- if err != nil {
- return Session{}, err
+ if err := json.Unmarshal([]byte(userJson), &user); err != nil {
+ fmt.Println("serialization in hydrating user error = ", err)
+ return nil
}
- // else go through the results and create a Session
- for result.Next() {
- var s Session
-
- // unless there is an error, of course, then return an empty struct
- if err := result.StructScan(&s); err != nil {
- return Session{}, err
- }
-
- return s, nil
- }
-
- // if we get nothing, well, we go nothing
- return Session{}, nil
+ return &user
}
-func GetUserFromSession(session Session) (User, error) {
- var user User
-
- fmt.Println(session.sessionData)
- err := json.Unmarshal([]byte(session.sessionData), &user)
+func (u *User) GetSid() int {
+ strSid, err := strconv.Atoi(u.Sid)
if err != nil {
- fmt.Println("error unmarshalling session data for user", err)
-
- return User{}, err
+ fmt.Println("sid is invalid")
}
- return user, nil
-}
-
-func (s *SessionManager) SaveUserIfNotExist(user User) error {
- rows, err := s.DB.Query(`SELECT * FROM users WHERE provider_userid = ? AND provider = ? LIMIT 1`, user.Provider_userid, user.Provider)
-
- if err != nil {
- fmt.Printf("error getting user from database: %v", err)
- return err
- }
-
- exists := rows.Next()
-
- if !exists {
- _, err = s.DB.Exec(`
- INSERT INTO users (provider_userid, provider, username)
- VALUES (?, ?, ?);`, user.Provider_userid, user.Provider, user.NickName)
-
- if err != nil {
- fmt.Printf("error inserting user: %v", err)
- return err
- }
- }
-
- return nil
-}
-
-func (s *SessionManager) DeleteSession(c *gin.Context) error {
- if cookie, err := c.Request.Cookie("_session"); err == nil {
- value := make(map[string]string)
-
- cookieValue, _ := url.QueryUnescape(cookie.Value)
-
- hash := []byte(config.GetEnvVar("COOKIE_HASH"))
- block := []byte(config.GetEnvVar("COOKIE_BLOCK"))
- secureCookie := securecookie.New(hash, block)
-
- err = secureCookie.Decode("_session", cookieValue, &value)
-
- if err != nil {
- fmt.Printf("error decoding cookie value: %v", err)
- return err
- }
-
- sessionId := value["sessionId"]
- sessionIdInt, err := strconv.Atoi(sessionId)
-
- if err != nil {
- fmt.Printf("error converting sessionId to int: %v", err)
- return err
- }
-
- _, err = s.DB.Exec(`DELETE FROM sessions WHERE ID = ?`, sessionIdInt)
-
- if err != nil {
- return err
- }
-
- if err != nil {
- return err
- }
- }
-
- c.SetCookie("_session", "", -1, "/", "localhost", false, true)
-
- return nil
+ return strSid
}
diff --git a/db/db.go b/db/db.go
index 25acaec..e2fd2a8 100644
--- a/db/db.go
+++ b/db/db.go
@@ -34,6 +34,7 @@ func (db *DBClient) Query(query string, args ...interface{}) (*sqlx.Rows, error)
}
func (db *DBClient) Exec(query string, args ...interface{}) (sql.Result, error) {
+ fmt.Println("running query")
return db.db.Exec(query, args...)
}
diff --git a/main.go b/main.go
index 4534af5..84beb21 100644
--- a/main.go
+++ b/main.go
@@ -44,6 +44,7 @@ func main() {
r.GET("/login", pages.Login)
r.GET("/welcome", pages.Welcome)
r.GET("/goals", pages.Goals)
+ r.GET("/goals/:goalId", pages.Goal)
// post routes
r.POST("/goals", pages.CreateGoal)
err = r.Run(":8080")
diff --git a/models/goal.go b/models/goal.go
new file mode 100644
index 0000000..ced7114
--- /dev/null
+++ b/models/goal.go
@@ -0,0 +1,81 @@
+package models
+
+import (
+ "fmt"
+ "log"
+ "time"
+
+ "sponsorahacker/db"
+)
+
+type Goal struct {
+ id int
+ Name string `form:"item-name" db:"name" binding:"required"`
+ FundingAmount float64 `form:"funding-amount" db:"funding_amount" binding:"required,numeric"`
+ Description string `form:"item-description" db:"description" binding:"required"`
+ LearnMoreURL string `form:"item-url" db:"learn_more_url"` // Optional field
+ CreatedAt time.Time `db:"created_at"`
+ UpdatedAt time.Time `db:"updated_at"`
+ CreatedBy int `db:"created_by"`
+}
+
+func (g *Goal) CreateGoal() error {
+ dbClient, err := db.NewDbClient()
+
+ if err != nil {
+ log.Fatalf("Could not connect to database: %v", err)
+ return err
+ }
+ _, err = dbClient.Exec(`INSERT INTO goals (name, description, learn_more_url, funding_amount, created_by, created_at, updated_at)
+VALUES (?, ?, ?, ?, ?, ?, ?);`, g.Name, g.Description, g.LearnMoreURL, g.FundingAmount, g.CreatedBy, g.CreatedAt, g.UpdatedAt)
+
+ if err != nil {
+ log.Fatalf("Could not create goal: %v", err)
+ }
+ return nil
+}
+
+func GetGoals(user int) ([]Goal, error) {
+ var goals []Goal
+
+ dbClient, err := db.NewDbClient()
+
+ if err != nil {
+ log.Fatalf("Could not connect to database: %v", err)
+ }
+
+ result, err := dbClient.Query(`SELECT name, description, learn_more_url, funding_amount, created_by, created_at, updated_at FROM goals where created_by = ?`, user)
+
+ if err != nil {
+ log.Fatalf("Could not get goals: %v", err)
+ }
+ for result.Next() {
+ var goal Goal
+ err = result.StructScan(&goal)
+
+ fmt.Println(goal.Name)
+
+ if err != nil {
+ log.Fatalf("Could not read goal: %v", err)
+ return nil, err
+ }
+ goals = append(goals, goal)
+ }
+
+ return goals, nil
+}
+
+func GetGoal(id int) (*Goal, error) {
+ dbClient, err := db.NewDbClient()
+ result, err := dbClient.Query(`SELECT name, description, learn_more_url, funding_amount, created_by, created_at, updated_at FROM goals where id = ?`, id)
+
+ if err != nil {
+ log.Fatalf("Could not read goal: %v", err)
+ return nil, err
+ }
+
+ var goal Goal
+ err = result.StructScan(&goal)
+
+ return &goal, nil
+}
diff --git a/pages/goals.go b/pages/goals.go
index 9a75550..b75f08d 100644
--- a/pages/goals.go
+++ b/pages/goals.go
@@ -3,26 +3,86 @@ package pages
import (
"fmt"
"github.com/gin-gonic/gin"
+ "github.com/markbates/goth/gothic"
+ "log"
"net/http"
"net/url"
+ "sponsorahacker/auth"
"sponsorahacker/models"
- "sponsorahacker/utils"
"strconv"
"strings"
"time"
)
func Goals(c *gin.Context) {
- isLoggedIn := utils.CheckIfLoggedIn(c)
+ user, err := gothic.GetFromSession("user", c.Request)
+
+ if err != nil {
+ fmt.Println("error finding session: ", err)
+ c.Redirect(http.StatusTemporaryRedirect, "/login")
+ return
+ }
+
+ userModel := auth.HydrateUser(user)
+
+ goals, err := models.GetGoals(userModel.GetSid())
+
+ if err != nil {
+ fmt.Println("error getting goals: ", err)
+ }
+
+ fmt.Println("sid: ", userModel.GetSid())
+ fmt.Println("goals:", goals)
c.HTML(http.StatusOK, "goals.html", gin.H{
"title": "Sponsor A Hacker",
- "isLoggedIn": isLoggedIn,
+ "isLoggedIn": true,
+ "user": userModel.NickName,
+ "goals": goals,
+ })
+}
+
+func Goal(c *gin.Context) {
+ user, err := gothic.GetFromSession("user", c.Request)
+
+ if err != nil {
+ fmt.Println("error finding session: ", err)
+ c.Redirect(http.StatusTemporaryRedirect, "/login")
+ return
+ }
+
+ goalId, err := strconv.Atoi(c.Param("goalId"))
+
+ if err != nil {
+ log.Println("error parsing goal id: ", err)
+ }
+
+ userModel := auth.HydrateUser(user)
+ goal, err := models.GetGoal(goalId)
+
+ if err != nil {
+ fmt.Println("error getting goals: ", err)
+ }
+
+ c.HTML(http.StatusOK, "goal.html", gin.H{
+ "title": "Sponsor A Hacker",
+ "isLoggedIn": true,
+ "user": userModel.NickName,
+ "goal": goal,
})
}
func CreateGoal(c *gin.Context) {
- isLoggedIn := utils.CheckIfLoggedIn(c)
+ user, err := gothic.GetFromSession("user", c.Request)
+
+ if err != nil {
+ fmt.Println("error finding session: ", err)
+ c.AbortWithStatus(http.StatusForbidden)
+ return
+ }
+
+ userModel := auth.HydrateUser(user)
+
trim := strings.TrimSpace
parseFloat := strconv.ParseFloat
parseUrl := url.Parse
@@ -36,13 +96,13 @@ func CreateGoal(c *gin.Context) {
description := trim(c.PostForm("item-description"))
learnMoreURL := trim(c.PostForm("item-url"))
- _, err := parseUrl(learnMoreURL)
+ _, err = parseUrl(learnMoreURL)
if isEmpty(name) && isEmpty(fundingAmountStr) && isEmpty(description) && isEmpty(learnMoreURL) && err != nil {
fieldError := fmt.Errorf("missing a required field. Please check and make sure all fields are filled out")
c.HTML(http.StatusNotAcceptable, "goals.html", gin.H{
"title": "Sponsor A Hacker",
- "isLoggedIn": isLoggedIn,
+ "isLoggedIn": true,
"error": fieldError,
})
}
@@ -53,7 +113,7 @@ func CreateGoal(c *gin.Context) {
fieldError := fmt.Errorf("invalid funding amount")
c.HTML(http.StatusInternalServerError, "goals.html", gin.H{
"title": "Sponsor A Hacker",
- "isLoggedIn": isLoggedIn,
+ "isLoggedIn": true,
"error": fieldError,
})
}
@@ -61,12 +121,18 @@ func CreateGoal(c *gin.Context) {
createdDate := time.Now()
updatedDate := time.Now()
+ if err != nil {
+ c.HTML(http.StatusInternalServerError, "goals.html", gin.H{})
+ }
+
+ fmt.Println("sid is : ", userModel.GetSid())
goal := models.Goal{
Name: name,
FundingAmount: fundingAmount,
Description: description,
LearnMoreURL: learnMoreURL,
CreatedAt: createdDate,
+ CreatedBy: userModel.GetSid(),
UpdatedAt: updatedDate,
}
@@ -76,13 +142,13 @@ func CreateGoal(c *gin.Context) {
fmt.Printf("Error inserting goal: %v", err)
c.HTML(http.StatusInternalServerError, "goals.html", gin.H{
"title": "Sponsor A Hacker",
- "isLoggedIn": isLoggedIn,
+ "isLoggedIn": true,
"error": err,
})
}
c.HTML(http.StatusOK, "goals.html", gin.H{
"title": "Sponsor A Hacker",
- "isLoggedIn": isLoggedIn,
+ "isLoggedIn": true,
})
}
diff --git a/pages/home.go b/pages/home.go
index ec60a85..5e8057a 100644
--- a/pages/home.go
+++ b/pages/home.go
@@ -3,29 +3,29 @@ package pages
import (
"fmt"
"github.com/gin-gonic/gin"
- "github.com/joho/godotenv"
- "log"
+ "github.com/markbates/goth/gothic"
"net/http"
- "sponsorahacker/db"
- "sponsorahacker/utils"
+ "sponsorahacker/auth"
)
func Home(c *gin.Context) {
+ user, err := gothic.GetFromSession("user", c.Request)
- envErr := godotenv.Load()
- if envErr != nil {
- log.Fatal("Error loading .env file")
+ if err != nil {
+ fmt.Println("error checking login", err)
}
- isLoggedIn := utils.CheckIfLoggedIn(c)
- fmt.Println("isLoggedIn:", isLoggedIn)
- _, err := db.NewDbClient()
+ auth.HydrateUser(user)
+
if err != nil {
- log.Fatal(err)
+ fmt.Println("error checking login", err)
+ c.HTML(http.StatusOK, "index.html", gin.H{
+ "title": "Sponsor a Hacker",
+ "isLoggedIn": false,
+ })
+
+ return
}
- c.HTML(http.StatusOK, "index.html", gin.H{
- "title": "Sponsor a Hacker",
- "isLoggedIn": isLoggedIn,
- })
+ c.Redirect(http.StatusTemporaryRedirect, "/welcome")
}
diff --git a/pages/welcome.go b/pages/welcome.go
index f60241c..2cb276b 100644
--- a/pages/welcome.go
+++ b/pages/welcome.go
@@ -3,15 +3,27 @@ package pages
import (
"fmt"
"github.com/gin-gonic/gin"
+ "github.com/markbates/goth/gothic"
"net/http"
- "sponsorahacker/utils"
+ "sponsorahacker/auth"
)
func Welcome(c *gin.Context) {
- isLoggedIn := utils.CheckIfLoggedIn(c)
- fmt.Println("isLoggedIn:", isLoggedIn)
+ user, err := gothic.GetFromSession("user", c.Request)
+ fmt.Println(user)
+
+ if err != nil {
+ fmt.Println("error finding session: ", err)
+ c.Redirect(http.StatusTemporaryRedirect, "/login")
+ return
+ }
+
+ userModel := auth.HydrateUser(user)
+ fmt.Println(userModel.NickName)
+
c.HTML(http.StatusOK, "welcome.html", gin.H{
"title": "Sponsor A Hacker",
- "isLoggedIn": isLoggedIn,
+ "isLoggedIn": true,
+ "user": userModel.NickName,
})
}
diff --git a/templates/goal.html b/templates/goal.html
new file mode 100644
index 0000000..373235e
--- /dev/null
+++ b/templates/goal.html
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+ Goal Page
+
+
+
+{{template "pageheader" . }}
+
+
+
+
+ Goal: Learn Full-Stack Development
+ Description: A comprehensive course to master full-stack web development. This goal includes learning front-end and back-end technologies to build robust applications.
+ Funding Needed: $500
+ Funding Received: $350
+
+
+
+
+ Funding Progress
+
+ 70% funded
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/templates/goals.html b/templates/goals.html
index 14e4949..2ef473e 100644
--- a/templates/goals.html
+++ b/templates/goals.html
@@ -13,7 +13,7 @@
@@ -43,20 +43,15 @@
Your Current Goals
-
-
-
Full-Stack Development Certification
-
Progress: 75% funded
+ {{ range .goals }}
+
+
+
{{ .Name }}
+
{{ .Description }}
+
Progress: 75% funded
+
-
Remove
-
-
-
-
Data Science Course
-
Progress: 40% funded
-
-
Remove
-
+ {{ end }}
diff --git a/templates/header.html b/templates/header.html
index 0f941e1..6ec4ef5 100644
--- a/templates/header.html
+++ b/templates/header.html
@@ -1,14 +1,17 @@
{{define "pageheader"}}
diff --git a/templates/upload-goal.html b/templates/upload-goal.html
new file mode 100644
index 0000000..17c7d13
--- /dev/null
+++ b/templates/upload-goal.html
@@ -0,0 +1,116 @@
+
+
+
+
+
+ Submit Hackathon Project
+
+
+
+
+
+
diff --git a/templates/welcome.html b/templates/welcome.html
index 90e0303..5af984c 100644
--- a/templates/welcome.html
+++ b/templates/welcome.html
@@ -12,7 +12,7 @@
-
Welcome, Codegirl007!
+
Welcome, {{ .user }}!
Find your path, fund futures, or inspire a community today.