Compare commits
No commits in common. "8f10fbfba1d49ab6c7d994becc83e842950daa30" and "4981ef7f814500e5c6d70f9c19615bef8e282926" have entirely different histories.
8f10fbfba1
...
4981ef7f81
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,7 +10,6 @@
|
|||||||
*.dylib
|
*.dylib
|
||||||
go-cook
|
go-cook
|
||||||
*.db
|
*.db
|
||||||
*.env
|
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
type UserDto struct {
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
type UserEntity struct {
|
|
||||||
Id int
|
|
||||||
CreatedAt time.Time
|
|
||||||
LastUpdated time.Time
|
|
||||||
Name string
|
|
||||||
Hash string
|
|
||||||
Scopes string
|
|
||||||
}
|
|
||||||
|
|
||||||
type RecipeEntity struct {
|
|
||||||
Id int32
|
|
||||||
CreatedAt time.Time
|
|
||||||
LastUpdated time.Time
|
|
||||||
Title string
|
|
||||||
Thumbnail string
|
|
||||||
Content string
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
type EnvConfig struct {
|
|
||||||
AdminToken string
|
|
||||||
JwtSecret string
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
type HelloBodyRequest struct {
|
|
||||||
Name string `json:"name" validate:"required"`
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
type ErrorResponse struct {
|
|
||||||
HttpCode int `json:"code"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HelloWhoResponse struct {
|
|
||||||
Success bool `json:"success"`
|
|
||||||
Error string `json:"error"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
const (
|
|
||||||
ScopeAll = "all"
|
|
||||||
ScopeRecipeRead = "recipe:read"
|
|
||||||
ScopeRecipeCreate = "recipe:create"
|
|
||||||
ScopeRecipeDelete = "recipe:delete"
|
|
||||||
)
|
|
@ -2,10 +2,9 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"go-cook/api/domain"
|
"go-cook/api/models"
|
||||||
"go-cook/api/repositories"
|
"go-cook/api/repositories"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
@ -16,57 +15,19 @@ const (
|
|||||||
ErrJwtMissing = "auth token is missing"
|
ErrJwtMissing = "auth token is missing"
|
||||||
ErrJwtClaimsMissing = "claims missing on token"
|
ErrJwtClaimsMissing = "claims missing on token"
|
||||||
ErrJwtExpired = "auth token has expired"
|
ErrJwtExpired = "auth token has expired"
|
||||||
ErrJwtScopeMissing = "required scope is missing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type JwtToken struct {
|
type JwtToken struct {
|
||||||
Exp time.Time `json:"exp"`
|
Exp time.Time `json:"exp"`
|
||||||
Iss string `json:"iss"`
|
|
||||||
Authorized bool `json:"authorized"`
|
Authorized bool `json:"authorized"`
|
||||||
UserName string `json:"username"`
|
UserName string `json:"username"`
|
||||||
Scopes []string `json:"scopes"`
|
Token string `json:"token"`
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j JwtToken) IsValid(scope string) error {
|
func generateJwt(username string) (string, error) {
|
||||||
err := j.hasExpired()
|
//TODO use env here
|
||||||
if err != nil {
|
secret := []byte("ThisIsABadSecretDontReallyUseThis")
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = j.hasScope(scope)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j JwtToken) hasExpired() error {
|
|
||||||
// Check to see if the token has expired
|
|
||||||
hasExpired := j.Exp.Compare(time.Now())
|
|
||||||
if hasExpired == -1 {
|
|
||||||
return errors.New(ErrJwtExpired)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j JwtToken) hasScope(scope string) error {
|
|
||||||
// they have the scope to access everything, so let them pass.
|
|
||||||
if strings.Contains(domain.ScopeAll, scope) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range j.Scopes {
|
|
||||||
if strings.Contains(s, scope) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errors.New(ErrJwtScopeMissing)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) generateJwt(username string) (string, error) {
|
|
||||||
secret := []byte(h.Config.JwtSecret)
|
|
||||||
|
|
||||||
token := jwt.New(jwt.SigningMethodHS256)
|
token := jwt.New(jwt.SigningMethodHS256)
|
||||||
claims := token.Claims.(jwt.MapClaims)
|
claims := token.Claims.(jwt.MapClaims)
|
||||||
@ -74,10 +35,6 @@ func (h *Handler) generateJwt(username string) (string, error) {
|
|||||||
claims["authorized"] = true
|
claims["authorized"] = true
|
||||||
claims["username"] = username
|
claims["username"] = username
|
||||||
|
|
||||||
var scopes []string
|
|
||||||
scopes = append(scopes, domain.ScopeRecipeRead)
|
|
||||||
claims["scopes"] = scopes
|
|
||||||
|
|
||||||
tokenString, err := token.SignedString(secret)
|
tokenString, err := token.SignedString(secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -93,7 +50,7 @@ func (h *Handler) AuthRegister(c echo.Context) error {
|
|||||||
// if we have an err, validate that if its not user not found.
|
// if we have an err, validate that if its not user not found.
|
||||||
// if the user is not found, we can use that name
|
// if the user is not found, we can use that name
|
||||||
if err.Error() != repositories.ErrUserNotFound {
|
if err.Error() != repositories.ErrUserNotFound {
|
||||||
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
|
return c.JSON(http.StatusInternalServerError, models.ErrorResponse{
|
||||||
HttpCode: http.StatusInternalServerError,
|
HttpCode: http.StatusInternalServerError,
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
})
|
})
|
||||||
@ -103,7 +60,7 @@ func (h *Handler) AuthRegister(c echo.Context) error {
|
|||||||
password := c.QueryParam("password")
|
password := c.QueryParam("password")
|
||||||
err = h.UserService.CheckPasswordForRequirements(password)
|
err = h.UserService.CheckPasswordForRequirements(password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
|
return c.JSON(http.StatusInternalServerError, models.ErrorResponse{
|
||||||
HttpCode: http.StatusInternalServerError,
|
HttpCode: http.StatusInternalServerError,
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
})
|
})
|
||||||
@ -111,7 +68,7 @@ func (h *Handler) AuthRegister(c echo.Context) error {
|
|||||||
|
|
||||||
_, err = h.userRepo.Create(username, password)
|
_, err = h.userRepo.Create(username, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
|
return c.JSON(http.StatusInternalServerError, models.ErrorResponse{
|
||||||
HttpCode: http.StatusInternalServerError,
|
HttpCode: http.StatusInternalServerError,
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
})
|
})
|
||||||
@ -136,7 +93,7 @@ func (h *Handler) AuthLogin(c echo.Context) error {
|
|||||||
return c.JSON(http.StatusInternalServerError, err)
|
return c.JSON(http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := h.generateJwt(username)
|
token, err := generateJwt(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, err)
|
return c.JSON(http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
@ -144,10 +101,6 @@ func (h *Handler) AuthLogin(c echo.Context) error {
|
|||||||
return c.JSON(http.StatusOK, token)
|
return c.JSON(http.StatusOK, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) AddScope(c echo.Context) error {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) RefreshJwtToken(c echo.Context) error {
|
func (h *Handler) RefreshJwtToken(c echo.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -165,5 +118,11 @@ func (h *Handler) getJwtToken(c echo.Context) (JwtToken, error) {
|
|||||||
return JwtToken{}, errors.New(ErrJwtClaimsMissing)
|
return JwtToken{}, errors.New(ErrJwtClaimsMissing)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check to see if the token has expired
|
||||||
|
hasExpired := claims.Exp.Compare(time.Now())
|
||||||
|
if hasExpired == -1 {
|
||||||
|
return JwtToken{}, errors.New(ErrJwtExpired)
|
||||||
|
}
|
||||||
|
|
||||||
return *claims, nil
|
return *claims, nil
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,20 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go-cook/api/domain"
|
"go-cook/api/models"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type HelloWhoResponse struct {
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Error string `error:"error"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handler) DemoHello(c echo.Context) error {
|
func (h *Handler) DemoHello(c echo.Context) error {
|
||||||
return c.JSON(http.StatusOK, domain.HelloWhoResponse{
|
return c.JSON(http.StatusOK, HelloWhoResponse{
|
||||||
Success: true,
|
Success: true,
|
||||||
Message: "Hello world!",
|
Message: "Hello world!",
|
||||||
})
|
})
|
||||||
@ -17,23 +23,27 @@ func (h *Handler) DemoHello(c echo.Context) error {
|
|||||||
|
|
||||||
func (h *Handler) HelloWho(c echo.Context) error {
|
func (h *Handler) HelloWho(c echo.Context) error {
|
||||||
name := c.Param("who")
|
name := c.Param("who")
|
||||||
return c.JSON(http.StatusOK, domain.HelloWhoResponse{
|
return c.JSON(http.StatusOK, HelloWhoResponse{
|
||||||
Success: true,
|
Success: true,
|
||||||
Message: fmt.Sprintf("Hello, %s", name),
|
Message: fmt.Sprintf("Hello, %s", name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HelloBodyRequest struct {
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handler) HelloBody(c echo.Context) error {
|
func (h *Handler) HelloBody(c echo.Context) error {
|
||||||
request := domain.HelloBodyRequest{}
|
request := HelloBodyRequest{}
|
||||||
err := (&echo.DefaultBinder{}).BindBody(c, &request)
|
err := (&echo.DefaultBinder{}).BindBody(c, &request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusBadRequest, domain.HelloWhoResponse{
|
return c.JSON(http.StatusBadRequest, HelloWhoResponse{
|
||||||
Success: false,
|
Success: false,
|
||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, domain.HelloWhoResponse{
|
return c.JSON(http.StatusOK, HelloWhoResponse{
|
||||||
Success: true,
|
Success: true,
|
||||||
Message: fmt.Sprintf("Hello, %s", request.Name),
|
Message: fmt.Sprintf("Hello, %s", request.Name),
|
||||||
})
|
})
|
||||||
@ -42,12 +52,10 @@ func (h *Handler) HelloBody(c echo.Context) error {
|
|||||||
func (h *Handler) ProtectedRoute(c echo.Context) error {
|
func (h *Handler) ProtectedRoute(c echo.Context) error {
|
||||||
token, err := h.getJwtToken(c)
|
token, err := h.getJwtToken(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.ReturnUnauthorizedResponse(c, err.Error())
|
return c.JSON(http.StatusForbidden, models.ErrorResponse{
|
||||||
}
|
HttpCode: http.StatusForbidden,
|
||||||
|
Message: err.Error(),
|
||||||
err = token.IsValid(domain.ScopeRecipeRead)
|
})
|
||||||
if err != nil {
|
|
||||||
h.ReturnUnauthorizedResponse(c, ErrJwtScopeMissing)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, token)
|
return c.JSON(http.StatusOK, token)
|
||||||
|
@ -2,10 +2,8 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"go-cook/api/domain"
|
|
||||||
"go-cook/api/repositories"
|
"go-cook/api/repositories"
|
||||||
"go-cook/api/services"
|
"go-cook/api/services"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
echojwt "github.com/labstack/echo-jwt/v4"
|
echojwt "github.com/labstack/echo-jwt/v4"
|
||||||
@ -13,16 +11,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
Config domain.EnvConfig
|
|
||||||
|
|
||||||
UserService services.UserService
|
UserService services.UserService
|
||||||
userRepo repositories.IUserTable
|
userRepo repositories.IUserTable
|
||||||
recipeRepo repositories.IRecipeTable
|
recipeRepo repositories.IRecipeTable
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(conn *sql.DB, cfg domain.EnvConfig) *Handler {
|
func NewHandler(conn *sql.DB) *Handler {
|
||||||
return &Handler{
|
return &Handler{
|
||||||
Config: cfg,
|
|
||||||
UserService: services.NewUserService(conn),
|
UserService: services.NewUserService(conn),
|
||||||
userRepo: repositories.NewUserRepository(conn),
|
userRepo: repositories.NewUserRepository(conn),
|
||||||
recipeRepo: repositories.NewRecipeRepository(conn),
|
recipeRepo: repositories.NewRecipeRepository(conn),
|
||||||
@ -34,7 +29,7 @@ func (h *Handler) Register(v1 *echo.Group) {
|
|||||||
NewClaimsFunc: func(c echo.Context) jwt.Claims {
|
NewClaimsFunc: func(c echo.Context) jwt.Claims {
|
||||||
return new(JwtToken)
|
return new(JwtToken)
|
||||||
},
|
},
|
||||||
SigningKey: []byte(h.Config.JwtSecret),
|
SigningKey: []byte("ThisIsABadSecretDontReallyUseThis"),
|
||||||
}
|
}
|
||||||
|
|
||||||
v1.POST("/login", h.AuthLogin)
|
v1.POST("/login", h.AuthLogin)
|
||||||
@ -58,10 +53,3 @@ func (h *Handler) Register(v1 *echo.Group) {
|
|||||||
//users.POST("/login", h.LoginUser)
|
//users.POST("/login", h.LoginUser)
|
||||||
//users.POST("/update/password", h.UpdatePassword)
|
//users.POST("/update/password", h.UpdatePassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) ReturnUnauthorizedResponse(c echo.Context, message string) error {
|
|
||||||
return c.JSON(http.StatusUnauthorized, domain.ErrorResponse{
|
|
||||||
HttpCode: http.StatusUnauthorized,
|
|
||||||
Message: message,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
-- +goose Up
|
|
||||||
-- +goose StatementBegin
|
|
||||||
SELECT 'up SQL query';
|
|
||||||
ALTER Table USERS ADD Scopes TEXT;
|
|
||||||
-- +goose StatementEnd
|
|
||||||
-- +goose Down
|
|
||||||
-- +goose StatementBegin
|
|
||||||
SELECT 'down SQL query';
|
|
||||||
ALTER TABLE USERS DROP COLUMN Scopes;
|
|
||||||
-- +goose StatementEnd
|
|
12
api/models/recipe.go
Normal file
12
api/models/recipe.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type RecipeModel struct {
|
||||||
|
Id int32
|
||||||
|
Title string
|
||||||
|
Thumbnail string
|
||||||
|
Content string
|
||||||
|
CreatedAt time.Time
|
||||||
|
LastUpdated time.Time
|
||||||
|
}
|
6
api/models/std.go
Normal file
6
api/models/std.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type ErrorResponse struct {
|
||||||
|
HttpCode int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
15
api/models/users.go
Normal file
15
api/models/users.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type UserModel struct {
|
||||||
|
Id int
|
||||||
|
Name string
|
||||||
|
Hash string
|
||||||
|
CreatedAt time.Time
|
||||||
|
LastUpdated time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserDto struct {
|
||||||
|
|
||||||
|
}
|
@ -3,14 +3,14 @@ package repositories
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"go-cook/api/domain"
|
"go-cook/api/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IRecipeTable interface {
|
type IRecipeTable interface {
|
||||||
Create(domain.RecipeEntity) error
|
Create(models.RecipeModel) error
|
||||||
List() ([]domain.RecipeEntity, error)
|
List() ([]models.RecipeModel, error)
|
||||||
Get(id int) (domain.RecipeEntity, error)
|
Get(id int) (models.RecipeModel, error)
|
||||||
Update(id int, entity domain.RecipeEntity) error
|
Update(id int, entity models.RecipeModel) error
|
||||||
Delete(id int) error
|
Delete(id int) error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,19 +24,19 @@ func NewRecipeRepository(client *sql.DB) RecipeRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr RecipeRepository) Create(domain.RecipeEntity) error {
|
func (rr RecipeRepository) Create(models.RecipeModel) error {
|
||||||
return errors.New("not implemented")
|
return errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr RecipeRepository) List() ([]domain.RecipeEntity, error) {
|
func (rr RecipeRepository) List() ([]models.RecipeModel, error) {
|
||||||
return []domain.RecipeEntity{}, errors.New("not implemented")
|
return []models.RecipeModel{}, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr RecipeRepository) Get(id int) (domain.RecipeEntity, error) {
|
func (rr RecipeRepository) Get(id int) (models.RecipeModel, error) {
|
||||||
return domain.RecipeEntity{}, errors.New("not implemented")
|
return models.RecipeModel{}, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr RecipeRepository) Update(id int, entity domain.RecipeEntity) error {
|
func (rr RecipeRepository) Update(id int, entity models.RecipeModel) error {
|
||||||
return errors.New("not implemented")
|
return errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go-cook/api/domain"
|
"go-cook/api/models"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/huandu/go-sqlbuilder"
|
"github.com/huandu/go-sqlbuilder"
|
||||||
@ -17,12 +17,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type IUserTable interface {
|
type IUserTable interface {
|
||||||
GetByName(name string) (domain.UserEntity, error)
|
GetByName(name string) (models.UserModel, error)
|
||||||
Create(name, password string) (int64, error)
|
Create(name, password string) (int64, error)
|
||||||
Update(id int, entity domain.UserEntity) error
|
Update(id int, entity models.UserModel) error
|
||||||
UpdatePassword(name, password string) error
|
UpdatePassword(name, password string) error
|
||||||
CheckUserHash(name, password string) error
|
CheckUserHash(name, password string) error
|
||||||
AddScope(name, scope string) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new instance of UserRepository with the bound sql
|
// Creates a new instance of UserRepository with the bound sql
|
||||||
@ -36,7 +35,7 @@ type UserRepository struct {
|
|||||||
connection *sql.DB
|
connection *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur UserRepository) GetByName(name string) (domain.UserEntity, error) {
|
func (ur UserRepository) GetByName(name string) (models.UserModel, error) {
|
||||||
builder := sqlbuilder.NewSelectBuilder()
|
builder := sqlbuilder.NewSelectBuilder()
|
||||||
builder.Select("*").From("users").Where(
|
builder.Select("*").From("users").Where(
|
||||||
builder.E("Name", name),
|
builder.E("Name", name),
|
||||||
@ -45,12 +44,12 @@ func (ur UserRepository) GetByName(name string) (domain.UserEntity, error) {
|
|||||||
|
|
||||||
rows, err := ur.connection.Query(query, args...)
|
rows, err := ur.connection.Query(query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.UserEntity{}, err
|
return models.UserModel{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := ur.processRows(rows)
|
data := ur.processRows(rows)
|
||||||
if len(data) == 0 {
|
if (len(data) == 0) {
|
||||||
return domain.UserEntity{}, errors.New(ErrUserNotFound)
|
return models.UserModel{}, errors.New(ErrUserNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
return data[0], nil
|
return data[0], nil
|
||||||
@ -78,7 +77,7 @@ func (ur UserRepository) Create(name, password string) (int64, error) {
|
|||||||
return 1, nil
|
return 1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur UserRepository) Update(id int, entity domain.UserEntity) error {
|
func (ur UserRepository) Update(id int, entity models.UserModel) error {
|
||||||
return errors.New("not implemented")
|
return errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,26 +109,8 @@ func (ur UserRepository) CheckUserHash(name, password string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur UserRepository) AddScope(name, scope string) error {
|
func (ur UserRepository) processRows(rows *sql.Rows) []models.UserModel {
|
||||||
builder := sqlbuilder.NewUpdateBuilder()
|
items := []models.UserModel{}
|
||||||
builder.Update("users")
|
|
||||||
builder.Set (
|
|
||||||
builder.Assign("Scopes", scope),
|
|
||||||
)
|
|
||||||
builder.Where(
|
|
||||||
builder.Equal("Name", name),
|
|
||||||
)
|
|
||||||
query, args := builder.Build()
|
|
||||||
|
|
||||||
_, err := ur.connection.Exec(query, args...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ur UserRepository) processRows(rows *sql.Rows) []domain.UserEntity {
|
|
||||||
items := []domain.UserEntity{}
|
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var id int
|
var id int
|
||||||
@ -137,17 +118,15 @@ func (ur UserRepository) processRows(rows *sql.Rows) []domain.UserEntity {
|
|||||||
var hash string
|
var hash string
|
||||||
var createdAt time.Time
|
var createdAt time.Time
|
||||||
var lastUpdated time.Time
|
var lastUpdated time.Time
|
||||||
var scopes string
|
err := rows.Scan(&id, &name, &hash, &createdAt, &lastUpdated)
|
||||||
err := rows.Scan(&id, &name, &hash, &createdAt, &lastUpdated, &scopes)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
items = append(items, domain.UserEntity{
|
items = append(items, models.UserModel{
|
||||||
Id: id,
|
Id: id,
|
||||||
Name: name,
|
Name: name,
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
Scopes: scopes,
|
|
||||||
CreatedAt: createdAt,
|
CreatedAt: createdAt,
|
||||||
LastUpdated: lastUpdated,
|
LastUpdated: lastUpdated,
|
||||||
})
|
})
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package services
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-cook/api/domain"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewEnvConfig() domain.EnvConfig {
|
|
||||||
err := godotenv.Load()
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return domain.EnvConfig{
|
|
||||||
AdminToken: os.Getenv("AdminToken"),
|
|
||||||
JwtSecret: os.Getenv("JwtSecret"),
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ package services
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"go-cook/api/domain"
|
"go-cook/api/models"
|
||||||
"go-cook/api/repositories"
|
"go-cook/api/repositories"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -36,6 +36,12 @@ func (us UserService) DoesUserExist(username string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (us UserService) DoesPasswordMatchHash(username, password string) error {
|
func (us UserService) DoesPasswordMatchHash(username, password string) error {
|
||||||
|
//passwordBytes := []byte(password)
|
||||||
|
//hash, err := bcrypt.GenerateFromPassword(passwordBytes, bcrypt.DefaultCost)
|
||||||
|
//if err != nil {
|
||||||
|
// return err
|
||||||
|
//}
|
||||||
|
|
||||||
model, err := us.GetUser(username)
|
model, err := us.GetUser(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -49,18 +55,18 @@ func (us UserService) DoesPasswordMatchHash(username, password string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us UserService) GetUser(username string) (domain.UserEntity, error) {
|
func (us UserService) GetUser(username string) (models.UserModel, error) {
|
||||||
return us.repo.GetByName(username)
|
return us.repo.GetByName(username)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us UserService) CreateNewUser(name, password string) (domain.UserEntity, error) {
|
func (us UserService) CreateNewUser(name, password string) (models.UserModel, error) {
|
||||||
err := us.CheckPasswordForRequirements(password)
|
err := us.CheckPasswordForRequirements(password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.UserEntity{}, err
|
return models.UserModel{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
us.repo.Create(name, password)
|
us.repo.Create(name, password)
|
||||||
return domain.UserEntity{}, nil
|
return models.UserModel{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us UserService) CheckPasswordForRequirements(password string) error {
|
func (us UserService) CheckPasswordForRequirements(password string) error {
|
||||||
|
1
go.mod
1
go.mod
@ -25,7 +25,6 @@ require (
|
|||||||
github.com/google/uuid v1.5.0 // indirect
|
github.com/google/uuid v1.5.0 // indirect
|
||||||
github.com/huandu/go-sqlbuilder v1.25.0 // indirect
|
github.com/huandu/go-sqlbuilder v1.25.0 // indirect
|
||||||
github.com/huandu/xstrings v1.3.2 // indirect
|
github.com/huandu/xstrings v1.3.2 // indirect
|
||||||
github.com/joho/godotenv v1.5.1 // indirect
|
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/labstack/echo-jwt/v4 v4.2.0 // indirect
|
github.com/labstack/echo-jwt/v4 v4.2.0 // indirect
|
||||||
github.com/labstack/echo/v4 v4.11.4 // indirect
|
github.com/labstack/echo/v4 v4.11.4 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -43,8 +43,6 @@ github.com/huandu/go-sqlbuilder v1.25.0 h1:h1l+6CqeCviPJCnkEZoRGNdfZ5RO9BKMvG3A+
|
|||||||
github.com/huandu/go-sqlbuilder v1.25.0/go.mod h1:nUVmMitjOmn/zacMLXT0d3Yd3RHoO2K+vy906JzqxMI=
|
github.com/huandu/go-sqlbuilder v1.25.0/go.mod h1:nUVmMitjOmn/zacMLXT0d3Yd3RHoO2K+vy906JzqxMI=
|
||||||
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
||||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
|
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
|
||||||
|
5
main.go
5
main.go
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
v1 "go-cook/api/handlers/v1"
|
v1 "go-cook/api/handlers/v1"
|
||||||
"go-cook/api/services"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@ -22,8 +21,6 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := services.NewEnvConfig()
|
|
||||||
|
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.Validator = &CustomValidator{
|
e.Validator = &CustomValidator{
|
||||||
validator: validator.New(),
|
validator: validator.New(),
|
||||||
@ -33,7 +30,7 @@ func main() {
|
|||||||
e.Pre(middleware.Recover())
|
e.Pre(middleware.Recover())
|
||||||
|
|
||||||
v1Group := e.Group("/api/v1")
|
v1Group := e.Group("/api/v1")
|
||||||
v1Api := v1.NewHandler(db, cfg)
|
v1Api := v1.NewHandler(db)
|
||||||
v1Api.Register(v1Group)
|
v1Api.Register(v1Group)
|
||||||
|
|
||||||
e.Logger.Fatal(e.Start(":1323"))
|
e.Logger.Fatal(e.Start(":1323"))
|
||||||
|
Loading…
Reference in New Issue
Block a user