Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

新增Google令牌双因素认证 #10

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/all/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
_ "github.com/infraboard/keyauth/apps/mconf/impl"
_ "github.com/infraboard/keyauth/apps/micro/impl"
_ "github.com/infraboard/keyauth/apps/namespace/impl"
_ "github.com/infraboard/keyauth/apps/otp/impl"
_ "github.com/infraboard/keyauth/apps/permission/impl"
_ "github.com/infraboard/keyauth/apps/policy/impl"
_ "github.com/infraboard/keyauth/apps/role/impl"
Expand Down
1 change: 1 addition & 0 deletions apps/all/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
_ "github.com/infraboard/keyauth/apps/mconf/http"
_ "github.com/infraboard/keyauth/apps/micro/http"
_ "github.com/infraboard/keyauth/apps/namespace/http"
_ "github.com/infraboard/keyauth/apps/otp/http"
_ "github.com/infraboard/keyauth/apps/permission/http"
_ "github.com/infraboard/keyauth/apps/policy/http"
_ "github.com/infraboard/keyauth/apps/provider/http"
Expand Down
5 changes: 5 additions & 0 deletions apps/otp/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package otp

const (
AppName = "OTP"
)
38 changes: 38 additions & 0 deletions apps/otp/http/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package http

import (
"github.com/infraboard/keyauth/apps/otp"
"github.com/infraboard/mcube/app"
"github.com/infraboard/mcube/http/router"
)

var (
api = &handler{}
)

type handler struct {
service otp.ServiceServer
}

// Registry 注册HTTP服务路由
func (h *handler) Registry(router router.SubRouter) {

r := router.ResourceRouter("otp")
r.BasePath("otp")
r.Handle("DELETE", "/:account", h.DeleteOTP)
r.Handle("GET", "/:account", h.GetOTP)
r.Handle("POST", "/", h.UpdateOTP)
}

func (h *handler) Config() error {
h.service = app.GetGrpcApp(otp.AppName).(otp.ServiceServer)
return nil
}

func (h *handler) Name() string {
return otp.AppName
}

func init() {
app.RegistryHttpApp(api)
}
63 changes: 63 additions & 0 deletions apps/otp/http/otp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package http

import (
"net/http"

"github.com/infraboard/keyauth/apps/otp"
"github.com/infraboard/mcube/http/context"
"github.com/infraboard/mcube/http/request"
"github.com/infraboard/mcube/http/response"
)

// enable OTP
func (h *handler) CreateOTP(w http.ResponseWriter, r *http.Request) {
req := otp.NewCreateOTPAuthRequest()
if err := request.GetDataFromRequest(r, req); err != nil {
response.Failed(w, err)
return
}
ins, err := h.service.CreateOTPAuth(r.Context(), req)
if err != nil {
response.Failed(w, err)
return
}
response.Success(w, ins)
}
func (h *handler) GetOTP(w http.ResponseWriter, r *http.Request) {
ctx := context.GetContext(r)
account := ctx.PS.ByName("account")
req := otp.NewDescribeOTPAuthRequestWithName(account)
ins, err := h.service.DescribeOTPAuth(r.Context(), req)
if err != nil {
response.Failed(w, err)
return
}
response.Success(w, ins)
}

func (h *handler) DeleteOTP(w http.ResponseWriter, r *http.Request) {
ctx := context.GetContext(r)
account := ctx.PS.ByName("account")
req := otp.NewDeleteOTPAuthRequestWithName(account)
ins, err := h.service.DeleteOTPAuth(r.Context(), req)
if err != nil {
response.Failed(w, err)
return
}
response.Success(w, ins)
}

func (h *handler) UpdateOTP(w http.ResponseWriter, r *http.Request) {
req := otp.NewUpdateOTPStatusRequest()
if err := request.GetDataFromRequest(r, req); err != nil {
response.Failed(w, err)
return
}

d, err := h.service.UpdateOTPAuthStatus(r.Context(), req)
if err != nil {
response.Failed(w, err)
return
}
response.Success(w, d)
}
46 changes: 46 additions & 0 deletions apps/otp/impl/impl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package impl

import (
"github.com/infraboard/keyauth/apps/otp"
"github.com/infraboard/keyauth/apps/user"
"github.com/infraboard/keyauth/conf"
"github.com/infraboard/mcube/app"
"github.com/infraboard/mcube/logger"
"github.com/infraboard/mcube/logger/zap"
"go.mongodb.org/mongo-driver/mongo"
"google.golang.org/grpc"
)

var (
svr = &service{}
)

type service struct {
col *mongo.Collection
log logger.Logger
enableCache bool
notifyCachPre string

user user.ServiceServer
otp.UnimplementedServiceServer
}

func (s *service) Config() error {
db := conf.C().Mongo.GetDB()
col := db.Collection("otp")

s.col = col
s.log = zap.L().Named("OTP")
s.user = app.GetGrpcApp(user.AppName).(user.ServiceServer)
return nil
}
func (s *service) Name() string {
return otp.AppName
}
func (s *service) Registry(server *grpc.Server) {
otp.RegisterServiceServer(server, svr)
}

func init() {
app.RegistryGrpcApp(svr)
}
105 changes: 105 additions & 0 deletions apps/otp/impl/otp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package impl

import (
"context"
"fmt"

"github.com/infraboard/keyauth/apps/otp"
"github.com/infraboard/keyauth/apps/user"
"github.com/infraboard/mcube/exception"
"go.mongodb.org/mongo-driver/mongo"
)

func (s *service) CreateOTPAuth(ctx context.Context, req *otp.CreateOTPAuthRequest) (*otp.OTPAuth, error) {
if err := req.Validate(); err != nil {
return nil, exception.NewBadRequest(err.Error())
}

ins := otp.NewOTPAuth()
ins.Account = req.Account
ins.GenSecret()
ins.GenOtpCode(ins.Account, ins.SecretKey)
ins.GenQrcodeUrl(ins.Account, ins.SecretKey)

_, err := s.col.InsertOne(context.Background(), ins)
if err != nil {
return nil, exception.NewInternalServerError("insert document(%s) error, %s", ins, err)
}
return ins, nil
}

func (s *service) DescribeOTPAuth(ctx context.Context, req *otp.DescribeOTPAuthRequest) (*otp.OTPAuth, error) {
if err := req.Validate(); err != nil {
return nil, exception.NewBadRequest(err.Error())
}
r := newdescribeOTPAuthRequest(req)
ins := otp.NewOTPAuth()

if err := s.col.FindOne(context.TODO(), r.FindFilter()).Decode(ins); err != nil {
if err == mongo.ErrNoDocuments {
return nil, exception.NewNotFound("otp for %s not found", req.Account)
}
return nil, exception.NewInternalServerError("find otp %s error, %s", req.Account, err)
}

return ins, nil
}

func (s *service) DeleteOTPAuth(ctx context.Context, req *otp.DeleteOTPAuthRequest) (*otp.OTPAuth, error) {
if err := req.Validate(); err != nil {
return nil, exception.NewBadRequest(err.Error())
}
r := newdeleteOTPAuthRequest(req)

ins, err := s.DescribeOTPAuth(ctx, otp.NewDescribeOTPAuthRequestWithName(req.Account))
if err != nil {
return nil, err
}

_, err = s.col.DeleteOne(context.TODO(), r.FindFilter())
if err != nil {
return nil, exception.NewInternalServerError("delete document(%s) otp error, %s", r.Account, err)
}
return ins, nil
}

func (s *service) UpdateOTPAuthStatus(ctx context.Context, req *otp.UpdateOTPStatusRequest) (*otp.OTPAuth, error) {
if err := req.Validate(); err != nil {
return nil, exception.NewBadRequest(err.Error())
}

u, err := s.user.DescribeAccount(ctx, user.NewDescriptAccountRequestWithAccount(req.Account))
if err != nil {
return nil, err
}

if u.OtpStatus == req.OtpStatus {
return nil, fmt.Errorf("do not need to update OTP status")
}

u.OtpStatus = req.OtpStatus
updateOTPReq := user.NewUpdateOTPStatusRequest()
updateOTPReq.Account = req.Account
updateOTPReq.OtpStatus = req.OtpStatus
_, err = s.user.UpdateOTPStatus(ctx, updateOTPReq)
if err != nil {
return nil, err
}

switch req.OtpStatus {
case otp.OTPStatus_DISABLED:
ins, err := s.DeleteOTPAuth(ctx, otp.NewDeleteOTPAuthRequestWithName(req.Account))
if err != nil {
return nil, err
}
return ins, nil
case otp.OTPStatus_ENABLED:
ins, err := s.CreateOTPAuth(ctx, otp.NewCreateOTPAuthRequestWithName(req.Account))
if err != nil {
return nil, err
}
return ins, nil
default:
return nil, fmt.Errorf("unknown OTPStatus type")
}
}
41 changes: 41 additions & 0 deletions apps/otp/impl/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package impl

import (
"github.com/infraboard/keyauth/apps/otp"
"go.mongodb.org/mongo-driver/bson"
)

func newdescribeOTPAuthRequest(req *otp.DescribeOTPAuthRequest) *describeOTPAuthRequest {
return &describeOTPAuthRequest{
DescribeOTPAuthRequest: req,
}
}

type describeOTPAuthRequest struct {
*otp.DescribeOTPAuthRequest
}

func (req *describeOTPAuthRequest) FindFilter() bson.M {
filter := bson.M{}
if req.Account != "" {
filter["account"] = req.Account
}
return filter
}
func newdeleteOTPAuthRequest(req *otp.DeleteOTPAuthRequest) *deleteOTPAuthRequest {
return &deleteOTPAuthRequest{
DeleteOTPAuthRequest: req,
}
}

type deleteOTPAuthRequest struct {
*otp.DeleteOTPAuthRequest
}

func (req *deleteOTPAuthRequest) FindFilter() bson.M {
filter := bson.M{}
if req.Account != "" {
filter["account"] = req.Account
}
return filter
}
Loading