github.com/infraboard/keyauth@v0.8.1/apps/verifycode/impl/code.go (about) 1 package impl 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/infraboard/mcube/exception" 8 "go.mongodb.org/mongo-driver/bson" 9 "go.mongodb.org/mongo-driver/mongo" 10 11 "github.com/infraboard/keyauth/apps/system/notify" 12 "github.com/infraboard/keyauth/apps/system/notify/mail" 13 "github.com/infraboard/keyauth/apps/system/notify/sms" 14 "github.com/infraboard/keyauth/apps/token" 15 "github.com/infraboard/keyauth/apps/user" 16 "github.com/infraboard/keyauth/apps/verifycode" 17 ) 18 19 func (s *service) IssueCode(ctx context.Context, req *verifycode.IssueCodeRequest) ( 20 *verifycode.IssueCodeResponse, error) { 21 code, err := verifycode.NewCode(req) 22 if err != nil { 23 return nil, err 24 } 25 26 // 根据系统配置设置校验码过期时间 27 cf, err := s.system.GetConfig() 28 if err != nil { 29 s.log.Errorf("get system config error, %s", err) 30 } else { 31 code.ExpiredMinite = uint32(cf.VerifyCode.ExpireMinutes) 32 } 33 34 // 如果是issue by pass, 这要检测 35 switch req.IssueType { 36 case verifycode.IssueType_PASS: 37 _, err := s.issuer.IssueToken(ctx, token.NewIssueTokenByPassword( 38 req.ClientId, 39 req.ClientSecret, 40 req.Username, 41 req.Password), 42 ) 43 if err != nil { 44 return nil, err 45 } 46 case verifycode.IssueType_TOKEN: 47 _, err := s.token.DescribeToken(ctx, token.NewDescribeTokenRequestWithAccessToken(req.AccessToken)) 48 if err != nil { 49 return nil, err 50 } 51 default: 52 return nil, fmt.Errorf("unknown issue_type %s", req.IssueType) 53 } 54 if _, err := s.col.InsertOne(context.TODO(), code); err != nil { 55 return nil, exception.NewInternalServerError("inserted verify code(%s) document error, %s", 56 code, err) 57 } 58 59 msg, err := s.sendCode(ctx, code) 60 if err != nil { 61 return nil, exception.NewInternalServerError("send verify code error, %s", err) 62 } 63 64 return verifycode.NewIssueCodeResponse(msg), nil 65 } 66 67 func (s *service) sendCode(ctx context.Context, code *verifycode.Code) (string, error) { 68 system, err := s.system.GetConfig() 69 if err != nil { 70 return "", fmt.Errorf("query system config error, %s", err) 71 } 72 73 u, err := s.user.DescribeAccount(ctx, user.NewDescriptAccountRequestWithAccount(code.Username)) 74 if err != nil { 75 return "", fmt.Errorf("get user error, %s", err) 76 } 77 78 var message string 79 vc := system.VerifyCode 80 switch vc.NotifyType { 81 case verifycode.NotifyType_MAIL: 82 sender, err := mail.NewSender(system.Email) 83 if err != nil { 84 return "", fmt.Errorf("new sms sender error, %s", err) 85 } 86 req := notify.NewSendMailRequest() 87 req.To = u.Profile.Email 88 req.Subject = "验证码" 89 req.Content = vc.RenderMailTemplate(code.Number, code.ExpiredMiniteString()) 90 if err := sender.Send(req); err != nil { 91 return "", fmt.Errorf("send verify code by mail error, %s", err) 92 } 93 message = fmt.Sprintf("验证码已通过邮件发送到你的邮箱: %s, 请及时查收", u.Profile.Email) 94 s.log.Debugf("send verify code to user: %s by mail ok", code.Username) 95 case verifycode.NotifyType_SMS: 96 sender, err := sms.NewSender(system.SMS) 97 if err != nil { 98 return "", fmt.Errorf("new sms sender error, %s", err) 99 } 100 req := notify.NewSendSMSRequest() 101 req.AddPhone(u.Profile.Phone) 102 req.TemplateID = vc.SmsTemplateID 103 req.AddParams(code.Number, code.ExpiredMiniteString()) 104 if err := sender.Send(req); err != nil { 105 return "", fmt.Errorf("send verify code by sms error, %s", err) 106 } 107 message = fmt.Sprintf("验证码已通过短信发送到你的手机: %s, 请及时查收", u.Profile.Phone) 108 s.log.Debugf("send verify code to user: %s by sms ok", code.Username) 109 default: 110 return "", fmt.Errorf("unknown notify type %s", vc.NotifyType) 111 } 112 113 return message, nil 114 } 115 116 func (s *service) CheckCode(ctx context.Context, req *verifycode.CheckCodeRequest) (*verifycode.Code, error) { 117 if err := req.Validate(); err != nil { 118 return nil, exception.NewBadRequest("validate check code request error, %s", err) 119 } 120 121 code := verifycode.NewDefaultCode() 122 if err := s.col.FindOne(context.TODO(), bson.M{"_id": req.HashID()}).Decode(code); err != nil { 123 if err == mongo.ErrNoDocuments { 124 return nil, exception.NewNotFound("verify code: %s not found", req.Number) 125 } 126 127 return nil, exception.NewInternalServerError("find system config %s error, %s", req.Number, err) 128 } 129 130 // 校验Token是否过期 131 if code.IsExpired() { 132 return nil, exception.NewPermissionDeny("verify code is expired") 133 } 134 135 // 没过去验证成功, 删除 136 if err := s.delete(code); err != nil { 137 s.log.Errorf("delete check ok verify code error, %s", err) 138 } 139 140 return code, nil 141 }