Initial commit (code only without large binaries)
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package mfa
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DisableAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DisableAction) RunPost(params struct{}) {
|
||||
_, err := this.RPC().LoginRPC().UpdateLogin(this.UserContext(), &pb.UpdateLoginRequest{
|
||||
Login: &pb.Login{
|
||||
Type: "otp",
|
||||
IsOn: false,
|
||||
UserId: this.UserId(),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
50
EdgeUser/internal/web/actions/default/settings/mfa/enable.go
Normal file
50
EdgeUser/internal/web/actions/default/settings/mfa/enable.go
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package mfa
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/xlzd/gotp"
|
||||
)
|
||||
|
||||
type EnableAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *EnableAction) RunPost(params struct{}) {
|
||||
// 修改OTP
|
||||
otpLoginResp, err := this.RPC().LoginRPC().FindEnabledLogin(this.UserContext(), &pb.FindEnabledLoginRequest{
|
||||
Type: "otp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
{
|
||||
var otpLogin = otpLoginResp.Login
|
||||
if otpLogin == nil {
|
||||
otpLogin = &pb.Login{
|
||||
Id: 0,
|
||||
Type: "otp",
|
||||
ParamsJSON: maps.Map{
|
||||
"secret": gotp.RandomSecret(16), // TODO 改成可以设置secret长度
|
||||
}.AsJSON(),
|
||||
IsOn: true,
|
||||
UserId: this.UserId(),
|
||||
}
|
||||
} else {
|
||||
// 如果已经有了,就覆盖,这样可以保留既有的参数
|
||||
otpLogin.IsOn = true
|
||||
}
|
||||
|
||||
_, err = this.RPC().LoginRPC().UpdateLogin(this.UserContext(), &pb.UpdateLoginRequest{Login: otpLogin})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
48
EdgeUser/internal/web/actions/default/settings/mfa/index.go
Normal file
48
EdgeUser/internal/web/actions/default/settings/mfa/index.go
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package mfa
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
userResp, err := this.RPC().UserRPC().FindEnabledUser(this.UserContext(), &pb.FindEnabledUserRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var user = userResp.User
|
||||
if user == nil {
|
||||
this.NotFound("User", this.UserId())
|
||||
return
|
||||
}
|
||||
|
||||
// OTP
|
||||
this.Data["otp"] = nil
|
||||
if user.OtpLogin != nil && user.OtpLogin.IsOn {
|
||||
loginParams := maps.Map{}
|
||||
err = json.Unmarshal(user.OtpLogin.ParamsJSON, &loginParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["otp"] = maps.Map{
|
||||
"isOn": true,
|
||||
"params": loginParams,
|
||||
}
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
21
EdgeUser/internal/web/actions/default/settings/mfa/init.go
Normal file
21
EdgeUser/internal/web/actions/default/settings/mfa/init.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package mfa
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/settings/settingutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(settingutils.NewHelper("mfa")).
|
||||
Prefix("/settings/mfa").
|
||||
GetPost("", new(IndexAction)).
|
||||
Get("/otpQrcode", new(OtpQrcodeAction)).
|
||||
Post("/enable", new(EnableAction)).
|
||||
Post("/disable", new(DisableAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package mfa
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils/otputils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"github.com/skip2/go-qrcode"
|
||||
"github.com/xlzd/gotp"
|
||||
)
|
||||
|
||||
type OtpQrcodeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *OtpQrcodeAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *OtpQrcodeAction) RunGet(params struct {
|
||||
Download bool
|
||||
}) {
|
||||
var userId = this.UserId()
|
||||
|
||||
loginResp, err := this.RPC().LoginRPC().FindEnabledLogin(this.UserContext(), &pb.FindEnabledLoginRequest{
|
||||
Type: "otp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var login = loginResp.Login
|
||||
if login == nil || !login.IsOn {
|
||||
this.NotFound("userLogin", userId)
|
||||
return
|
||||
}
|
||||
|
||||
var loginParams = maps.Map{}
|
||||
err = json.Unmarshal(login.ParamsJSON, &loginParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var secret = loginParams.GetString("secret")
|
||||
|
||||
// 当前用户信息
|
||||
userResp, err := this.RPC().UserRPC().FindEnabledUser(this.UserContext(), &pb.FindEnabledUserRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var user = userResp.User
|
||||
if user == nil {
|
||||
this.NotFound("user", userId)
|
||||
return
|
||||
}
|
||||
|
||||
uiConfig, err := configloaders.LoadUIConfig()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var productName = uiConfig.ProductName
|
||||
if len(productName) == 0 {
|
||||
productName = "GoEdge用户"
|
||||
}
|
||||
var url = gotp.NewDefaultTOTP(secret).ProvisioningUri(user.Username, productName)
|
||||
data, err := qrcode.Encode(otputils.FixIssuer(url), qrcode.Medium, 256)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if params.Download {
|
||||
var filename = "OTP-USER-" + user.Username + ".png"
|
||||
this.AddHeader("Content-Disposition", "attachment; filename=\""+filename+"\";")
|
||||
}
|
||||
this.AddHeader("Content-Type", "image/png")
|
||||
this.AddHeader("Content-Length", types.String(len(data)))
|
||||
_, _ = this.Write(data)
|
||||
}
|
||||
Reference in New Issue
Block a user