Skip to content

Commit 274ed22

Browse files
ziddah edemziddah edem
authored andcommitted
updated
1 parent 460861b commit 274ed22

File tree

11 files changed

+1009
-739
lines changed

11 files changed

+1009
-739
lines changed

cmd/server/main.go

Lines changed: 70 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,70 @@
1-
package main
2-
3-
import (
4-
"database/sql"
5-
"fmt"
6-
"log"
7-
"net/http"
8-
9-
"github.com/gin-gonic/gin"
10-
"github.com/wpcodevo/golang-postgresql-grpc/config"
11-
"github.com/wpcodevo/golang-postgresql-grpc/controllers"
12-
dbConn "github.com/wpcodevo/golang-postgresql-grpc/db/sqlc"
13-
"github.com/wpcodevo/golang-postgresql-grpc/routes"
14-
15-
_ "github.com/lib/pq"
16-
)
17-
18-
var (
19-
server *gin.Engine
20-
db *dbConn.Queries
21-
22-
AuthController controllers.AuthController
23-
AuthRoutes routes.AuthRoutes
24-
)
25-
26-
func init() {
27-
config, err := config.LoadConfig(".")
28-
29-
if err != nil {
30-
log.Fatalf("could not load config: %v", err)
31-
}
32-
33-
conn, err := sql.Open(config.PostgreDriver, config.PostgresSource)
34-
if err != nil {
35-
log.Fatalf("could not connect to postgres database: %v", err)
36-
}
37-
38-
db = dbConn.New(conn)
39-
40-
fmt.Println("PostgreSQL connected successfully...")
41-
42-
AuthController = *controllers.NewAuthController(db)
43-
AuthRoutes = routes.NewAuthRoutes(AuthController)
44-
45-
server = gin.Default()
46-
}
47-
48-
func main() {
49-
config, err := config.LoadConfig(".")
50-
51-
if err != nil {
52-
log.Fatalf("could not load config: %v", err)
53-
}
54-
55-
router := server.Group("/api")
56-
57-
router.GET("/healthchecker", func(ctx *gin.Context) {
58-
ctx.JSON(http.StatusOK, gin.H{"status": "success", "message": "Welcome to Golang with PostgreSQL"})
59-
})
60-
61-
AuthRoutes.AuthRoute(router)
62-
log.Fatal(server.Run(":" + config.Port))
63-
}
1+
package main
2+
3+
import (
4+
"context"
5+
"database/sql"
6+
"fmt"
7+
"log"
8+
"net/http"
9+
10+
"github.com/gin-gonic/gin"
11+
"github.com/wpcodevo/golang-postgresql-grpc/config"
12+
"github.com/wpcodevo/golang-postgresql-grpc/controllers"
13+
dbConn "github.com/wpcodevo/golang-postgresql-grpc/db/sqlc"
14+
"github.com/wpcodevo/golang-postgresql-grpc/routes"
15+
16+
_ "github.com/lib/pq"
17+
)
18+
19+
var (
20+
server *gin.Engine
21+
db *dbConn.Queries
22+
ctx context.Context
23+
24+
AuthController controllers.AuthController
25+
AuthRoutes routes.AuthRoutes
26+
)
27+
28+
func init() {
29+
ctx = context.TODO()
30+
config, err := config.LoadConfig(".")
31+
32+
if err != nil {
33+
log.Fatalf("could not load config: %v", err)
34+
}
35+
36+
conn, err := sql.Open(config.PostgreDriver, config.PostgresSource)
37+
if err != nil {
38+
log.Fatalf("could not connect to postgres database: %v", err)
39+
}
40+
41+
db = dbConn.New(conn)
42+
43+
fmt.Println("PostgreSQL connected successfully...")
44+
45+
AuthController = *controllers.NewAuthController(db, ctx)
46+
AuthRoutes = routes.NewAuthRoutes(AuthController, db)
47+
48+
server = gin.Default()
49+
}
50+
51+
func main() {
52+
config, err := config.LoadConfig(".")
53+
54+
if err != nil {
55+
log.Fatalf("could not load config: %v", err)
56+
}
57+
58+
router := server.Group("/api")
59+
60+
router.GET("/healthchecker", func(ctx *gin.Context) {
61+
ctx.JSON(http.StatusOK, gin.H{"status": "success", "message": "Welcome to Golang with PostgreSQL"})
62+
})
63+
64+
AuthRoutes.AuthRoute(router)
65+
66+
server.NoRoute(func(ctx *gin.Context) {
67+
ctx.JSON(http.StatusNotFound, gin.H{"status": "fail", "message": fmt.Sprintf("Route %s not found", ctx.Request.URL)})
68+
})
69+
log.Fatal(server.Run(":" + config.Port))
70+
}

config/default.go

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,39 @@
1-
package config
2-
3-
import (
4-
"github.com/spf13/viper"
5-
)
6-
7-
type Config struct {
8-
PostgreDriver string `mapstructure:"POSTGRES_DRIVER"`
9-
PostgresSource string `mapstructure:"POSTGRES_SOURCE"`
10-
11-
Port string `mapstructure:"PORT"`
12-
}
13-
14-
func LoadConfig(path string) (config Config, err error) {
15-
viper.AddConfigPath(path)
16-
viper.SetConfigType("env")
17-
viper.SetConfigName("app")
18-
19-
viper.AutomaticEnv()
20-
21-
err = viper.ReadInConfig()
22-
if err != nil {
23-
return
24-
}
25-
26-
err = viper.Unmarshal(&config)
27-
return
28-
}
1+
package config
2+
3+
import (
4+
"time"
5+
6+
"github.com/spf13/viper"
7+
)
8+
9+
type Config struct {
10+
PostgreDriver string `mapstructure:"POSTGRES_DRIVER"`
11+
PostgresSource string `mapstructure:"POSTGRES_SOURCE"`
12+
13+
Port string `mapstructure:"PORT"`
14+
15+
AccessTokenPrivateKey string `mapstructure:"ACCESS_TOKEN_PRIVATE_KEY"`
16+
AccessTokenPublicKey string `mapstructure:"ACCESS_TOKEN_PUBLIC_KEY"`
17+
RefreshTokenPrivateKey string `mapstructure:"REFRESH_TOKEN_PRIVATE_KEY"`
18+
RefreshTokenPublicKey string `mapstructure:"REFRESH_TOKEN_PUBLIC_KEY"`
19+
AccessTokenExpiresIn time.Duration `mapstructure:"ACCESS_TOKEN_EXPIRED_IN"`
20+
RefreshTokenExpiresIn time.Duration `mapstructure:"REFRESH_TOKEN_EXPIRED_IN"`
21+
AccessTokenMaxAge int `mapstructure:"ACCESS_TOKEN_MAXAGE"`
22+
RefreshTokenMaxAge int `mapstructure:"REFRESH_TOKEN_MAXAGE"`
23+
}
24+
25+
func LoadConfig(path string) (config Config, err error) {
26+
viper.AddConfigPath(path)
27+
viper.SetConfigType("env")
28+
viper.SetConfigName("app")
29+
30+
viper.AutomaticEnv()
31+
32+
err = viper.ReadInConfig()
33+
if err != nil {
34+
return
35+
}
36+
37+
err = viper.Unmarshal(&config)
38+
return
39+
}

controllers/signup.controller.go

Lines changed: 141 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,141 @@
1-
package controllers
2-
3-
import (
4-
"net/http"
5-
"time"
6-
7-
"github.com/gin-gonic/gin"
8-
db "github.com/wpcodevo/golang-postgresql-grpc/db/sqlc"
9-
"github.com/wpcodevo/golang-postgresql-grpc/utils"
10-
)
11-
12-
type AuthController struct {
13-
db *db.Queries
14-
}
15-
16-
func NewAuthController(db *db.Queries) *AuthController {
17-
return &AuthController{db}
18-
}
19-
20-
func (ac *AuthController) SignUpUser(ctx *gin.Context) {
21-
var credentials *db.User
22-
23-
if err := ctx.ShouldBindJSON(&credentials); err != nil {
24-
ctx.JSON(http.StatusBadRequest, err.Error())
25-
return
26-
}
27-
28-
hashedPassword := utils.HashPassword(credentials.Password)
29-
30-
args := &db.CreateUserParams{
31-
Name: credentials.Name,
32-
Email: credentials.Email,
33-
Password: hashedPassword,
34-
Photo: "default.jpeg",
35-
Verified: true,
36-
Role: "user",
37-
UpdatedAt: time.Now(),
38-
}
39-
40-
user, err := ac.db.CreateUser(ctx, *args)
41-
42-
if err != nil {
43-
ctx.JSON(http.StatusBadGateway, err.Error())
44-
return
45-
}
46-
47-
ctx.JSON(http.StatusCreated, gin.H{"status": "success", "data": gin.H{"user": user}})
48-
}
1+
package controllers
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
"time"
8+
9+
"github.com/gin-gonic/gin"
10+
"github.com/google/uuid"
11+
"github.com/wpcodevo/golang-postgresql-grpc/config"
12+
db "github.com/wpcodevo/golang-postgresql-grpc/db/sqlc"
13+
"github.com/wpcodevo/golang-postgresql-grpc/models"
14+
"github.com/wpcodevo/golang-postgresql-grpc/utils"
15+
)
16+
17+
type AuthController struct {
18+
db *db.Queries
19+
ctx context.Context
20+
}
21+
22+
func NewAuthController(db *db.Queries, ctx context.Context) *AuthController {
23+
return &AuthController{db, ctx}
24+
}
25+
26+
func (ac *AuthController) SignUpUser(ctx *gin.Context) {
27+
var credentials *db.CreateUserParams
28+
29+
if err := ctx.ShouldBindJSON(&credentials); err != nil {
30+
ctx.JSON(http.StatusBadRequest, err.Error())
31+
return
32+
}
33+
34+
hashedPassword := utils.HashPassword(credentials.Password)
35+
36+
args := &db.CreateUserParams{
37+
Name: credentials.Name,
38+
Email: credentials.Email,
39+
Password: hashedPassword,
40+
Photo: "default.jpeg",
41+
Verified: true,
42+
Role: "user",
43+
UpdatedAt: time.Now(),
44+
}
45+
46+
user, err := ac.db.CreateUser(ctx, *args)
47+
48+
if err != nil {
49+
ctx.JSON(http.StatusBadGateway, err.Error())
50+
return
51+
}
52+
53+
userResponse := models.FilteredResponse(&user)
54+
55+
ctx.JSON(http.StatusCreated, gin.H{"status": "success", "data": gin.H{"user": userResponse}})
56+
}
57+
58+
func (ac *AuthController) SignInUser(ctx *gin.Context) {
59+
var credentials *models.SignInInput
60+
61+
if err := ctx.ShouldBindJSON(&credentials); err != nil {
62+
ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
63+
return
64+
}
65+
66+
user, err := ac.db.GetUserByEmail(ac.ctx, credentials.Email)
67+
if err != nil {
68+
ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": "Invalid email or password"})
69+
return
70+
}
71+
72+
if err := utils.ComparePassword(user.Password, credentials.Password); err != nil {
73+
ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": "Invalid email or password"})
74+
return
75+
}
76+
77+
config, _ := config.LoadConfig(".")
78+
79+
// Generate Tokens
80+
access_token, err := utils.CreateToken(config.AccessTokenExpiresIn, user.ID, config.AccessTokenPrivateKey)
81+
if err != nil {
82+
ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
83+
return
84+
}
85+
86+
refresh_token, err := utils.CreateToken(config.RefreshTokenExpiresIn, user.ID, config.RefreshTokenPrivateKey)
87+
if err != nil {
88+
ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
89+
return
90+
}
91+
92+
ctx.SetCookie("access_token", access_token, config.AccessTokenMaxAge*60, "/", "localhost", false, true)
93+
ctx.SetCookie("refresh_token", refresh_token, config.RefreshTokenMaxAge*60, "/", "localhost", false, true)
94+
ctx.SetCookie("logged_in", "true", config.AccessTokenMaxAge*60, "/", "localhost", false, false)
95+
96+
ctx.JSON(http.StatusOK, gin.H{"status": "success", "access_token": access_token})
97+
}
98+
99+
func (ac *AuthController) RefreshAccessToken(ctx *gin.Context) {
100+
message := "could not refresh access token"
101+
102+
cookie, err := ctx.Cookie("refresh_token")
103+
104+
if err != nil {
105+
ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"status": "fail", "message": message})
106+
return
107+
}
108+
109+
config, _ := config.LoadConfig(".")
110+
111+
sub, err := utils.ValidateToken(cookie, config.RefreshTokenPublicKey)
112+
if err != nil {
113+
ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"status": "fail", "message": err.Error()})
114+
return
115+
}
116+
117+
user, err := ac.db.GetUserById(ac.ctx, uuid.MustParse(fmt.Sprint(sub)))
118+
if err != nil {
119+
ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"status": "fail", "message": "the user belonging to this token no logger exists"})
120+
return
121+
}
122+
123+
access_token, err := utils.CreateToken(config.AccessTokenExpiresIn, user.ID, config.AccessTokenPrivateKey)
124+
if err != nil {
125+
ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"status": "fail", "message": err.Error()})
126+
return
127+
}
128+
129+
ctx.SetCookie("access_token", access_token, config.AccessTokenMaxAge*60, "/", "localhost", false, true)
130+
ctx.SetCookie("logged_in", "true", config.AccessTokenMaxAge*60, "/", "localhost", false, false)
131+
132+
ctx.JSON(http.StatusOK, gin.H{"status": "success", "access_token": access_token})
133+
}
134+
135+
func (ac *AuthController) LogoutUser(ctx *gin.Context) {
136+
ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
137+
ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
138+
ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)
139+
140+
ctx.JSON(http.StatusOK, gin.H{"status": "success"})
141+
}

0 commit comments

Comments
 (0)