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  }