resultFiles = {};
for (final e in result.entries) {
resultFiles.addAll(e.value);
}
diff --git a/server/ente/userentity/entity.go b/server/ente/userentity/entity.go
index 09f0ddfd46..904b846d1a 100644
--- a/server/ente/userentity/entity.go
+++ b/server/ente/userentity/entity.go
@@ -11,14 +11,18 @@ type EntityType string
const (
Location EntityType = "location"
- Person EntityType = "person"
+ // Person entity is deprecated and will be removed in the future.
+ //Deprecated ..
+ Person EntityType = "person"
// CGroup is a new version of Person entity, where the data is gzipped before encryption
CGroup EntityType = "cgroup"
+ // SmartAlbum is a new entity type for storing smart album config data
+ SmartAlbum EntityType = "smart_album"
)
func (et EntityType) IsValid() error {
switch et {
- case Location, Person, CGroup:
+ case Location, Person, CGroup, SmartAlbum:
return nil
}
return ente.NewBadRequestWithMessage(fmt.Sprintf("Invalid EntityType: %s", et))
@@ -65,6 +69,26 @@ type EntityDataRequest struct {
Type EntityType `json:"type" binding:"required"`
EncryptedData string `json:"encryptedData" binding:"required"`
Header string `json:"header" binding:"required"`
+ ID *string `json:"id"` // Optional ID, if not provided a new ID will be generated
+}
+
+func (edr *EntityDataRequest) IsValid(userID int64) error {
+ if err := edr.Type.IsValid(); err != nil {
+ return err
+ }
+ switch edr.Type {
+ case SmartAlbum:
+ if edr.ID == nil {
+ return ente.NewBadRequestWithMessage("ID is required for SmartAlbum entity type")
+ }
+ // check if ID starts with sa_userid_ or not
+ if !strings.HasPrefix(*edr.ID, fmt.Sprintf("sa_%d_", userID)) {
+ return ente.NewBadRequestWithMessage(fmt.Sprintf("ID %s is not valid for SmartAlbum entity type", *edr.ID))
+ }
+ return nil
+ default:
+ return nil
+ }
}
// UpdateEntityDataRequest updates the current entity
diff --git a/server/pkg/api/userentity.go b/server/pkg/api/userentity.go
index acda89a09e..e8aa043b5b 100644
--- a/server/pkg/api/userentity.go
+++ b/server/pkg/api/userentity.go
@@ -61,10 +61,6 @@ func (h *UserEntityHandler) CreateEntity(c *gin.Context) {
stacktrace.Propagate(ente.ErrBadRequest, fmt.Sprintf("Request binding failed %s", err)))
return
}
- if err := request.Type.IsValid(); err != nil {
- handler.Error(c, stacktrace.Propagate(err, "Invalid EntityType"))
- return
- }
resp, err := h.Controller.CreateEntity(c, request)
if err != nil {
handler.Error(c, stacktrace.Propagate(err, "Failed to create CreateEntityKey"))
diff --git a/server/pkg/controller/filedata/controller.go b/server/pkg/controller/filedata/controller.go
index 65cbef0033..9c192d7495 100644
--- a/server/pkg/controller/filedata/controller.go
+++ b/server/pkg/controller/filedata/controller.go
@@ -22,6 +22,7 @@ import (
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"net/http"
+ "strings"
"sync"
gTime "time"
)
@@ -264,12 +265,12 @@ func (c *Controller) getS3FileMetadataParallel(ctx *gin.Context, dbRows []fileDa
func (c *Controller) fetchS3FileMetadata(ctx context.Context, row fileData.Row, ctxLogger *log.Entry) (*fileData.S3FileMetadata, error) {
dc := row.LatestBucket
- // :todo:neeraj make it configurable to
- // specify preferred dc to read from
- // and fallback logic to read from different bucket when we fail to read from preferred dc
- if dc == "b5" {
- if array.StringInList("b6", row.ReplicatedBuckets) {
- dc = "b6"
+ preferredBucket := c.S3Config.GetBucketID(row.Type)
+ // If the current primary bucket is different from the latest bucket where data was written,
+ // check and use the preferred bucket if the data is replicated there.
+ if !strings.EqualFold(preferredBucket, dc) {
+ if array.StringInList(preferredBucket, row.ReplicatedBuckets) {
+ dc = preferredBucket
}
}
opt := _defaultFetchConfig
diff --git a/server/pkg/controller/userentity/controller.go b/server/pkg/controller/userentity/controller.go
index f4fb1c8b9b..38b99fba22 100644
--- a/server/pkg/controller/userentity/controller.go
+++ b/server/pkg/controller/userentity/controller.go
@@ -32,6 +32,9 @@ func (c *Controller) GetKey(ctx *gin.Context, req model.GetEntityKeyRequest) (*m
// CreateEntity stores entity data for the given type
func (c *Controller) CreateEntity(ctx *gin.Context, req model.EntityDataRequest) (*model.EntityData, error) {
userID := auth.GetUserID(ctx.Request.Header)
+ if err := req.IsValid(userID); err != nil {
+ return nil, stacktrace.Propagate(err, "invalid EntityDataRequest")
+ }
id, err := c.Repo.Create(ctx, userID, req)
if err != nil {
return nil, stacktrace.Propagate(err, "failed to createEntity")
diff --git a/server/pkg/repo/userentity/data.go b/server/pkg/repo/userentity/data.go
index fa6457ebfa..45f59d3051 100644
--- a/server/pkg/repo/userentity/data.go
+++ b/server/pkg/repo/userentity/data.go
@@ -14,12 +14,17 @@ import (
// Create inserts a new entry
func (r *Repository) Create(ctx context.Context, userID int64, entry model.EntityDataRequest) (string, error) {
- idPrt, err := entry.Type.GetNewID()
- if err != nil {
- return "", stacktrace.Propagate(err, "failed to generate new id")
+ var id string
+ if entry.ID != nil {
+ id = *entry.ID
+ } else {
+ idPrt, err := entry.Type.GetNewID()
+ if err != nil {
+ return "", stacktrace.Propagate(err, "failed to generate new id")
+ }
+ id = *idPrt
}
- id := *idPrt
- err = r.DB.QueryRow(`INSERT into entity_data(
+ err := r.DB.QueryRow(`INSERT into entity_data(
id,
user_id,
type,
diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json
index d1a4378a02..1d3d91cf93 100644
--- a/web/packages/base/locales/es-ES/translation.json
+++ b/web/packages/base/locales/es-ES/translation.json
@@ -32,7 +32,7 @@
"set_password": "Definir contraseña",
"sign_in": "Ingresar",
"incorrect_password": "Contraseña incorrecta",
- "incorrect_password_or_no_account": "",
+ "incorrect_password_or_no_account": "Contraseña incorrecta o correo electrónico no registrado",
"pick_password_hint": "Introducir una contraseña que podamos usar para cifrar sus datos",
"pick_password_caution": "No guardamos su contraseña, así que si la olvida, no podremos ayudarte a recuperar tus datos sin una clave de recuperación.",
"key_generation_in_progress": "Generando claves de encriptación...",
@@ -40,7 +40,7 @@
"referral_source_hint": "¿Cómo conociste Ente? (opcional)",
"referral_source_info": "No rastreamos la instalación de las aplicaciones. ¡Nos ayudaría si nos dijera dónde nos encontró!",
"password_mismatch_error": "Las contraseñas no coinciden",
- "show_or_hide_password": "",
+ "show_or_hide_password": "Mostrar u ocultar la contraseña",
"welcome_to_ente_title": "Bienvenido a ",
"welcome_to_ente_subtitle": "Almacenamiento y compartición de fotos cifradas de extremo a extremo",
"new_album": "Nuevo álbum",
@@ -162,7 +162,7 @@
"ok": "OK",
"success": "Completado",
"error": "Error",
- "note": "",
+ "note": "Nota",
"offline_message": "Estás desconectado, se están mostrando recuerdos en caché",
"install": "Instalar",
"install_mobile_app": "Instala nuestra aplicación Android o iOS para hacer una copia de seguridad automática de todas usted fotos",
@@ -627,7 +627,7 @@
"faster_upload_description": "Enrutar subidas a través de servidores cercanos",
"open_ente_on_startup": "Abrir ente al iniciar",
"cast_album_to_tv": "Reproducir álbum en TV",
- "cast_to_tv": "",
+ "cast_to_tv": "Reproducir en el televisor",
"enter_cast_pin_code": "Introduce el código que ves en el televisor para emparejar este dispositivo.",
"code": "Código",
"pair_device_to_tv": "Emparejar dispositivos",
@@ -679,11 +679,11 @@
"system": "Sistema",
"light": "Claro",
"dark": "Oscuro",
- "streamable_videos": "",
- "processing_videos_status": "",
- "share_favorites": "",
- "person_favorites": "",
- "shared_favorites": "",
- "added_by_name": "",
- "unowned_files_not_processed": ""
+ "streamable_videos": "Vídeos en streaming",
+ "processing_videos_status": "Procesando vídeos...",
+ "share_favorites": "Compartir favoritos",
+ "person_favorites": "Los favoritos de {{name}}",
+ "shared_favorites": "Favoritos compartidos",
+ "added_by_name": "Añadido por {{name}}",
+ "unowned_files_not_processed": "Los archivos añadidos por otros usuarios no han sido procesados"
}
diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json
index 0eb8b4c74d..ecbbff918f 100644
--- a/web/packages/base/locales/pl-PL/translation.json
+++ b/web/packages/base/locales/pl-PL/translation.json
@@ -59,7 +59,7 @@
"select_photos": "Wybierz zdjęcia",
"file_upload": "Przesył plików",
"preparing": "Przygotowywanie",
- "processed_counts": "",
+ "processed_counts": "{{count, number}} / {{total, number}}",
"upload_reading_metadata_files": "Czytanie plików metadanych",
"upload_cancelling": "Anulowanie pozostałych przesłań",
"upload_done": "",
@@ -496,7 +496,7 @@
"yes_stop": "Tak, zatrzymaj",
"change_folder": "Zmień Folder",
"view_logs": "Wyświetl logi",
- "view_logs_message": "",
+ "view_logs_message": "Spowoduje to wyświetlenie logów debugowania, które możesz wysłać do nas na e-maila, aby pomóc w debugowaniu Twojego problemu.
Należy pamiętać, że nazwy plików będą dołączone, aby pomóc w śledzeniu problemów z konkretnymi plikami.
",
"weak_device_hint": "Przeglądarka, której używasz nie jest wystarczająco silna, aby zaszyfrować Twoje zdjęcia. Prosimy zalogować się do Ente na Twoim komputerze lub pobierz aplikacje mobilną/komputerową Ente.",
"drag_and_drop_hint": "Lub przeciągnij i upuść do okna Ente",
"authenticate": "Uwierzytelnij się",
diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json
index b1cf846414..627ac8aa91 100644
--- a/web/packages/base/locales/tr-TR/translation.json
+++ b/web/packages/base/locales/tr-TR/translation.json
@@ -162,7 +162,7 @@
"ok": "Tamam",
"success": "Başarılı",
"error": "Hata",
- "note": "",
+ "note": "Not",
"offline_message": "Çevrimdışısın, önbelleğe alınmış anılar gösteriliyor",
"install": "Kur",
"install_mobile_app": "Tüm fotoğraflarını otomatik olarak yedeklemek için Android veya iOS uygulamamızı yükle",
@@ -685,5 +685,5 @@
"person_favorites": "{{name}}'in favorileri",
"shared_favorites": "Paylaşılan favoriler",
"added_by_name": "{{name}} tarafından eklendi",
- "unowned_files_not_processed": ""
+ "unowned_files_not_processed": "Diğer kullanıcılar tarafından eklenen dosyalar işlenmedi"
}
diff --git a/web/packages/base/locales/zh-HK/translation.json b/web/packages/base/locales/zh-HK/translation.json
index 05fbcc6e4d..bdfed3f70f 100644
--- a/web/packages/base/locales/zh-HK/translation.json
+++ b/web/packages/base/locales/zh-HK/translation.json
@@ -77,7 +77,7 @@
"audio": "音訊",
"more": "更多",
"mouse_scroll": "",
- "pan": "",
+ "pan": "橫移",
"pinch": "",
"drag": "拖曳",
"tap_inside_image": "",