Skip to content

Commit

Permalink
chore: prevent edit SSO user
Browse files Browse the repository at this point in the history
  • Loading branch information
tructn committed Jun 14, 2024
1 parent 96f7313 commit 471afff
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 14 deletions.
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
DB=postgres://postgres:admin@localhost:5434/racket?sslmode=disable
AUTH0_DOMAIN=
AUTH0_CLIENTID=
AUTH0_CLIENTSECRET=
AUTH0_CLIENTSECRET=
RESEND_API_KEY=re_YuDJPgda_KNvkxxiTAgTvL76JtYpi3qU8
6 changes: 6 additions & 0 deletions di/di.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,27 @@ import (
"github.com/truc9/racket/handler"
"github.com/truc9/racket/logger"
"github.com/truc9/racket/service"
"github.com/truc9/racket/service/email"
"go.uber.org/dig"
)

func Register() *dig.Container {
c := dig.New()

// Infra
c.Provide(db.NewDatabase)
c.Provide(logger.NewLogger)

// Handlers
c.Provide(handler.NewMatchHandler)
c.Provide(handler.NewPlayerHandler)
c.Provide(handler.NewRegHandler)
c.Provide(handler.NewSportCenterHandler)
c.Provide(handler.NewSettingsHandler)

// Services
c.Provide(service.NewSportCenterService)
c.Provide(email.NewResendEmailer)

return c
}
5 changes: 5 additions & 0 deletions dto/email.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dto

type EmailDto struct {
To []string `json:"to"`
}
1 change: 0 additions & 1 deletion frontend/src/screens/matches/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import Page from "../../components/page";
import { useSportCenterValueLabelQuery } from "../../hooks/useQueries";
import { CreateOrUpdateMatchModel } from "../../models";
import { MatchModel } from "./models";
import formatter from "../../common/formatter";
import Currency from "../../components/currency";

const schema = z.object({
Expand Down
39 changes: 37 additions & 2 deletions frontend/src/screens/players/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import {
Skeleton,
Table,
TextInput,
Tooltip,
} from "@mantine/core";
import { useForm, zodResolver } from "@mantine/form";
import { useDisclosure } from "@mantine/hooks";
import { useMutation, useQuery } from "@tanstack/react-query";
import { IoAdd, IoPencil, IoSave, IoTrash } from "react-icons/io5";
import { IoAdd, IoMail, IoPencil, IoSave, IoTrash } from "react-icons/io5";
import { z } from "zod";
import formatter from "../../common/formatter";
import httpService from "../../common/http-service";
import Page from "../../components/page";
import { PlayerSummaryModel, UpdatePlayerModel } from "./models";
import { notifications } from "@mantine/notifications";

const schema = z.object({
id: z.number().nullable(),
Expand Down Expand Up @@ -74,9 +76,25 @@ function Players() {
};

const deleteClick = (model: PlayerSummaryModel) => {
if (model.externalUserId) {
notifications.show({
title: "Important",
message: "Please do not delete user from SSO",
color: "teal",
});
return;
}

deleteMutation.mutate(model);
};

const sendWelcomeEmail = async (model: PlayerSummaryModel) => {
console.log(model);
await httpService.post(`api/v1/players/${model.id}/welcome-email`, {
to: [model.email],
});
};

return (
<>
<Page title="Players Management">
Expand Down Expand Up @@ -123,10 +141,27 @@ function Players() {
)}
</Table.Td>
<Table.Td className="flex items-center justify-end gap-2">
<ActionIcon onClick={() => editClick(item)} size="lg">
<Tooltip label="Welcome Email" position="top">
<ActionIcon
disabled={!item.email}
color="pink"
onClick={() => sendWelcomeEmail(item)}
size="lg"
>
<IoMail />
</ActionIcon>
</Tooltip>

<ActionIcon
onClick={() => editClick(item)}
size="lg"
disabled={!!item.externalUserId}
>
<IoPencil />
</ActionIcon>

<ActionIcon
disabled={!!item.externalUserId}
size="lg"
color="red"
onClick={() => deleteClick(item)}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/gin-contrib/cors v1.7.2
github.com/gin-gonic/gin v1.10.0
github.com/joho/godotenv v1.5.1
github.com/resend/resend-go/v2 v2.9.0
github.com/samber/lo v1.39.0
go.uber.org/dig v1.17.1
go.uber.org/zap v1.27.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/resend/resend-go/v2 v2.9.0 h1:e5pCfMiek1JOuhn533t5ipZbuA+nWo+jxMn4h62nfzY=
github.com/resend/resend-go/v2 v2.9.0/go.mod h1:ihnxc7wPpSgans8RV8d8dIF4hYWVsqMK5KxXAr9LIos=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
Expand Down
39 changes: 29 additions & 10 deletions handler/player.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
package handler

import (
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"github.com/truc9/racket/domain"
"github.com/truc9/racket/dto"
"github.com/truc9/racket/params"
"github.com/truc9/racket/service/email"
"go.uber.org/zap"
"gorm.io/gorm"
)

type PlayerHandler struct {
db *gorm.DB
logger *zap.SugaredLogger
db *gorm.DB
logger *zap.SugaredLogger
emailer email.Emailer
}

func NewPlayerHandler(db *gorm.DB, logger *zap.SugaredLogger) *PlayerHandler {
func NewPlayerHandler(db *gorm.DB, logger *zap.SugaredLogger, emailer email.Emailer) *PlayerHandler {
return &PlayerHandler{
db: db,
logger: logger,
db: db,
logger: logger,
emailer: emailer,
}
}

func (h PlayerHandler) Create(c *gin.Context) {
func (h *PlayerHandler) Create(c *gin.Context) {
dto := dto.PlayerDto{}
var err error
if err = c.BindJSON(&dto); err != nil {
Expand All @@ -39,13 +43,13 @@ func (h PlayerHandler) Create(c *gin.Context) {
c.JSON(http.StatusCreated, p)
}

func (h PlayerHandler) GetAll(c *gin.Context) {
func (h *PlayerHandler) GetAll(c *gin.Context) {
var result []domain.Player
h.db.Order("first_name ASC").Find(&result)
c.JSON(http.StatusOK, result)
}

func (h PlayerHandler) GetExternalUserAttendantRequests(c *gin.Context) {
func (h *PlayerHandler) GetExternalUserAttendantRequests(c *gin.Context) {
var result []dto.PlayerAttendantRequestDto
externalUserId := params.Get(c, "externalUserId")
h.db.Raw(`
Expand All @@ -61,7 +65,7 @@ func (h PlayerHandler) GetExternalUserAttendantRequests(c *gin.Context) {
c.JSON(http.StatusOK, result)
}

func (h PlayerHandler) Update(c *gin.Context) {
func (h *PlayerHandler) Update(c *gin.Context) {
var model dto.PlayerDto
id := params.Get(c, "playerId")
if err := c.BindJSON(&model); err != nil {
Expand All @@ -77,8 +81,23 @@ func (h PlayerHandler) Update(c *gin.Context) {
c.JSON(http.StatusOK, p)
}

func (h PlayerHandler) Delete(c *gin.Context) {
func (h *PlayerHandler) Delete(c *gin.Context) {
id := params.Get(c, "playerId")
h.db.Unscoped().Delete(&domain.Player{}, id)
c.Status(http.StatusOK)
}

func (h *PlayerHandler) SendWelcomeEmail(c *gin.Context) {
dto := &dto.EmailDto{}
c.BindJSON(dto)

playerId := params.Get(c, "playerId")
var name string
h.db.Find(&domain.Player{}, playerId).Select("first_name", &name)

_, err := h.emailer.Send("[email protected]", dto.To, "Welcome", fmt.Sprintf("<h1>Welcome %s to Racket!</h1>", name))
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
}
c.Status(http.StatusOK)
}
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func main() {
v1.GET("/players", handler.GetAll)
v1.GET("/players/external-users/:externalUserId/attendant-requests", handler.GetExternalUserAttendantRequests)
v1.POST("/players", handler.Create)
v1.POST("/players/:playerId/welcome-email", handler.SendWelcomeEmail)
v1.DELETE("/players/:playerId", handler.Delete)
v1.PUT("/players/:playerId", handler.Update)
})
Expand Down
5 changes: 5 additions & 0 deletions service/email/emailer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package email

type Emailer interface {
Send(from string, to []string, subject, body string) (*EmailerRes, error)
}
5 changes: 5 additions & 0 deletions service/email/emailer_res.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package email

type EmailerRes struct {
Id string `json:"id"`
}
47 changes: 47 additions & 0 deletions service/email/resend_emailer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package email

import (
"fmt"
"log"
"os"

"github.com/joho/godotenv"
resend "github.com/resend/resend-go/v2"
)

type ResendEmailer struct {
}

func NewResendEmailer() Emailer {
return &ResendEmailer{}
}

func (re *ResendEmailer) Send(from string, to []string, subject, body string) (*EmailerRes, error) {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}

API_KEY := os.Getenv("RESEND_API_KEY")

client := resend.NewClient(API_KEY)

params := &resend.SendEmailRequest{
From: "The Racket <[email protected]>",
To: to,
Html: body,
Subject: subject,
}

sent, err := client.Emails.Send(params)
if err != nil {
fmt.Println(err.Error())
return nil, err
}

fmt.Println(sent.Id)

return &EmailerRes{
Id: sent.Id,
}, err
}

0 comments on commit 471afff

Please sign in to comment.