From c6a1c59ad6f81d38d8d053b269eae89aa3b96c7a Mon Sep 17 00:00:00 2001 From: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Date: Thu, 23 Nov 2023 12:39:07 +0300 Subject: [PATCH 1/3] feat(users): add unique constraint to clients name This commit adds a new migration to the users. The migration adds a unique constraint to the "clients" table in the database. This constraint ensures that the "name" column of the "clients" table is unique. --- users/postgres/init.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/users/postgres/init.go b/users/postgres/init.go index 5d48de9ca..4f11528d0 100644 --- a/users/postgres/init.go +++ b/users/postgres/init.go @@ -37,6 +37,15 @@ func Migration() *migrate.MemoryMigrationSource { `DROP TABLE IF EXISTS clients`, }, }, + { + Id: "clients_02", + Up: []string{ + `ALTER TABLE clients ADD CONSTRAINT clients_name_key UNIQUE (name)`, + }, + Down: []string{ + `ALTER TABLE clients DROP CONSTRAINT clients_name_key`, + }, + }, }, } } From 1c49b5b2ce8aee56a2481724d0f8fc981f59508f Mon Sep 17 00:00:00 2001 From: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Date: Thu, 23 Nov 2023 12:56:56 +0300 Subject: [PATCH 2/3] feat: add tests This commit adds constraints to the PostgreSQL database code for saving clients. Specifically, it ensures that the name column is not null and unique. The code includes test cases with descriptions, client objects, and expected errors to cover scenarios such as adding clients successfully. These changes enhance the functionality and reliability of the codebase. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> --- users/postgres/clients_test.go | 73 ++++++++++++++++++++++++---------- users/postgres/init.go | 6 ++- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/users/postgres/clients_test.go b/users/postgres/clients_test.go index 5244ebf3e..c5cfaaacc 100644 --- a/users/postgres/clients_test.go +++ b/users/postgres/clients_test.go @@ -9,6 +9,7 @@ import ( "strings" "testing" + "github.com/0x6flab/namegenerator" "github.com/absmach/magistrala/internal/testsutil" mgclients "github.com/absmach/magistrala/pkg/clients" "github.com/absmach/magistrala/pkg/errors" @@ -22,10 +23,9 @@ const ( ) var ( - invalidName = strings.Repeat("m", maxNameSize+10) - password = "$tr0ngPassw0rd" - clientIdentity = "client-identity@example.com" - clientName = "client name" + invalidName = strings.Repeat("m", maxNameSize+10) + password = "$tr0ngPassw0rd" + namesgen = namegenerator.NewNameGenerator() ) func TestClientsSave(t *testing.T) { @@ -37,6 +37,9 @@ func TestClientsSave(t *testing.T) { uid := testsutil.GenerateUUID(t) + name := namesgen.Generate() + clientIdentity := name + "@example.com" + cases := []struct { desc string client mgclients.Client @@ -46,7 +49,7 @@ func TestClientsSave(t *testing.T) { desc: "add new client successfully", client: mgclients.Client{ ID: uid, - Name: clientName, + Name: name, Credentials: mgclients.Credentials{ Identity: clientIdentity, Secret: password, @@ -61,9 +64,9 @@ func TestClientsSave(t *testing.T) { client: mgclients.Client{ ID: testsutil.GenerateUUID(t), Owner: uid, - Name: clientName, + Name: namesgen.Generate(), Credentials: mgclients.Credentials{ - Identity: "withowner-client@example.com", + Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()), Secret: password, }, Metadata: mgclients.Metadata{}, @@ -75,7 +78,21 @@ func TestClientsSave(t *testing.T) { desc: "add client with duplicate client identity", client: mgclients.Client{ ID: testsutil.GenerateUUID(t), - Name: clientName, + Name: namesgen.Generate(), + Credentials: mgclients.Credentials{ + Identity: clientIdentity, + Secret: password, + }, + Metadata: mgclients.Metadata{}, + Status: mgclients.EnabledStatus, + }, + err: errors.ErrConflict, + }, + { + desc: "add client with duplicate client name", + client: mgclients.Client{ + ID: testsutil.GenerateUUID(t), + Name: name, Credentials: mgclients.Credentials{ Identity: clientIdentity, Secret: password, @@ -89,9 +106,9 @@ func TestClientsSave(t *testing.T) { desc: "add client with invalid client id", client: mgclients.Client{ ID: invalidName, - Name: clientName, + Name: namesgen.Generate(), Credentials: mgclients.Credentials{ - Identity: "invalidid-client@example.com", + Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()), Secret: password, }, Metadata: mgclients.Metadata{}, @@ -105,7 +122,7 @@ func TestClientsSave(t *testing.T) { ID: testsutil.GenerateUUID(t), Name: invalidName, Credentials: mgclients.Credentials{ - Identity: "invalidname-client@example.com", + Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()), Secret: password, }, Metadata: mgclients.Metadata{}, @@ -119,7 +136,7 @@ func TestClientsSave(t *testing.T) { ID: testsutil.GenerateUUID(t), Owner: invalidName, Credentials: mgclients.Credentials{ - Identity: "invalidowner-client@example.com", + Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()), Secret: password, }, Metadata: mgclients.Metadata{}, @@ -131,7 +148,7 @@ func TestClientsSave(t *testing.T) { desc: "add client with invalid client identity", client: mgclients.Client{ ID: testsutil.GenerateUUID(t), - Name: clientName, + Name: namesgen.Generate(), Credentials: mgclients.Credentials{ Identity: invalidName, Secret: password, @@ -142,24 +159,36 @@ func TestClientsSave(t *testing.T) { err: errors.ErrMalformedEntity, }, { - desc: "add client with a missing client identity", + desc: "add client with a missing client name", client: mgclients.Client{ ID: testsutil.GenerateUUID(t), Credentials: mgclients.Credentials{ - Identity: "", + Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()), Secret: password, }, Metadata: mgclients.Metadata{}, }, err: nil, }, + { + desc: "add client with a missing client identity", + client: mgclients.Client{ + ID: testsutil.GenerateUUID(t), + Name: namesgen.Generate(), + Credentials: mgclients.Credentials{ + Secret: password, + }, + Metadata: mgclients.Metadata{}, + }, + err: nil, + }, { desc: "add client with a missing client secret", client: mgclients.Client{ - ID: testsutil.GenerateUUID(t), + ID: testsutil.GenerateUUID(t), + Name: namesgen.Generate(), Credentials: mgclients.Credentials{ - Identity: "missing-client-secret@example.com", - Secret: "", + Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()), }, Metadata: mgclients.Metadata{}, }, @@ -192,9 +221,9 @@ func TestIsPlatformAdmin(t *testing.T) { desc: "authorize check for super user", client: mgclients.Client{ ID: testsutil.GenerateUUID(t), - Name: clientName, + Name: namesgen.Generate(), Credentials: mgclients.Credentials{ - Identity: "admin@example.com", + Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()), Secret: password, }, Metadata: mgclients.Metadata{}, @@ -207,9 +236,9 @@ func TestIsPlatformAdmin(t *testing.T) { desc: "unauthorize user", client: mgclients.Client{ ID: testsutil.GenerateUUID(t), - Name: clientName, + Name: namesgen.Generate(), Credentials: mgclients.Credentials{ - Identity: clientIdentity, + Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()), Secret: password, }, Metadata: mgclients.Metadata{}, diff --git a/users/postgres/init.go b/users/postgres/init.go index 4f11528d0..f3cfc8992 100644 --- a/users/postgres/init.go +++ b/users/postgres/init.go @@ -40,10 +40,12 @@ func Migration() *migrate.MemoryMigrationSource { { Id: "clients_02", Up: []string{ - `ALTER TABLE clients ADD CONSTRAINT clients_name_key UNIQUE (name)`, + `ALTER TABLE clients ALTER COLUMN name SET NOT NULL`, + `ALTER TABLE clients ADD CONSTRAINT clients_name_unique UNIQUE (name)`, }, Down: []string{ - `ALTER TABLE clients DROP CONSTRAINT clients_name_key`, + `ALTER TABLE clients ALTER COLUMN name DROP NOT NULL`, + `ALTER TABLE clients DROP CONSTRAINT clients_name_unique`, }, }, }, From 1d38455bb5453bdbad15c1e6c88a4e76de4cc594 Mon Sep 17 00:00:00 2001 From: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Date: Thu, 23 Nov 2023 14:01:42 +0300 Subject: [PATCH 3/3] fix: no need for seperate migration This commit fixes an issue in the clients table in the PostgreSQL database. The name column is now set to NOT NULL and UNIQUE, ensuring that every client has a name and that the name is unique. This change improves data integrity and prevents any potential data inconsistencies. Note: This commit does not include the clients_02 migration as it has been removed. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> --- users/postgres/init.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/users/postgres/init.go b/users/postgres/init.go index f3cfc8992..3edda715f 100644 --- a/users/postgres/init.go +++ b/users/postgres/init.go @@ -20,7 +20,7 @@ func Migration() *migrate.MemoryMigrationSource { Up: []string{ `CREATE TABLE IF NOT EXISTS clients ( id VARCHAR(36) PRIMARY KEY, - name VARCHAR(254), + name VARCHAR(254) NOT NULL UNIQUE, owner_id VARCHAR(36), identity VARCHAR(254) NOT NULL UNIQUE, secret TEXT NOT NULL, @@ -37,17 +37,6 @@ func Migration() *migrate.MemoryMigrationSource { `DROP TABLE IF EXISTS clients`, }, }, - { - Id: "clients_02", - Up: []string{ - `ALTER TABLE clients ALTER COLUMN name SET NOT NULL`, - `ALTER TABLE clients ADD CONSTRAINT clients_name_unique UNIQUE (name)`, - }, - Down: []string{ - `ALTER TABLE clients ALTER COLUMN name DROP NOT NULL`, - `ALTER TABLE clients DROP CONSTRAINT clients_name_unique`, - }, - }, }, } }