chore: init repository

This commit is contained in:
2022-10-06 15:37:28 +02:00
commit 833851f695
38 changed files with 2302 additions and 0 deletions

113
internal/user/database.go Executable file
View File

@@ -0,0 +1,113 @@
package user
import (
"database/sql"
"john/internal/storage/dao"
"john/internal/storage/dao/postgresql"
"github.com/lib/pq"
)
type Database struct {
*postgresql.DatabasePostgreSQL
}
func NewDatabase(db *postgresql.DatabasePostgreSQL) *Database {
return &Database{db}
}
func (db *Database) GetAllUsers() ([]*User, error) {
q := `
SELECT u.id, u.created_at, u.updated_at, u.email
FROM public.user u
`
rows, err := db.Session.Query(q)
if err != nil {
return nil, err
}
defer rows.Close()
us := make([]*User, 0)
for rows.Next() {
u := User{}
err := rows.Scan(&u.ID, &u.CreatedAt, &u.UpdatedAt, &u.Email)
if err != nil {
return nil, err
}
us = append(us, &u)
}
return us, nil
}
func (db *Database) GetUsersByID(id string) (*User, error) {
q := `
SELECT u.id, u.created_at, u.updated_at, u.email
FROM public.user u
WHERE u.id = $1
`
row := db.Session.QueryRow(q, id)
u := User{}
err := row.Scan(&u.ID, &u.CreatedAt, &u.UpdatedAt, &u.Email)
if errPq, ok := err.(*pq.Error); ok {
return nil, postgresql.HandlePgError(errPq)
}
if err == sql.ErrNoRows {
return nil, dao.NewDAOError(dao.ErrTypeNotFound, err)
}
return &u, err
}
func (db *Database) CreateUser(user *User) error {
q := `
INSERT INTO public.user
(email, google_id)
VALUES
($1, $2)
RETURNING id, created_at
`
err := db.Session.
QueryRow(q, user.Email, user.GoogleID).
Scan(&user.ID, &user.CreatedAt)
if errPq, ok := err.(*pq.Error); ok {
return postgresql.HandlePgError(errPq)
}
return err
}
func (db *Database) DeleteUser(id string) error {
q := `
DELETE FROM public.user
WHERE id = $1
`
_, err := db.Session.Exec(q, id)
if errPq, ok := err.(*pq.Error); ok {
return postgresql.HandlePgError(errPq)
}
return err
}
func (db *Database) UpdateUser(user *User) error {
return nil
}
func (db *Database) GetUsersByGoogleID(id string) (*User, error) {
q := `
SELECT u.id, u.created_at, u.updated_at, u.email, u.google_id
FROM public.user u
WHERE u.google_id = $1
`
row := db.Session.QueryRow(q, id)
u := User{}
err := row.Scan(&u.ID, &u.CreatedAt, &u.UpdatedAt, &u.Email, &u.GoogleID)
if errPq, ok := err.(*pq.Error); ok {
return nil, postgresql.HandlePgError(errPq)
}
if err == sql.ErrNoRows {
return nil, dao.NewDAOError(dao.ErrTypeNotFound, err)
}
return &u, err
}

133
internal/user/handler.go Executable file
View File

@@ -0,0 +1,133 @@
package user
import (
"john/handler"
"john/internal/storage/dao/postgresql"
"john/internal/storage/model"
"john/internal/utils"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"google.golang.org/api/oauth2/v2"
)
type Context struct {
service *Service
db *Database
*handler.Context
}
func NewHandler(ctx *handler.Context, db *postgresql.DatabasePostgreSQL) *Context {
database := NewDatabase(db)
service := NewService(database)
return &Context{service: service, db: database, Context: ctx}
}
func (uc *Context) GetAllUsers(c *gin.Context) {
users, err := uc.db.GetAllUsers()
if err != nil {
utils.GetLoggerFromCtx(c).WithError(err).Error("error while getting users")
utils.JSONErrorWithMessage(c.Writer, model.ErrInternalServer, "Error while getting users")
return
}
utils.JSON(c.Writer, http.StatusOK, users)
}
func (hc *Context) ConnectUser(c *gin.Context) {
authorizationHeader := c.GetHeader("Authorization")
authorizationHeaderSplitted := strings.Split(authorizationHeader, " ")
if len(authorizationHeaderSplitted) != 2 {
utils.JSONError(c.Writer, model.ErrBadRequestFormat)
return
}
oauth2Service, err := oauth2.New(&http.Client{})
if oauth2Service == nil {
utils.GetLoggerFromCtx(c).WithError(err).Error(err)
utils.JSONError(c.Writer, model.ErrInternalServer)
return
}
tokenInfoCall := oauth2Service.Tokeninfo()
tokenInfoCall.IdToken(authorizationHeaderSplitted[1])
tokenInfo, err := tokenInfoCall.Do()
if err != nil {
utils.GetLoggerFromCtx(c).WithError(err).Error(err)
utils.JSONError(c.Writer, model.ErrBadRequestFormat)
return
}
user, err := hc.service.GetUserFromGoogleID(tokenInfo.UserId)
if err != nil {
if castedError, ok := err.(*model.APIError); ok {
if castedError.Type == model.ErrNotFound.Type {
user, err := hc.service.CreateUserFromGoogleToken(tokenInfo.UserId, tokenInfo.Email)
if err != nil {
utils.GetLoggerFromCtx(c).WithError(err).Error(err)
utils.JSONError(c.Writer, model.ErrInternalServer)
return
}
utils.JSON(c.Writer, 200, user)
return
}
utils.JSONError(c.Writer, *castedError)
return
}
utils.GetLoggerFromCtx(c).WithError(err).Error(err)
utils.JSONError(c.Writer, model.ErrInternalServer)
return
}
utils.JSON(c.Writer, 200, user)
}
func (hc *Context) CreateUser(c *gin.Context) {
authorizationHeader := c.GetHeader("Authorization")
authorizationHeaderSplitted := strings.Split(authorizationHeader, " ")
if len(authorizationHeaderSplitted) != 2 {
utils.JSONError(c.Writer, model.ErrBadRequestFormat)
return
}
oauth2Service, err := oauth2.New(&http.Client{})
if oauth2Service == nil {
utils.GetLogger().WithError(err).Error(err)
utils.JSONError(c.Writer, model.ErrInternalServer)
return
}
tokenInfoCall := oauth2Service.Tokeninfo()
tokenInfoCall.IdToken(authorizationHeaderSplitted[1])
tokenInfo, err := tokenInfoCall.Do()
if err != nil {
utils.GetLogger().WithError(err).Error(err)
utils.JSONError(c.Writer, model.ErrBadRequestFormat)
return
}
user, err := hc.service.GetUserFromGoogleID(tokenInfo.UserId)
if err != nil {
utils.GetLogger().WithError(err).Error(err)
if castedError, ok := err.(*model.APIError); ok {
if castedError.Type == model.ErrNotFound.Type {
user, err := hc.service.CreateUserFromGoogleToken(tokenInfo.UserId, tokenInfo.Email)
if err != nil {
utils.GetLogger().WithError(err).Error(err)
utils.JSONError(c.Writer, model.ErrInternalServer)
return
}
utils.JSON(c.Writer, http.StatusCreated, user)
return
}
utils.JSONError(c.Writer, *castedError)
return
}
utils.GetLogger().Info(err)
utils.JSONError(c.Writer, model.ErrInternalServer)
return
}
utils.JSON(c.Writer, http.StatusOK, user)
}
func (hc *Context) GetUser(c *gin.Context) {
userID := c.Param("userId")
user, _ := hc.service.GetUserById(userID)
utils.JSON(c.Writer, http.StatusOK, user)
}

17
internal/user/model.go Executable file
View File

@@ -0,0 +1,17 @@
package user
import (
"time"
)
type User struct {
UserEditable
ID string `json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt *time.Time `json:"updatedAt"`
GoogleID string `json:"-"`
}
type UserEditable struct {
Email string `json:"email" validate:"required"`
}

55
internal/user/service.go Normal file
View File

@@ -0,0 +1,55 @@
package user
import (
"john/internal/storage/dao"
"john/internal/storage/model"
)
type Service struct {
db *Database
}
func NewService(database *Database) *Service {
return &Service{db: database}
}
func (s *Service) GetUserById(userId string) (*User, error) {
user, err := s.db.GetUsersByID(userId)
if e, ok := err.(*dao.Error); ok {
switch {
case e.Type == dao.ErrTypeNotFound:
return nil, &model.ErrNotFound
default:
return nil, &model.ErrInternalServer
}
} else if err != nil {
return nil, &model.ErrInternalServer
}
if user == nil {
return nil, &model.ErrNotFound
}
return user, nil
}
func (us *Service) GetUserFromGoogleID(googleUserID string) (*User, error) {
user, err := us.db.GetUsersByGoogleID(googleUserID)
if err != nil {
if castedError, ok := err.(*dao.Error); ok {
switch castedError.Type {
case dao.ErrTypeNotFound:
return nil, &model.ErrNotFound
default:
return nil, &model.ErrInternalServer
}
}
return nil, &model.ErrInternalServer
}
return user, nil
}
func (us *Service) CreateUserFromGoogleToken(id string, email string) (*User, error) {
user := &User{UserEditable: UserEditable{Email: email}, GoogleID: id}
err := us.db.CreateUser(user)
return user, err
}