From 28274816c97df39c01c01b9287ac83c3e5e8e3b0 Mon Sep 17 00:00:00 2001
From: ko_oler <kooler89@gmail.com>
Date: Mon, 1 Apr 2024 12:34:51 +0300
Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?=
 =?UTF-8?q?=D0=BD=20OID=20=D0=B4=D0=BB=D1=8F=20Locales?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 id/bson_test.go           |  4 ++
 id/locale.go              | 63 ++++++++++++++++++++++++++++
 id/object_id_test.go      | 12 ++++++
 id/registry.go            |  1 +
 id/system/system.go       |  7 ++++
 id/test/object_id_test.go | 87 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 174 insertions(+)
 create mode 100644 id/locale.go

diff --git a/id/bson_test.go b/id/bson_test.go
index 7ae62ccb..c5fca60f 100644
--- a/id/bson_test.go
+++ b/id/bson_test.go
@@ -41,6 +41,10 @@ func TestID_MarshalUnmarshalBSON(t *testing.T) {
 			name: "RoleID",
 			id:   &ObjectId{Descriptor: &RoleId{RoleID: "1", SpaceId: SpaceId{SpaceID: "1"}}},
 		},
+		{
+			name: "LocaleID",
+			id:   &ObjectId{Descriptor: &LocaleID{LocaleID: "1", SpaceId: SpaceId{SpaceID: "1"}}},
+		},
 		{
 			name: "CollectionId",
 			id:   &ObjectId{Descriptor: &CollectionId{CollectionID: "1", EnvironmentId: EnvironmentId{EnvironmentID: "1", SpaceId: SpaceId{SpaceID: "1"}}}},
diff --git a/id/locale.go b/id/locale.go
new file mode 100644
index 00000000..710bc5e3
--- /dev/null
+++ b/id/locale.go
@@ -0,0 +1,63 @@
+package id
+
+import "fmt"
+
+const (
+	Locale        = "locale"
+	LocalesPrefix = "locales"
+)
+
+var _ Descriptor = &LocaleID{}
+
+type LocaleID struct {
+	SpaceId
+	LocaleID string `json:"locale_id,omitempty" bson:"locale_id,omitempty"`
+}
+
+func (id *LocaleID) New() Descriptor {
+	return &LocaleID{}
+}
+
+func (id *LocaleID) Type() string { return Locale }
+
+func (id *LocaleID) String() string {
+	return Join(id.SpaceId.String(), LocalesPrefix, id.LocaleID)
+}
+
+func (id *LocaleID) FromParts(parts []string) error {
+	if len(parts) != 4 || parts[2] != LocalesPrefix {
+		return ErrInvalidID
+	}
+	if err := id.SpaceId.FromParts(parts[:2]); err != nil {
+		return err
+	}
+	id.LocaleID = parts[3]
+	return nil
+}
+
+func (id *LocaleID) Map() map[string]any {
+	m := id.SpaceId.Map()
+	m["locale_id"] = id.LocaleID
+	m["type"] = Locale
+	return m
+}
+
+func (id *LocaleID) FromMap(m map[string]any) error {
+	id.LocaleID = m["locale_id"].(string)
+	if id.LocaleID == "" {
+		return fmt.Errorf("%w: LocaleID required", ErrInvalidID)
+	}
+	return id.SpaceId.FromMap(m)
+}
+
+func (id *LocaleID) Validate() error {
+	if id.LocaleID == "" {
+		return fmt.Errorf("%w: LocaleID required", ErrInvalidID)
+	}
+
+	return id.SpaceId.Validate()
+}
+
+func NewLocaleId(spaceID, id string) *ObjectId {
+	return &ObjectId{Descriptor: &LocaleID{SpaceId: SpaceId{SpaceID: spaceID}, LocaleID: id}}
+}
diff --git a/id/object_id_test.go b/id/object_id_test.go
index 4f8d0181..56a2c104 100644
--- a/id/object_id_test.go
+++ b/id/object_id_test.go
@@ -45,6 +45,11 @@ func Test_ParseID(t *testing.T) {
 			id:     "/spaces/<space_id>/roles/<role_id>",
 			result: MustObjectId("/spaces/<space_id>/roles/<role_id>"),
 		},
+		{
+			name:   "LocaleID",
+			id:     "/spaces/<space_id>/locales/<locale_id>",
+			result: MustObjectId("/spaces/<space_id>/locales/<locale_id>"),
+		},
 		{
 			name:   "EnvironmentID",
 			id:     "/spaces/<space_id>/envs/<env_id>",
@@ -165,6 +170,13 @@ func Test_Map(t *testing.T) {
 				RoleID:  "<role_id>",
 			}},
 		},
+		{
+			name: "LocaleID",
+			id: &ObjectId{Descriptor: &LocaleID{
+				SpaceId:  SpaceId{SpaceID: "<space_id>"},
+				LocaleID: "<locale_id>",
+			}},
+		},
 		{
 			name: "EnvironmentID",
 			id: &ObjectId{Descriptor: &EnvironmentId{
diff --git a/id/registry.go b/id/registry.go
index 0ffec024..17c86e4b 100644
--- a/id/registry.go
+++ b/id/registry.go
@@ -110,6 +110,7 @@ func RegisterSystemIds(r *Registry) {
 	r.RegisterDescriptor(&SystemId{})
 	r.RegisterDescriptor(&ServiceId{})
 	r.RegisterDescriptor(&OrganizationId{})
+	r.RegisterDescriptor(&LocaleID{})
 }
 
 func GetRegistry() *Registry {
diff --git a/id/system/system.go b/id/system/system.go
index 81006292..c33995d9 100644
--- a/id/system/system.go
+++ b/id/system/system.go
@@ -10,6 +10,7 @@ import (
 	"git.perx.ru/perxis/perxis-go/pkg/collections"
 	"git.perx.ru/perxis/perxis-go/pkg/environments"
 	"git.perx.ru/perxis/perxis-go/pkg/items"
+	"git.perx.ru/perxis/perxis-go/pkg/locales"
 	"git.perx.ru/perxis/perxis-go/pkg/organizations"
 	"git.perx.ru/perxis/perxis-go/pkg/roles"
 	"git.perx.ru/perxis/perxis-go/pkg/spaces"
@@ -74,6 +75,11 @@ func Handler(obj any) *id.ObjectId {
 		var i id.UserId
 		i.UserID = val.GetID(context.TODO())
 		return id.MustObjectId(&i)
+	case *locales.Locale:
+		var i id.LocaleID
+		i.SpaceID = val.SpaceID
+		i.LocaleID = val.ID
+		return id.MustObjectId(&i)
 	}
 	return nil
 }
@@ -92,6 +98,7 @@ func Register(r *id.Registry) {
 	r.RegisterObjectHandler(reflect.TypeOf(&auth.ClientPrincipal{}), Handler)
 	r.RegisterObjectHandler(reflect.TypeOf(&auth.SystemPrincipal{}), Handler)
 	r.RegisterObjectHandler(reflect.TypeOf(&auth.Anonymous{}), Handler)
+	r.RegisterObjectHandler(reflect.TypeOf(&locales.Locale{}), Handler)
 }
 
 func init() {
diff --git a/id/test/object_id_test.go b/id/test/object_id_test.go
index ec2cd931..e29328dd 100644
--- a/id/test/object_id_test.go
+++ b/id/test/object_id_test.go
@@ -9,6 +9,7 @@ import (
 	"git.perx.ru/perxis/perxis-go/pkg/collections"
 	"git.perx.ru/perxis/perxis-go/pkg/environments"
 	"git.perx.ru/perxis/perxis-go/pkg/items"
+	"git.perx.ru/perxis/perxis-go/pkg/locales"
 	"git.perx.ru/perxis/perxis-go/pkg/organizations"
 	"git.perx.ru/perxis/perxis-go/pkg/roles"
 	"git.perx.ru/perxis/perxis-go/pkg/spaces"
@@ -799,3 +800,89 @@ func Test_RevisionId(t *testing.T) {
 		})
 	}
 }
+
+func Test_LocaleId(t *testing.T) {
+
+	tests := []struct {
+		name   string
+		in     any
+		out    string
+		result *id.ObjectId
+		err    error
+	}{
+		{
+			name: "valid string",
+			in:   "/spaces/<space_id>/locales/<locale_id>",
+			result: &id.ObjectId{Descriptor: &id.LocaleID{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				LocaleID: "<locale_id>",
+			}},
+		},
+		{
+			name: "invalid string",
+			in:   "/locales/<locale_id>",
+			result: &id.ObjectId{Descriptor: &id.LocaleID{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				LocaleID: "<locale_id>",
+			}},
+			err: id.ErrInvalidID,
+		},
+		{
+			name: "valid object",
+			in:   &locales.Locale{SpaceID: "<space_id>", ID: "<locale_id>"},
+			out:  "/spaces/<space_id>/locales/<locale_id>",
+			result: &id.ObjectId{Descriptor: &id.LocaleID{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				LocaleID: "<locale_id>",
+			}},
+		},
+		{
+			name: "valid map",
+			in:   map[string]any{"type": "locale", "space_id": "<space_id>", "locale_id": "<locale_id>"},
+			out:  "/spaces/<space_id>/locales/<locale_id>",
+			result: &id.ObjectId{Descriptor: &id.LocaleID{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				LocaleID: "<locale_id>",
+			}},
+		},
+		{
+			name: "invalid map 1",
+			in:   map[string]any{"type": "client", "space_id": "<space_id>"},
+			out:  "/spaces/<space_id>/locales/<locale_id>",
+			result: &id.ObjectId{Descriptor: &id.LocaleID{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				LocaleID: "<locale_id>",
+			}},
+			err: id.ErrInvalidID,
+		},
+		{
+			name: "invalid map 2",
+			in:   map[string]any{"type": "locale", "locale_id": "<locale_id>"},
+			out:  "/spaces/<space_id>/locales/<locale_id>",
+			result: &id.ObjectId{Descriptor: &id.LocaleID{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				LocaleID: "<locale_id>",
+			}},
+			err: id.ErrInvalidID,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			i, err := id.NewObjectId(tt.in)
+
+			if tt.err != nil {
+				require.ErrorIs(t, err, tt.err)
+				return
+			}
+
+			require.NoError(t, err)
+			require.Equal(t, tt.result, i)
+			if tt.out == "" {
+				require.Equal(t, tt.in, i.String())
+			} else {
+				require.Equal(t, tt.out, i.String())
+			}
+		})
+	}
+}
-- 
GitLab