ソースを参照

Add API to get account two recovery status

Neeraj Gupta 1 年間 前
コミット
09a7d557d2

+ 7 - 0
server/cmd/museum/main.go

@@ -5,6 +5,7 @@ import (
 	"database/sql"
 	b64 "encoding/base64"
 	"fmt"
+	"github.com/ente-io/museum/pkg/repo/accountrecovery"
 	"net/http"
 	"os"
 	"os/signal"
@@ -137,6 +138,7 @@ func main() {
 
 	twoFactorRepo := &repo.TwoFactorRepository{DB: db, SecretEncryptionKey: secretEncryptionKeyBytes}
 	userAuthRepo := &repo.UserAuthRepository{DB: db}
+	accountRecoveryRepo := &accountrecovery.Repository{Db: db}
 	billingRepo := &repo.BillingRepository{DB: db}
 	userEntityRepo := &userEntityRepo.Repository{DB: db}
 	locationTagRepository := &locationtagRepo.Repository{DB: db}
@@ -304,6 +306,7 @@ func main() {
 		usageRepo,
 		userAuthRepo,
 		twoFactorRepo,
+		accountRecoveryRepo,
 		passkeysRepo,
 		storagBonusRepo,
 		fileRepo,
@@ -429,6 +432,10 @@ func main() {
 	publicAPI.POST("/users/two-factor/remove", userHandler.RemoveTwoFactor)
 	publicAPI.POST("/users/two-factor/passkeys/begin", userHandler.BeginPasskeyAuthenticationCeremony)
 	publicAPI.POST("/users/two-factor/passkeys/finish", userHandler.FinishPasskeyAuthenticationCeremony)
+	privateAPI.GET("/users/two-factor/account-recovery-status", userHandler.GetAccountRecoveryStatus)
+	privateAPI.POST("/users/two-factor/passkeys/set-reset-challenge", userHandler.ConfigurePassKeyRecovery)
+	publicAPI.GET("/users/two-factor/passkeys/reset-challenge", userHandler.GetPasskeyResetChallenge)
+	publicAPI.POST("/users/two-factor/passkeys/reset", userHandler.ResetPasskey)
 	privateAPI.GET("/users/two-factor/status", userHandler.GetTwoFactorStatus)
 	privateAPI.POST("/users/two-factor/setup", userHandler.SetupTwoFactor)
 	privateAPI.POST("/users/two-factor/enable", userHandler.EnableTwoFactor)

+ 31 - 0
server/pkg/api/user.go

@@ -244,6 +244,27 @@ func (h *UserHandler) GetTwoFactorStatus(c *gin.Context) {
 	c.JSON(http.StatusOK, gin.H{"status": status})
 }
 
+func (h *UserHandler) GetAccountRecoveryStatus(c *gin.Context) {
+	res, err := h.UserController.GetAccountRecoveryStatus(c)
+	if err != nil {
+		handler.Error(c, stacktrace.Propagate(err, ""))
+		return
+	}
+	c.JSON(http.StatusOK, res)
+}
+
+func (h *UserHandler) ConfigurePassKeyRecovery(c *gin.Context) {
+	c.JSON(http.StatusNotImplemented, gin.H{"message": "Not implemented"})
+}
+
+func (h *UserHandler) GetPasskeyResetChallenge(c *gin.Context) {
+	c.JSON(http.StatusNotImplemented, gin.H{"message": "Not implemented"})
+}
+
+func (h *UserHandler) ResetPasskey(c *gin.Context) {
+	c.JSON(http.StatusNotImplemented, gin.H{"message": "Not implemented"})
+}
+
 // SetupTwoFactor generates a two factor secret and sends it to user to setup his authenticator app with
 func (h *UserHandler) SetupTwoFactor(c *gin.Context) {
 	userID := auth.GetUserID(c.Request.Header)
@@ -352,6 +373,16 @@ func (h *UserHandler) FinishPasskeyAuthenticationCeremony(c *gin.Context) {
 	c.JSON(http.StatusOK, response)
 }
 
+func (h *UserHandler) IsPasskeyRecoveryEnabled(c *gin.Context) {
+	userID := auth.GetUserID(c.Request.Header)
+	response, err := h.UserController.GetKeyAttributeAndToken(c, userID)
+	if err != nil {
+		handler.Error(c, stacktrace.Propagate(err, ""))
+		return
+	}
+	c.JSON(http.StatusOK, response)
+}
+
 // DisableTwoFactor disables the two factor authentication for a user
 func (h *UserHandler) DisableTwoFactor(c *gin.Context) {
 	userID := auth.GetUserID(c.Request.Header)

+ 13 - 0
server/pkg/controller/user/passkey.go

@@ -0,0 +1,13 @@
+package user
+
+import (
+	"github.com/ente-io/museum/ente"
+	"github.com/ente-io/museum/pkg/utils/auth"
+	"github.com/gin-gonic/gin"
+)
+
+// GetAccountRecoveryStatus returns a user's passkey reset status
+func (c *UserController) GetAccountRecoveryStatus(ctx *gin.Context) (*ente.AccountRecoveryStatus, error) {
+	userID := auth.GetUserID(ctx.Request.Header)
+	return c.AccountRecoveryRepo.GetAccountRecoveryStatus(userID)
+}

+ 4 - 0
server/pkg/controller/user/user.go

@@ -3,6 +3,7 @@ package user
 import (
 	"errors"
 	"fmt"
+	"github.com/ente-io/museum/pkg/repo/accountrecovery"
 	"strings"
 
 	cache2 "github.com/ente-io/museum/ente/cache"
@@ -30,6 +31,7 @@ import (
 // UserController exposes request handlers for all user related requests
 type UserController struct {
 	UserRepo               *repo.UserRepository
+	AccountRecoveryRepo    *accountrecovery.Repository
 	UsageRepo              *repo.UsageRepository
 	UserAuthRepo           *repo.UserAuthRepository
 	TwoFactorRepo          *repo.TwoFactorRepository
@@ -99,6 +101,7 @@ func NewUserController(
 	usageRepo *repo.UsageRepository,
 	userAuthRepo *repo.UserAuthRepository,
 	twoFactorRepo *repo.TwoFactorRepository,
+	accountRecoveryRepo *accountrecovery.Repository,
 	passkeyRepo *passkey.Repository,
 	storageBonusRepo *storageBonusRepo.Repository,
 	fileRepo *repo.FileRepository,
@@ -121,6 +124,7 @@ func NewUserController(
 	return &UserController{
 		UserRepo:               userRepo,
 		UsageRepo:              usageRepo,
+		AccountRecoveryRepo:    accountRecoveryRepo,
 		UserAuthRepo:           userAuthRepo,
 		StorageBonusRepo:       storageBonusRepo,
 		TwoFactorRepo:          twoFactorRepo,

+ 29 - 0
server/pkg/repo/accountrecovery/repository.go

@@ -0,0 +1,29 @@
+package accountrecovery
+
+import (
+	"database/sql"
+	"github.com/ente-io/museum/ente"
+)
+
+type Repository struct {
+	Db *sql.DB
+}
+
+// GetAccountRecoveryStatus returns `ente.AccountRecoveryStatus` for a user
+func (r *Repository) GetAccountRecoveryStatus(userID int64) (*ente.AccountRecoveryStatus, error) {
+	var isAdminResetEnabled bool
+	var resetKey sql.NullString
+	row := r.Db.QueryRow("SELECT enable_admin_mfa_reset, pass_key_reset_key FROM account_recovery WHERE user_id = $1", userID)
+	err := row.Scan(&isAdminResetEnabled, &resetKey)
+	if err != nil {
+		if err == sql.ErrNoRows {
+			// by default, admin
+			return &ente.AccountRecoveryStatus{
+				AllowAdminReset:       true,
+				IsPassKeyResetEnabled: false,
+			}, nil
+		}
+		return nil, err
+	}
+	return &ente.AccountRecoveryStatus{AllowAdminReset: isAdminResetEnabled, IsPassKeyResetEnabled: resetKey.Valid}, nil
+}