mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-22 18:25:47 +08:00

* refactor: remove isGlobalAdmin field in user * fix: upload xlsx * fix: remove field in account table
190 lines
4.3 KiB
Go
190 lines
4.3 KiB
Go
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package object
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/casdoor/casdoor/util"
|
|
|
|
"github.com/beego/beego/context"
|
|
)
|
|
|
|
const MfaRecoveryCodesSession = "mfa_recovery_codes"
|
|
|
|
type MfaProps struct {
|
|
Enabled bool `json:"enabled"`
|
|
IsPreferred bool `json:"isPreferred"`
|
|
MfaType string `json:"mfaType" form:"mfaType"`
|
|
Secret string `json:"secret,omitempty"`
|
|
CountryCode string `json:"countryCode,omitempty"`
|
|
URL string `json:"url,omitempty"`
|
|
RecoveryCodes []string `json:"recoveryCodes,omitempty"`
|
|
}
|
|
|
|
type MfaInterface interface {
|
|
Initiate(ctx *context.Context, userId string) (*MfaProps, error)
|
|
SetupVerify(ctx *context.Context, passcode string) error
|
|
Enable(ctx *context.Context, user *User) error
|
|
Verify(passcode string) error
|
|
}
|
|
|
|
const (
|
|
EmailType = "email"
|
|
SmsType = "sms"
|
|
TotpType = "app"
|
|
)
|
|
|
|
const (
|
|
MfaSessionUserId = "MfaSessionUserId"
|
|
NextMfa = "NextMfa"
|
|
RequiredMfa = "RequiredMfa"
|
|
)
|
|
|
|
func GetMfaUtil(mfaType string, config *MfaProps) MfaInterface {
|
|
switch mfaType {
|
|
case SmsType:
|
|
return NewSmsMfaUtil(config)
|
|
case EmailType:
|
|
return NewEmailMfaUtil(config)
|
|
case TotpType:
|
|
return NewTotpMfaUtil(config)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func MfaRecover(user *User, recoveryCode string) error {
|
|
hit := false
|
|
|
|
if len(user.RecoveryCodes) == 0 {
|
|
return fmt.Errorf("do not have recovery codes")
|
|
}
|
|
|
|
for _, code := range user.RecoveryCodes {
|
|
if code == recoveryCode {
|
|
hit = true
|
|
user.RecoveryCodes = util.DeleteVal(user.RecoveryCodes, code)
|
|
break
|
|
}
|
|
}
|
|
if !hit {
|
|
return fmt.Errorf("recovery code not found")
|
|
}
|
|
|
|
_, err := UpdateUser(user.GetId(), user, []string{"recovery_codes"}, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func GetAllMfaProps(user *User, masked bool) []*MfaProps {
|
|
mfaProps := []*MfaProps{}
|
|
|
|
for _, mfaType := range []string{SmsType, EmailType, TotpType} {
|
|
mfaProps = append(mfaProps, user.GetMfaProps(mfaType, masked))
|
|
}
|
|
return mfaProps
|
|
}
|
|
|
|
func (user *User) GetMfaProps(mfaType string, masked bool) *MfaProps {
|
|
mfaProps := &MfaProps{}
|
|
|
|
if mfaType == SmsType {
|
|
if !user.MfaPhoneEnabled {
|
|
return &MfaProps{
|
|
Enabled: false,
|
|
MfaType: mfaType,
|
|
}
|
|
}
|
|
|
|
mfaProps = &MfaProps{
|
|
Enabled: user.MfaPhoneEnabled,
|
|
MfaType: mfaType,
|
|
CountryCode: user.CountryCode,
|
|
}
|
|
if masked {
|
|
mfaProps.Secret = util.GetMaskedPhone(user.Phone)
|
|
} else {
|
|
mfaProps.Secret = user.Phone
|
|
}
|
|
} else if mfaType == EmailType {
|
|
if !user.MfaEmailEnabled {
|
|
return &MfaProps{
|
|
Enabled: false,
|
|
MfaType: mfaType,
|
|
}
|
|
}
|
|
|
|
mfaProps = &MfaProps{
|
|
Enabled: user.MfaEmailEnabled,
|
|
MfaType: mfaType,
|
|
}
|
|
if masked {
|
|
mfaProps.Secret = util.GetMaskedEmail(user.Email)
|
|
} else {
|
|
mfaProps.Secret = user.Email
|
|
}
|
|
} else if mfaType == TotpType {
|
|
if user.TotpSecret == "" {
|
|
return &MfaProps{
|
|
Enabled: false,
|
|
MfaType: mfaType,
|
|
}
|
|
}
|
|
|
|
mfaProps = &MfaProps{
|
|
Enabled: true,
|
|
MfaType: mfaType,
|
|
}
|
|
if masked {
|
|
mfaProps.Secret = ""
|
|
} else {
|
|
mfaProps.Secret = user.TotpSecret
|
|
}
|
|
}
|
|
|
|
if user.PreferredMfaType == mfaType {
|
|
mfaProps.IsPreferred = true
|
|
}
|
|
return mfaProps
|
|
}
|
|
|
|
func DisabledMultiFactorAuth(user *User) error {
|
|
user.PreferredMfaType = ""
|
|
user.RecoveryCodes = []string{}
|
|
user.MfaPhoneEnabled = false
|
|
user.MfaEmailEnabled = false
|
|
user.TotpSecret = ""
|
|
|
|
_, err := updateUser(user.GetId(), user, []string{"preferred_mfa_type", "recovery_codes", "mfa_phone_enabled", "mfa_email_enabled", "totp_secret"})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func SetPreferredMultiFactorAuth(user *User, mfaType string) error {
|
|
user.PreferredMfaType = mfaType
|
|
|
|
_, err := UpdateUser(user.GetId(), user, []string{"preferred_mfa_type"}, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|