修复登录失效后跳转,发送邮件逻辑
This commit is contained in:
parent
500d2cc223
commit
ed4725e179
@ -35,6 +35,7 @@ import SecurityIcon from '@mui/icons-material/Security';
|
|||||||
import SettingsIcon from '@mui/icons-material/Settings';
|
import SettingsIcon from '@mui/icons-material/Settings';
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import GroupIcon from '@mui/icons-material/Group';
|
import GroupIcon from '@mui/icons-material/Group';
|
||||||
|
import { ApiErr } from '@/apis/error';
|
||||||
|
|
||||||
const drawerWidth = 240;
|
const drawerWidth = 240;
|
||||||
const DrawerOpen = atom(false)
|
const DrawerOpen = atom(false)
|
||||||
@ -211,12 +212,16 @@ const MyDrawer = function MyDrawer() {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isLg = useMediaQuery(theme.breakpoints.up('lg'))
|
const isLg = useMediaQuery(theme.breakpoints.up('lg'))
|
||||||
const [open, setOpen] = useAtom(DrawerOpen)
|
const [open, setOpen] = useAtom(DrawerOpen)
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const userinfo = useRequest(() => userInfo(nowToken), {
|
const userinfo = useRequest(() => userInfo(nowToken), {
|
||||||
refreshDeps: [nowToken],
|
refreshDeps: [nowToken],
|
||||||
cacheKey: "/api/v1/user" + nowToken,
|
cacheKey: "/api/v1/user" + nowToken,
|
||||||
staleTime: 60000,
|
staleTime: 60000,
|
||||||
onError: e => {
|
onError: e => {
|
||||||
|
if (e instanceof ApiErr && e.code == 5) {
|
||||||
|
navigate("/login")
|
||||||
|
}
|
||||||
console.warn(e)
|
console.warn(e)
|
||||||
setErr(String(e))
|
setErr(String(e))
|
||||||
},
|
},
|
||||||
|
1
go.mod
1
go.mod
@ -38,6 +38,7 @@ require (
|
|||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/wneessen/go-mail v0.4.0 // indirect
|
||||||
github.com/zclconf/go-cty v1.8.0 // indirect
|
github.com/zclconf/go-cty v1.8.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
|
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
|
||||||
golang.org/x/mod v0.10.0 // indirect
|
golang.org/x/mod v0.10.0 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -97,6 +97,8 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
|
|||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
||||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||||
|
github.com/wneessen/go-mail v0.4.0 h1:Oo4HLIV8My7G9JuZkoOX6eipXQD+ACvIqURYeIzUc88=
|
||||||
|
github.com/wneessen/go-mail v0.4.0/go.mod h1:zxOlafWCP/r6FEhAaRgH4IC1vg2YXxO0Nar9u0IScZ8=
|
||||||
github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA=
|
github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA=
|
||||||
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
|
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
9
handle/email.go
Normal file
9
handle/email.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package handle
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
func (h *Handel) SendVerifyCode() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -15,21 +15,25 @@ import (
|
|||||||
"github.com/xmdhs/authlib-skin/config"
|
"github.com/xmdhs/authlib-skin/config"
|
||||||
"github.com/xmdhs/authlib-skin/model"
|
"github.com/xmdhs/authlib-skin/model"
|
||||||
"github.com/xmdhs/authlib-skin/service"
|
"github.com/xmdhs/authlib-skin/service"
|
||||||
|
"github.com/xmdhs/authlib-skin/service/email"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handel struct {
|
type Handel struct {
|
||||||
webService *service.WebService
|
webService *service.WebService
|
||||||
validate *validator.Validate
|
validate *validator.Validate
|
||||||
config config.Config
|
emailService *email.Email
|
||||||
logger *slog.Logger
|
config config.Config
|
||||||
|
logger *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandel(webService *service.WebService, validate *validator.Validate, config config.Config, logger *slog.Logger) *Handel {
|
func NewHandel(webService *service.WebService, validate *validator.Validate,
|
||||||
|
config config.Config, logger *slog.Logger, email *email.Email) *Handel {
|
||||||
return &Handel{
|
return &Handel{
|
||||||
webService: webService,
|
webService: webService,
|
||||||
validate: validate,
|
validate: validate,
|
||||||
config: config,
|
config: config,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
emailService: email,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,12 +12,13 @@ import (
|
|||||||
"github.com/xmdhs/authlib-skin/handle/yggdrasil"
|
"github.com/xmdhs/authlib-skin/handle/yggdrasil"
|
||||||
"github.com/xmdhs/authlib-skin/server/route"
|
"github.com/xmdhs/authlib-skin/server/route"
|
||||||
"github.com/xmdhs/authlib-skin/service"
|
"github.com/xmdhs/authlib-skin/service"
|
||||||
|
"github.com/xmdhs/authlib-skin/service/email"
|
||||||
yggdrasilS "github.com/xmdhs/authlib-skin/service/yggdrasil"
|
yggdrasilS "github.com/xmdhs/authlib-skin/service/yggdrasil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitializeRoute(ctx context.Context, c config.Config) (*http.Server, func(), error) {
|
func InitializeRoute(ctx context.Context, c config.Config) (*http.Server, func(), error) {
|
||||||
panic(wire.Build(Set, route.NewRoute, NewSlog,
|
panic(wire.Build(Set, route.NewRoute, NewSlog,
|
||||||
NewServer, handle.NewHandel, yggdrasil.NewYggdrasil,
|
NewServer, handle.NewHandel, yggdrasil.NewYggdrasil,
|
||||||
service.NewWebService, yggdrasilS.NewYggdrasil,
|
service.NewWebService, yggdrasilS.NewYggdrasil, email.NewEmail,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
125
service/email/email.go
Normal file
125
service/email/email.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package email
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/rsa"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"github.com/wneessen/go-mail"
|
||||||
|
"github.com/xmdhs/authlib-skin/config"
|
||||||
|
"github.com/xmdhs/authlib-skin/db/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EmailConfig struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
SSL bool
|
||||||
|
Name string
|
||||||
|
Pass string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Email struct {
|
||||||
|
emailConfig []EmailConfig
|
||||||
|
pri *rsa.PrivateKey
|
||||||
|
config config.Config
|
||||||
|
cache cache.Cache
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEmail(emailConfig []EmailConfig, pri *rsa.PrivateKey, config config.Config, cache cache.Cache) Email {
|
||||||
|
return Email{
|
||||||
|
emailConfig: emailConfig,
|
||||||
|
pri: pri,
|
||||||
|
config: config,
|
||||||
|
cache: cache,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Email) getRandEmailUser() EmailConfig {
|
||||||
|
i := rand.Intn(len(e.emailConfig))
|
||||||
|
return e.emailConfig[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Email) SendEmail(ctx context.Context, to string, subject, body string) error {
|
||||||
|
u := e.getRandEmailUser()
|
||||||
|
m := mail.NewMsg()
|
||||||
|
|
||||||
|
err := m.From(u.Name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SendRegVerify: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.To(to)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SendRegVerify: %w", err)
|
||||||
|
}
|
||||||
|
m.Subject(subject)
|
||||||
|
m.SetBodyString(mail.TypeTextHTML, body)
|
||||||
|
|
||||||
|
c, err := mail.NewClient(u.Host, mail.WithPort(u.Port), mail.WithSMTPAuth(mail.SMTPAuthPlain),
|
||||||
|
mail.WithUsername(u.Name), mail.WithPassword(u.Pass))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SendRegVerify: %w", err)
|
||||||
|
}
|
||||||
|
if u.SSL {
|
||||||
|
c.SetSSL(true)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
err = c.DialAndSendWithContext(ctx, m)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SendRegVerify: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Email) SendVerifyCode(ctx context.Context, email string, interval int) error {
|
||||||
|
sendKey := []byte("SendEmail" + email)
|
||||||
|
sendB, err := e.cache.Get(sendKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SendRegVerifyCode: %w", err)
|
||||||
|
}
|
||||||
|
if sendB == nil {
|
||||||
|
return fmt.Errorf("SendRegVerifyCode: %w", ErrSendLimit)
|
||||||
|
}
|
||||||
|
err = e.cache.Put(sendKey, []byte{1}, time.Now().Add(time.Second*time.Duration(interval)))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SendRegVerifyCode: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
code := lo.RandomString(8, append(lo.NumbersCharset, lo.UpperCaseLettersCharset...))
|
||||||
|
|
||||||
|
err = e.cache.Put([]byte("VerifyCode"+email), []byte(code), time.Now().Add(5*time.Minute))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SendRegVerifyCode: %w", err)
|
||||||
|
}
|
||||||
|
err = e.SendEmail(ctx, email, "验证你的邮箱", fmt.Sprintf("验证码:%v,五分钟内有效", code))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SendRegVerifyCode: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrCodeNotValid = errors.New("验证码无效")
|
||||||
|
ErrSendLimit = errors.New("邮件发送限制")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (e Email) VerifyCode(email, code string) error {
|
||||||
|
key := []byte("VerifyCode" + email)
|
||||||
|
codeb, err := e.cache.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("VerifyCode: %w", err)
|
||||||
|
}
|
||||||
|
if string(codeb) != code {
|
||||||
|
err := e.cache.Del(key)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("VerifyCode: %w", err)
|
||||||
|
}
|
||||||
|
return ErrCodeNotValid
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user