From 648806baa7fd5d06c895a78ed9032e6b0c10c888 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 22 Apr 2024 17:30:54 +0530 Subject: [PATCH] [server] Add endpoint to get user feature flags --- server/cmd/museum/main.go | 1 + server/ente/remotestore.go | 44 +++++++++++++++++ .../pkg/controller/remotestore/controller.go | 49 +++++-------------- 3 files changed, 56 insertions(+), 38 deletions(-) diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 8be76120d..337989651 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -672,6 +672,7 @@ func main() { privateAPI.POST("/remote-store/update", remoteStoreHandler.InsertOrUpdate) privateAPI.GET("/remote-store", remoteStoreHandler.GetKey) + privateAPI.GET("/remote-store/feature-flags", remoteStoreHandler.GetFeatureFlags) pushHandler := &api.PushHandler{PushController: pushController} privateAPI.POST("/push/token", pushHandler.AddToken) diff --git a/server/ente/remotestore.go b/server/ente/remotestore.go index 02eb93232..4c094deba 100644 --- a/server/ente/remotestore.go +++ b/server/ente/remotestore.go @@ -13,3 +13,47 @@ type UpdateKeyValueRequest struct { Key string `json:"key" binding:"required"` Value string `json:"value" binding:"required"` } + +type FeatureFlagResponse struct { + EnableStripe bool `json:"enableStripe"` + // If true, the mobile client will stop using CF worker to download files + DisableCFWorker bool `json:"disableCFWorker"` + MapEnabled bool `json:"mapEnabled"` + FaceSearchEnabled bool `json:"faceSearchEnabled"` + PassKeyEnabled bool `json:"passKeyEnabled"` + RecoveryKeyVerified bool `json:"recoveryKeyVerified"` + InternalUser bool `json:"internalUser"` + BetaUser bool `json:"betaUser"` +} + +type FlagKey string + +const ( + RecoveryKeyVerified FlagKey = "recoveryKeyVerified" + MapEnabled FlagKey = "mapEnabled" + FaceSearchEnabled FlagKey = "faceSearchEnabled" + PassKeyEnabled FlagKey = "passKeyEnabled" +) + +func (k FlagKey) String() string { + return string(k) +} + +// UserEditable returns true if the key is user editable +func (k FlagKey) UserEditable() bool { + switch k { + case RecoveryKeyVerified, MapEnabled, FaceSearchEnabled, PassKeyEnabled: + return true + default: + return false + } +} + +func (k FlagKey) IsBoolType() bool { + switch k { + case RecoveryKeyVerified, MapEnabled, FaceSearchEnabled, PassKeyEnabled: + return true + default: + return false + } +} diff --git a/server/pkg/controller/remotestore/controller.go b/server/pkg/controller/remotestore/controller.go index 0a4e8cbb1..98a460526 100644 --- a/server/pkg/controller/remotestore/controller.go +++ b/server/pkg/controller/remotestore/controller.go @@ -12,33 +12,6 @@ import ( "github.com/gin-gonic/gin" ) -type FlagKey string - -const ( - RecoveryKeyVerified FlagKey = "recoveryKeyVerified" - MapEnabled FlagKey = "mapEnabled" - FaceSearchEnabled FlagKey = "faceSearchEnabled" - PassKeyEnabled FlagKey = "passKeyEnabled" -) - -func isBoolType(key FlagKey) bool { - switch key { - case RecoveryKeyVerified, MapEnabled, FaceSearchEnabled, PassKeyEnabled: - return true - default: - return false - } -} - -var ( - _allowKeys = map[FlagKey]*bool{ - RecoveryKeyVerified: nil, - MapEnabled: nil, - FaceSearchEnabled: nil, - PassKeyEnabled: nil, - } -) - // Controller is interface for exposing business logic related to for remote store type Controller struct { Repo *remotestore.Repository @@ -77,18 +50,18 @@ func (c *Controller) GetFeatureFlags(ctx *gin.Context) (*ente.FeatureFlagRespons DisableCFWorker: false, } for key, value := range values { - flag := FlagKey(key) - if !isBoolType(flag) { + flag := ente.FlagKey(key) + if !flag.IsBoolType() { continue } switch flag { - case RecoveryKeyVerified: - response.RestoreKeyVerified = value == "true" - case MapEnabled: + case ente.RecoveryKeyVerified: + response.RecoveryKeyVerified = value == "true" + case ente.MapEnabled: response.MapEnabled = value == "true" - case FaceSearchEnabled: + case ente.FaceSearchEnabled: response.FaceSearchEnabled = value == "true" - case PassKeyEnabled: + case ente.PassKeyEnabled: response.PassKeyEnabled = value == "true" } } @@ -96,11 +69,11 @@ func (c *Controller) GetFeatureFlags(ctx *gin.Context) (*ente.FeatureFlagRespons } func _validateRequest(request ente.UpdateKeyValueRequest) error { - flag := FlagKey(request.Key) - if _, ok := _allowKeys[flag]; !ok { - return stacktrace.Propagate(ente.NewBadRequestWithMessage(fmt.Sprintf("key %s is not allowed", request.Key)), "key not allowed") + flag := ente.FlagKey(request.Key) + if !flag.UserEditable() { + return stacktrace.Propagate(ente.NewBadRequestWithMessage(fmt.Sprintf("key %s is not user editable", request.Key)), "key not user editable") } - if isBoolType(flag) && request.Value != "true" && request.Value != "false" { + if flag.IsBoolType() && request.Value != "true" && request.Value != "false" { return stacktrace.Propagate(ente.NewBadRequestWithMessage(fmt.Sprintf("value %s is not allowed", request.Value)), "value not allowed") } return nil