diff --git a/.gitignore b/.gitignore index 3ff832a29..f90fd7219 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,4 @@ rules/test.yaml ignore/ vendor/ buf.lock -buf.yaml \ No newline at end of file +buf.yaml diff --git a/internal/group/groups.go b/internal/group/groups.go index 5946db86b..35bfd400a 100644 --- a/internal/group/groups.go +++ b/internal/group/groups.go @@ -3,14 +3,13 @@ package group import ( "context" "errors" - - "github.com/odpf/shield/internal/bootstrap/definition" - shieldError "github.com/odpf/shield/utils/errors" + "strings" "github.com/odpf/shield/internal/authz" + "github.com/odpf/shield/internal/bootstrap/definition" "github.com/odpf/shield/internal/permission" - "github.com/odpf/shield/model" + shieldError "github.com/odpf/shield/utils/errors" ) type Service struct { @@ -88,6 +87,7 @@ func (s Service) AddUsersToGroup(ctx context.Context, groupId string, userIds [] return []model.User{}, err } + groupId = strings.TrimSpace(groupId) group, err := s.Store.GetGroup(ctx, groupId) if err != nil { @@ -95,7 +95,7 @@ func (s Service) AddUsersToGroup(ctx context.Context, groupId string, userIds [] } isAuthorized, err := s.Permissions.CheckPermission(ctx, currentUser, model.Resource{ - Idxa: groupId, + Idxa: group.Id, Namespace: definition.TeamNamespace, }, definition.ManageTeamAction, @@ -130,6 +130,7 @@ func (s Service) RemoveUserFromGroup(ctx context.Context, groupId string, userId return []model.User{}, err } + groupId = strings.TrimSpace(groupId) group, err := s.Store.GetGroup(ctx, groupId) if err != nil { @@ -137,7 +138,7 @@ func (s Service) RemoveUserFromGroup(ctx context.Context, groupId string, userId } isAuthorized, err := s.Permissions.CheckPermission(ctx, currentUser, model.Resource{ - Idxa: groupId, + Idxa: group.Id, Namespace: definition.TeamNamespace, }, definition.ManageTeamAction, @@ -187,6 +188,7 @@ func (s Service) AddAdminsToGroup(ctx context.Context, groupId string, userIds [ return []model.User{}, err } + groupId = strings.TrimSpace(groupId) group, err := s.Store.GetGroup(ctx, groupId) if err != nil { @@ -194,7 +196,7 @@ func (s Service) AddAdminsToGroup(ctx context.Context, groupId string, userIds [ } isAuthorized, err := s.Permissions.CheckPermission(ctx, currentUser, model.Resource{ - Idxa: groupId, + Idxa: group.Id, Namespace: definition.TeamNamespace, }, definition.ManageTeamAction, @@ -234,6 +236,7 @@ func (s Service) RemoveAdminFromGroup(ctx context.Context, groupId string, userI return []model.User{}, err } + groupId = strings.TrimSpace(groupId) group, err := s.Store.GetGroup(ctx, groupId) if err != nil { @@ -241,7 +244,7 @@ func (s Service) RemoveAdminFromGroup(ctx context.Context, groupId string, userI } isAuthorized, err := s.Permissions.CheckPermission(ctx, currentUser, model.Resource{ - Idxa: groupId, + Idxa: group.Id, Namespace: definition.TeamNamespace, }, definition.ManageTeamAction, diff --git a/internal/org/org.go b/internal/org/org.go index eeec30737..192299ce9 100644 --- a/internal/org/org.go +++ b/internal/org/org.go @@ -3,12 +3,12 @@ package org import ( "context" "errors" + "strings" "github.com/odpf/shield/internal/bootstrap/definition" "github.com/odpf/shield/internal/permission" - shieldError "github.com/odpf/shield/utils/errors" - "github.com/odpf/shield/model" + shieldError "github.com/odpf/shield/utils/errors" ) type Service struct { @@ -75,6 +75,7 @@ func (s Service) AddAdmin(ctx context.Context, id string, userIds []string) ([]m return []model.User{}, err } + id = strings.TrimSpace(id) org, err := s.Store.GetOrg(ctx, id) if err != nil { @@ -82,7 +83,7 @@ func (s Service) AddAdmin(ctx context.Context, id string, userIds []string) ([]m } isAuthorized, err := s.Permissions.CheckPermission(ctx, currentUser, model.Resource{ - Idxa: id, + Idxa: org.Id, Namespace: definition.OrgNamespace, }, definition.ManageOrganizationAction, @@ -121,6 +122,7 @@ func (s Service) RemoveAdmin(ctx context.Context, id string, userId string) ([]m return []model.User{}, err } + id = strings.TrimSpace(id) org, err := s.Store.GetOrg(ctx, id) if err != nil { @@ -128,7 +130,7 @@ func (s Service) RemoveAdmin(ctx context.Context, id string, userId string) ([]m } isAuthorized, err := s.Permissions.CheckPermission(ctx, currentUser, model.Resource{ - Idxa: id, + Idxa: org.Id, Namespace: definition.OrgNamespace, }, definition.ManageOrganizationAction, diff --git a/internal/project/project.go b/internal/project/project.go index 8b9e1f31d..939518f47 100644 --- a/internal/project/project.go +++ b/internal/project/project.go @@ -3,12 +3,12 @@ package project import ( "context" "errors" + "strings" "github.com/odpf/shield/internal/bootstrap/definition" "github.com/odpf/shield/internal/permission" - shieldError "github.com/odpf/shield/utils/errors" - "github.com/odpf/shield/model" + shieldError "github.com/odpf/shield/utils/errors" ) type Service struct { @@ -83,6 +83,7 @@ func (s Service) AddAdmin(ctx context.Context, id string, userIds []string) ([]m return []model.User{}, err } + id = strings.TrimSpace(id) project, err := s.Store.GetProject(ctx, id) if err != nil { @@ -90,7 +91,7 @@ func (s Service) AddAdmin(ctx context.Context, id string, userIds []string) ([]m } isAuthorized, err := s.Permissions.CheckPermission(ctx, currentUser, model.Resource{ - Idxa: id, + Idxa: project.Id, Namespace: definition.ProjectNamespace, }, definition.ManageProjectAction, @@ -129,6 +130,7 @@ func (s Service) RemoveAdmin(ctx context.Context, id string, userId string) ([]m return []model.User{}, err } + id = strings.TrimSpace(id) project, err := s.Store.GetProject(ctx, id) if err != nil { @@ -136,7 +138,7 @@ func (s Service) RemoveAdmin(ctx context.Context, id string, userId string) ([]m } isAuthorized, err := s.Permissions.CheckPermission(ctx, currentUser, model.Resource{ - Idxa: id, + Idxa: project.Id, Namespace: definition.ProjectNamespace, }, definition.ManageProjectAction, diff --git a/store/postgres/groups.go b/store/postgres/groups.go index 89337bbd8..b4861c71f 100644 --- a/store/postgres/groups.go +++ b/store/postgres/groups.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "strings" "time" "github.com/doug-martin/goqu/v9" @@ -27,6 +28,7 @@ type Group struct { DeletedAt sql.NullTime `db:"deleted_at"` } +// *Get Groups Query func buildGetGroupsBySlugQuery(dialect goqu.DialectWrapper) (string, error) { getGroupsBySlugQuery, _, err := dialect.From(TABLE_GROUPS).Where(goqu.Ex{ "slug": goqu.L("$1"), @@ -35,6 +37,16 @@ func buildGetGroupsBySlugQuery(dialect goqu.DialectWrapper) (string, error) { return getGroupsBySlugQuery, err } +func buildGetGroupsByIdQuery(dialect goqu.DialectWrapper) (string, error) { + getGroupsByIdQuery, _, err := dialect.From(TABLE_GROUPS).Where(goqu.ExOr{ + "id": goqu.L("$1"), + "slug": goqu.L("$2"), + }).ToSQL() + + return getGroupsByIdQuery, err +} + +// *Create Group Query func buildCreateGroupQuery(dialect goqu.DialectWrapper) (string, error) { createGroupsQuery, _, err := dialect.Insert(TABLE_GROUPS).Rows( goqu.Record{ @@ -46,35 +58,13 @@ func buildCreateGroupQuery(dialect goqu.DialectWrapper) (string, error) { return createGroupsQuery, err } -func buildGetGroupsByIdQuery(dialect goqu.DialectWrapper) (string, error) { - getGroupsByIdQuery, _, err := dialect.From(TABLE_GROUPS).Where(goqu.Or( - goqu.C("id").Eq(goqu.L("$1")), - goqu.C("slug").Eq(goqu.L("$2")), - )).ToSQL() - - return getGroupsByIdQuery, err -} - +// *List Groups Query func buildListGroupsQuery(dialect goqu.DialectWrapper) (string, error) { listGroupsQuery, _, err := dialect.From(TABLE_GROUPS).ToSQL() return listGroupsQuery, err } -func buildUpdateGroupQuery(dialect goqu.DialectWrapper) (string, error) { - updateGroupQuery, _, err := dialect.Update(TABLE_GROUPS). - Set(goqu.Record{ - "name": goqu.L("$2"), - "slug": goqu.L("$3"), - "org_id": goqu.L("$4"), - "metadata": goqu.L("$5"), - "updated_at": goqu.L("now()"), - }).Where(goqu.Ex{"id": goqu.L("$1")}). - Returning(&Group{}).ToSQL() - - return updateGroupQuery, err -} - func buildListGroupUsersQuery(dialect goqu.DialectWrapper) (string, error) { listGroupUsersQuery, _, err := dialect.Select( goqu.I("u.id").As("id"), @@ -99,8 +89,8 @@ func buildListGroupUsersQuery(dialect goqu.DialectWrapper) (string, error) { func buildListUserGroupRelationsQuery(dialect goqu.DialectWrapper) (string, error) { listUserGroupRelationsQuery, _, err := dialect.From(TABLE_RELATION).Where(goqu.Ex{ - "subject_namespace_id": goqu.L(definition.UserNamespace.Id), - "object_namespace_id": goqu.L(definition.TeamNamespace.Id), + "subject_namespace_id": definition.UserNamespace.Id, + "object_namespace_id": definition.TeamNamespace.Id, "subject_id": goqu.L("$1"), "object_id": goqu.L("$2"), }).ToSQL() @@ -108,11 +98,44 @@ func buildListUserGroupRelationsQuery(dialect goqu.DialectWrapper) (string, erro return listUserGroupRelationsQuery, err } +// *Update Group Query +func buildUpdateGroupBySlugQuery(dialect goqu.DialectWrapper) (string, error) { + updateGroupQuery, _, err := dialect.Update(TABLE_GROUPS).Set( + goqu.Record{ + "name": goqu.L("$2"), + "slug": goqu.L("$3"), + "org_id": goqu.L("$4"), + "metadata": goqu.L("$5"), + "updated_at": goqu.L("now()"), + }).Where(goqu.Ex{ + "slug": goqu.L("$1"), + }).Returning(&Group{}).ToSQL() + + return updateGroupQuery, err +} + +func buildUpdateGroupByIdQuery(dialect goqu.DialectWrapper) (string, error) { + updateGroupQuery, _, err := dialect.Update(TABLE_GROUPS).Set( + goqu.Record{ + "name": goqu.L("$3"), + "slug": goqu.L("$4"), + "org_id": goqu.L("$5"), + "metadata": goqu.L("$6"), + "updated_at": goqu.L("now()"), + }).Where(goqu.ExOr{ + "id": goqu.L("$1"), + "slug": goqu.L("$2"), + }).Returning(&Group{}).ToSQL() + + return updateGroupQuery, err +} + func (s Store) GetGroup(ctx context.Context, id string) (model.Group, error) { var fetchedGroup Group var getGroupsQuery string var err error - var isUuid = isUUID(id) + id = strings.TrimSpace(id) + isUuid := isUUID(id) if isUuid { getGroupsQuery, err = buildGetGroupsByIdQuery(dialect) @@ -224,15 +247,30 @@ func (s Store) UpdateGroup(ctx context.Context, toUpdate model.Group) (model.Gro return model.Group{}, fmt.Errorf("%w: %s", parseErr, err) } - updateGroupQuery, err := buildUpdateGroupQuery(dialect) + var updateGroupQuery string + toUpdate.Id = strings.TrimSpace(toUpdate.Id) + isUuid := isUUID(toUpdate.Id) + + if isUuid { + updateGroupQuery, err = buildUpdateGroupByIdQuery(dialect) + } else { + updateGroupQuery, err = buildUpdateGroupBySlugQuery(dialect) + } if err != nil { return model.Group{}, fmt.Errorf("%w: %s", queryErr, err) } var updatedGroup Group - err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { - return s.DB.GetContext(ctx, &updatedGroup, updateGroupQuery, toUpdate.Id, toUpdate.Name, toUpdate.Slug, toUpdate.Organization.Id, marshaledMetadata) - }) + + if isUuid { + err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { + return s.DB.GetContext(ctx, &updatedGroup, updateGroupQuery, toUpdate.Id, toUpdate.Id, toUpdate.Name, toUpdate.Slug, toUpdate.Organization.Id, marshaledMetadata) + }) + } else { + err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { + return s.DB.GetContext(ctx, &updatedGroup, updateGroupQuery, toUpdate.Id, toUpdate.Name, toUpdate.Slug, toUpdate.Organization.Id, marshaledMetadata) + }) + } if errors.Is(err, sql.ErrNoRows) { return model.Group{}, group.GroupDoesntExist @@ -254,6 +292,13 @@ func (s Store) ListGroupUsers(ctx context.Context, groupId string, roleId string role = roleId } + groupId = strings.TrimSpace(groupId) //groupId can be uuid or slug + fetchedGroup, err := s.GetGroup(ctx, groupId) + if err != nil { + return []model.User{}, err + } + groupId = fetchedGroup.Id + listGroupUsersQuery, err := buildListGroupUsersQuery(dialect) if err != nil { return []model.User{}, fmt.Errorf("%w: %s", queryErr, err) @@ -294,6 +339,13 @@ func (s Store) ListUserGroupRelations(ctx context.Context, userId string, groupI return []model.Relation{}, fmt.Errorf("%w: %s", queryErr, err) } + groupId = strings.TrimSpace(groupId) + fetchedGroup, err := s.GetGroup(ctx, groupId) + if err != nil { + return []model.Relation{}, err + } + groupId = fetchedGroup.Id + err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { return s.DB.SelectContext(ctx, &fetchedRelations, listUserGroupRelationsQuery, userId, groupId) }) diff --git a/store/postgres/org.go b/store/postgres/org.go index 2be27672b..0d660beeb 100644 --- a/store/postgres/org.go +++ b/store/postgres/org.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "strings" "time" "github.com/doug-martin/goqu/v9" @@ -25,6 +26,7 @@ type Organization struct { DeletedAt sql.NullTime `db:"deleted_at"` } +// *Get Organizations Query func buildGetOrganizationsBySlugQuery(dialect goqu.DialectWrapper) (string, error) { getOrganizationsBySlugQuery, _, err := dialect.From(TABLE_ORG).Where(goqu.Ex{ "slug": goqu.L("$1"), @@ -34,14 +36,14 @@ func buildGetOrganizationsBySlugQuery(dialect goqu.DialectWrapper) (string, erro } func buildGetOrganizationsByIdQuery(dialect goqu.DialectWrapper) (string, error) { - getOrganizationsByIdQuery, _, err := dialect.From(TABLE_ORG).Where(goqu.Or( - goqu.C("id").Eq(goqu.L("$1")), - goqu.C("slug").Eq(goqu.L("$2")), - )).ToSQL() - + getOrganizationsByIdQuery, _, err := dialect.From(TABLE_ORG).Where(goqu.ExOr{ + "id": goqu.L("$1"), + "slug": goqu.L("$2"), + }).ToSQL() return getOrganizationsByIdQuery, err } +// *Create Organization Query func buildCreateOrganizationQuery(dialect goqu.DialectWrapper) (string, error) { createOrganizationQuery, _, err := dialect.Insert(TABLE_ORG).Rows( goqu.Record{ @@ -52,24 +54,14 @@ func buildCreateOrganizationQuery(dialect goqu.DialectWrapper) (string, error) { return createOrganizationQuery, err } + +// *List Organization Query func buildListOrganizationsQuery(dialect goqu.DialectWrapper) (string, error) { listOrganizationsQuery, _, err := dialect.From(TABLE_ORG).ToSQL() return listOrganizationsQuery, err } -func buildUpdateOrganizationQuery(dialect goqu.DialectWrapper) (string, error) { - updateOrganizationQuery, _, err := dialect.Update(TABLE_ORG).Set( - goqu.Record{ - "name": goqu.L("$2"), - "slug": goqu.L("$3"), - "metadata": goqu.L("$4"), - "updated_at": goqu.L("now()"), - }).Where(goqu.Ex{ - "id": goqu.L("$1"), - }).Returning(&Organization{}).ToSQL() - return updateOrganizationQuery, err -} func buildListOrganizationAdmins(dialect goqu.DialectWrapper) (string, error) { listOrganizationAdmins, _, err := dialect.Select( goqu.I("u.id").As("id"), @@ -91,11 +83,42 @@ func buildListOrganizationAdmins(dialect goqu.DialectWrapper) (string, error) { return listOrganizationAdmins, err } +// *Update Organization Query +func buildUpdateOrganizationBySlugQuery(dialect goqu.DialectWrapper) (string, error) { + updateOrganizationQuery, _, err := dialect.Update(TABLE_ORG).Set( + goqu.Record{ + "name": goqu.L("$2"), + "slug": goqu.L("$3"), + "metadata": goqu.L("$4"), + "updated_at": goqu.L("now()"), + }).Where(goqu.Ex{ + "slug": goqu.L("$1"), + }).Returning(&Organization{}).ToSQL() + + return updateOrganizationQuery, err +} + +func buildUpdateOrganizationByIdQuery(dialect goqu.DialectWrapper) (string, error) { + updateOrganizationQuery, _, err := dialect.Update(TABLE_ORG).Set( + goqu.Record{ + "name": goqu.L("$3"), + "slug": goqu.L("$4"), + "metadata": goqu.L("$5"), + "updated_at": goqu.L("now()"), + }).Where(goqu.ExOr{ + "slug": goqu.L("$1"), + "id": goqu.L("$2"), + }).Returning(&Organization{}).ToSQL() + + return updateOrganizationQuery, err +} + func (s Store) GetOrg(ctx context.Context, id string) (model.Organization, error) { var fetchedOrg Organization var getOrganizationsQuery string var err error - var isUuid = isUUID(id) + id = strings.TrimSpace(id) + isUuid := isUUID(id) if isUuid { getOrganizationsQuery, err = buildGetOrganizationsByIdQuery(dialect) @@ -203,15 +226,27 @@ func (s Store) UpdateOrg(ctx context.Context, toUpdate model.Organization) (mode return model.Organization{}, fmt.Errorf("%w: %s", parseErr, err) } - updateOrganizationQuery, err := buildUpdateOrganizationQuery(dialect) + var updateOrganizationQuery string + isUuid := isUUID(toUpdate.Id) + + if isUuid { + updateOrganizationQuery, err = buildUpdateOrganizationByIdQuery(dialect) + } else { + updateOrganizationQuery, err = buildUpdateOrganizationBySlugQuery(dialect) + } if err != nil { return model.Organization{}, fmt.Errorf("%w: %s", queryErr, err) } - err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { - return s.DB.GetContext(ctx, &updatedOrg, updateOrganizationQuery, toUpdate.Id, toUpdate.Name, toUpdate.Slug, marshaledMetadata) - }) - + if isUuid { + err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { + return s.DB.GetContext(ctx, &updatedOrg, updateOrganizationQuery, toUpdate.Id, toUpdate.Id, toUpdate.Name, toUpdate.Slug, marshaledMetadata) + }) + } else { + err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { + return s.DB.GetContext(ctx, &updatedOrg, updateOrganizationQuery, toUpdate.Id, toUpdate.Name, toUpdate.Slug, marshaledMetadata) + }) + } if err != nil { return model.Organization{}, fmt.Errorf("%s: %w", txnErr, err) } @@ -231,6 +266,13 @@ func (s Store) ListOrgAdmins(ctx context.Context, id string) ([]model.User, erro return []model.User{}, fmt.Errorf("%w: %s", queryErr, err) } + id = strings.TrimSpace(id) + fetchedOrg, err := s.GetOrg(ctx, id) + if err != nil { + return []model.User{}, err + } + id = fetchedOrg.Id + err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { return s.DB.SelectContext(ctx, &fetchedUsers, listOrganizationAdmins, id) }) diff --git a/store/postgres/postgres.go b/store/postgres/postgres.go index e87a44450..ba7cdf9f0 100644 --- a/store/postgres/postgres.go +++ b/store/postgres/postgres.go @@ -2,7 +2,6 @@ package postgres import ( "errors" - "fmt" "github.com/doug-martin/goqu/v9" _ "github.com/doug-martin/goqu/v9/dialect/postgres" @@ -44,6 +43,5 @@ func NewStore(db *sql.SQL) Store { func isUUID(key string) bool { _, err := uuid.Parse(key) - fmt.Println(err) return err == nil } diff --git a/store/postgres/projects.go b/store/postgres/projects.go index 51b9806f0..5719d05fb 100644 --- a/store/postgres/projects.go +++ b/store/postgres/projects.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "strings" "time" "github.com/doug-martin/goqu/v9" @@ -26,6 +27,7 @@ type Project struct { DeletedAt sql.NullTime `db:"deleted_at"` } +// *Get Projects Query func buildGetProjectsBySlugQuery(dialect goqu.DialectWrapper) (string, error) { getProjectsBySlugQuery, _, err := dialect.From(TABLE_PROJECTS).Where(goqu.Ex{ "slug": goqu.L("$1"), @@ -35,13 +37,15 @@ func buildGetProjectsBySlugQuery(dialect goqu.DialectWrapper) (string, error) { } func buildGetProjectsByIdQuery(dialect goqu.DialectWrapper) (string, error) { - getProjectsByIdQuery, _, err := dialect.From(TABLE_PROJECTS).Where(goqu.Or( - goqu.C("id").Eq(goqu.L("$1")), - goqu.C("slug").Eq(goqu.L("$2")), - )).ToSQL() + getProjectsByIdQuery, _, err := dialect.From(TABLE_PROJECTS).Where(goqu.ExOr{ + "id": goqu.L("$1"), + "slug": goqu.L("$2"), + }).ToSQL() return getProjectsByIdQuery, err } + +// *Create Project Query func buildCreateProjectQuery(dialect goqu.DialectWrapper) (string, error) { createProjectQuery, _, err := dialect.Insert(TABLE_PROJECTS).Rows( goqu.Record{ @@ -53,25 +57,8 @@ func buildCreateProjectQuery(dialect goqu.DialectWrapper) (string, error) { return createProjectQuery, err } -func buildListProjectQuery(dialect goqu.DialectWrapper) (string, error) { - listProjectQuery, _, err := dialect.From(TABLE_PROJECTS).ToSQL() - - return listProjectQuery, err -} -func buildUpdateProjectQuery(dialect goqu.DialectWrapper) (string, error) { - updateProjectQuery, _, err := dialect.Update(TABLE_PROJECTS).Set( - goqu.Record{ - "name": goqu.L("$2"), - "slug": goqu.L("$3"), - "org_id": goqu.L("$4"), - "metadata": goqu.L("$5"), - "updated_at": goqu.L("now()"), - }).Where(goqu.Ex{ - "id": goqu.L("$1"), - }).Returning(&Project{}).ToSQL() - return updateProjectQuery, err -} +// *List Project Query func buildListProjectAdminsQuery(dialect goqu.DialectWrapper) (string, error) { listProjectAdminsQuery, _, err := dialect.Select( goqu.I("u.id").As("id"), @@ -93,11 +80,50 @@ func buildListProjectAdminsQuery(dialect goqu.DialectWrapper) (string, error) { return listProjectAdminsQuery, err } +func buildListProjectQuery(dialect goqu.DialectWrapper) (string, error) { + listProjectQuery, _, err := dialect.From(TABLE_PROJECTS).ToSQL() + + return listProjectQuery, err +} + +// *Update Project Query +func buildUpdateProjectBySlugQuery(dialect goqu.DialectWrapper) (string, error) { + updateProjectQuery, _, err := dialect.Update(TABLE_PROJECTS).Set( + goqu.Record{ + "name": goqu.L("$2"), + "slug": goqu.L("$3"), + "org_id": goqu.L("$4"), + "metadata": goqu.L("$5"), + "updated_at": goqu.L("now()"), + }).Where(goqu.Ex{ + "slug": goqu.L("$1"), + }).Returning(&Project{}).ToSQL() + + return updateProjectQuery, err +} + +func buildUpdateProjectByIdQuery(dialect goqu.DialectWrapper) (string, error) { + updateProjectQuery, _, err := dialect.Update(TABLE_PROJECTS).Set( + goqu.Record{ + "name": goqu.L("$3"), + "slug": goqu.L("$4"), + "org_id": goqu.L("$5"), + "metadata": goqu.L("$6"), + "updated_at": goqu.L("now()"), + }).Where(goqu.ExOr{ + "id": goqu.L("$1"), + "slug": goqu.L("$2"), + }).Returning(&Project{}).ToSQL() + + return updateProjectQuery, err +} + func (s Store) GetProject(ctx context.Context, id string) (model.Project, error) { var fetchedProject Project var getProjectsQuery string var err error - var isUuid = isUUID(id) + id = strings.TrimSpace(id) + isUuid := isUUID(id) if isUuid { getProjectsQuery, err = buildGetProjectsByIdQuery(dialect) @@ -209,15 +235,28 @@ func (s Store) UpdateProject(ctx context.Context, toUpdate model.Project) (model return model.Project{}, fmt.Errorf("%w: %s", parseErr, err) } - updateProjectQuery, err := buildUpdateProjectQuery(dialect) + var updateProjectQuery string + toUpdate.Id = strings.TrimSpace(toUpdate.Id) + isUuid := isUUID(toUpdate.Id) + + if isUuid { + updateProjectQuery, err = buildUpdateProjectByIdQuery(dialect) + } else { + updateProjectQuery, err = buildUpdateProjectBySlugQuery(dialect) + } if err != nil { return model.Project{}, fmt.Errorf("%w: %s", queryErr, err) } - err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { - return s.DB.GetContext(ctx, &updatedProject, updateProjectQuery, toUpdate.Id, toUpdate.Name, toUpdate.Slug, toUpdate.Organization.Id, marshaledMetadata) - }) - + if isUuid { + err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { + return s.DB.GetContext(ctx, &updatedProject, updateProjectQuery, toUpdate.Id, toUpdate.Id, toUpdate.Name, toUpdate.Slug, toUpdate.Organization.Id, marshaledMetadata) + }) + } else { + err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { + return s.DB.GetContext(ctx, &updatedProject, updateProjectQuery, toUpdate.Id, toUpdate.Name, toUpdate.Slug, toUpdate.Organization.Id, marshaledMetadata) + }) + } if errors.Is(err, sql.ErrNoRows) { return model.Project{}, project.ProjectDoesntExist } else if err != nil && fmt.Sprintf("%s", err.Error()[0:38]) == "pq: invalid input syntax for type uuid" { @@ -244,6 +283,13 @@ func (s Store) ListProjectAdmins(ctx context.Context, id string) ([]model.User, return []model.User{}, fmt.Errorf("%w: %s", queryErr, err) } + id = strings.TrimSpace(id) + fetchedProject, err := s.GetProject(ctx, id) + if err != nil { + return []model.User{}, err + } + id = fetchedProject.Id + err = s.DB.WithTimeout(ctx, func(ctx context.Context) error { return s.DB.SelectContext(ctx, &fetchedUsers, listProjectAdminsQuery, id) }) diff --git a/store/postgres/relation.go b/store/postgres/relation.go index 3071a805e..b24c5acef 100644 --- a/store/postgres/relation.go +++ b/store/postgres/relation.go @@ -27,6 +27,7 @@ type Relation struct { NamespaceId sql.NullString `db:"namespace_id"` CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` + DeletedAt sql.NullTime `db:"deleted_at"` } type relationCols struct { diff --git a/store/postgres/user.go b/store/postgres/user.go index 5d4e1757b..cfde0b6d3 100644 --- a/store/postgres/user.go +++ b/store/postgres/user.go @@ -48,7 +48,7 @@ func buildGetUserQuery(dialect goqu.DialectWrapper) (string, error) { } func buildGetUsersByIdsQuery(dialect goqu.DialectWrapper) (string, error) { - getUsersByIdsQuery, _, err := dialect.From("users").Prepared(true).Where( + getUsersByIdsQuery, _, err := goqu.From("users").Prepared(true).Where( goqu.C("id").In("id_PH")).ToSQL() return getUsersByIdsQuery, err @@ -266,7 +266,6 @@ func (s Store) GetUsersByIds(ctx context.Context, userIds []string) ([]model.Use var query string var args []interface{} query, args, err = sqlx.In(getUsersByIdsQuery, userIds) - if err != nil { return []model.User{}, fmt.Errorf("%w: %s", dbErr, err) }