mirror of
https://github.com/paralus/paralus.git
synced 2026-02-14 17:49:51 +00:00
265 lines
8.0 KiB
Go
265 lines
8.0 KiB
Go
package dao
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/paralus/paralus/internal/models"
|
|
userv3 "github.com/paralus/paralus/proto/types/userpb/v3"
|
|
"github.com/uptrace/bun"
|
|
)
|
|
|
|
func GetUserType(ctx context.Context, db bun.IDB, id uuid.UUID) (string, error) {
|
|
var user = models.KratosIdentities{}
|
|
q := db.NewSelect().Model(&user)
|
|
q.Relation("IdentityCredential").
|
|
Relation("IdentityCredential.IdentityCredentialType")
|
|
q.Where("id = ?", id)
|
|
err := q.Scan(ctx)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return user.IdentityCredential.IdentityCredentialType.Name, nil
|
|
}
|
|
|
|
func GetGroups(ctx context.Context, db bun.IDB, id uuid.UUID) ([]models.Group, error) {
|
|
var entities = []models.Group{}
|
|
err := db.NewSelect().Model(&entities).
|
|
Join(`JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id`).
|
|
Where("authsrv_groupaccount.account_id = ?", id).
|
|
Where("authsrv_groupaccount.trash = ?", false).
|
|
Scan(ctx)
|
|
return entities, err
|
|
}
|
|
|
|
func GetUserRoles(ctx context.Context, db bun.IDB, id uuid.UUID) ([]*userv3.ProjectNamespaceRole, error) {
|
|
// Could possibly union them later for some speedup
|
|
// TODO filter by org and partner
|
|
var r = []*userv3.ProjectNamespaceRole{}
|
|
err := db.NewSelect().Table("authsrv_accountresourcerole").
|
|
ColumnExpr("authsrv_resourcerole.name as role").
|
|
Join(`JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id`).
|
|
Where("authsrv_accountresourcerole.account_id = ?", id).
|
|
Where("authsrv_resourcerole.trash = ?", false).
|
|
Where("authsrv_accountresourcerole.trash = ?", false).
|
|
Scan(ctx, &r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var pr = []*userv3.ProjectNamespaceRole{}
|
|
err = db.NewSelect().Table("authsrv_projectaccountresourcerole").
|
|
ColumnExpr("distinct authsrv_resourcerole.name as role, authsrv_project.name as project").
|
|
Join(`JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id`).
|
|
Join(`JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id`).
|
|
Where("authsrv_projectaccountresourcerole.account_id = ?", id).
|
|
Where("authsrv_project.trash = ?", false).
|
|
Where("authsrv_resourcerole.trash = ?", false).
|
|
Where("authsrv_projectaccountresourcerole.trash = ?", false).
|
|
Scan(ctx, &pr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var pnr = []*userv3.ProjectNamespaceRole{}
|
|
err = db.NewSelect().Table("authsrv_projectaccountnamespacerole").
|
|
ColumnExpr("authsrv_resourcerole.name as role, authsrv_project.name as project, namespace").
|
|
Join(`JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id`).
|
|
Join(`JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id`). // also need a namespace join
|
|
Where("authsrv_projectaccountnamespacerole.account_id = ?", id).
|
|
Where("authsrv_project.trash = ?", false).
|
|
Where("authsrv_resourcerole.trash = ?", false).
|
|
Where("authsrv_projectaccountnamespacerole.trash = ?", false).
|
|
Scan(ctx, &pnr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return append(append(r, pr...), pnr...), err
|
|
}
|
|
|
|
func GetQueryFilteredUsers(ctx context.Context, db bun.IDB, partner, org, group, role uuid.UUID, projects []uuid.UUID) ([]uuid.UUID, error) {
|
|
p := []models.AccountPermission{}
|
|
q := db.NewSelect().Model(&p).ColumnExpr("DISTINCT account_id")
|
|
|
|
q.Where("partner_id = ?", partner).
|
|
Where("organization_id = ?", org)
|
|
|
|
if role != uuid.Nil {
|
|
q.Where("role_id = ?", role)
|
|
}
|
|
if len(projects) != 0 {
|
|
q.Where("project_id IN (?)", bun.In(projects))
|
|
}
|
|
|
|
if group != uuid.Nil {
|
|
// If the group is not mapped to a project, we won't be able
|
|
// to pick it from sentry table and that is why we have to do
|
|
// this.
|
|
gaccs := []models.GroupAccount{}
|
|
subq := db.NewSelect().
|
|
Model(&gaccs).
|
|
ColumnExpr("DISTINCT account_id").
|
|
Where("group_id = ?", group).
|
|
Where("trash = ?", false)
|
|
|
|
q = q.Where("account_id IN (?)", subq)
|
|
}
|
|
err := q.Scan(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
acc := []uuid.UUID{}
|
|
for _, a := range p {
|
|
acc = append(acc, a.AccountId)
|
|
}
|
|
return acc, nil
|
|
|
|
}
|
|
|
|
func listFilteredUsersQuery(
|
|
q *bun.SelectQuery,
|
|
fusers []uuid.UUID,
|
|
query string,
|
|
utype string,
|
|
orderBy string,
|
|
order string,
|
|
limit int,
|
|
offset int,
|
|
) *bun.SelectQuery {
|
|
if utype != "" {
|
|
q = q.Relation("IdentityCredential", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.ExcludeColumn("*")
|
|
}).
|
|
Relation("IdentityCredential.IdentityCredentialType", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.ExcludeColumn("*").Where("name = ?", utype)
|
|
})
|
|
}
|
|
|
|
if len(fusers) > 0 {
|
|
// filter with precomputed users if we have any
|
|
q = q.Where("identities.id IN (?)", bun.In(fusers))
|
|
}
|
|
if query != "" {
|
|
q = q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
q = q.Where("traits ->> 'email' ILIKE ?", "%"+query+"%") // XXX: ILIKE is not-standard sql
|
|
q = q.WhereOr("traits ->> 'first_name' ILIKE ?", "%"+query+"%")
|
|
q = q.WhereOr("traits ->> 'last_name' ILIKE ?", "%"+query+"%")
|
|
return q
|
|
})
|
|
}
|
|
if orderBy != "" && order != "" {
|
|
q = q.Order("traits ->> '" + orderBy + "' " + order)
|
|
}
|
|
if limit > 0 {
|
|
q = q.Limit(limit)
|
|
}
|
|
if offset > 0 {
|
|
q = q.Offset(offset)
|
|
}
|
|
return q
|
|
}
|
|
|
|
// ListFilteredUsers will return the list of users fileterd by query
|
|
func ListFilteredUsers(
|
|
ctx context.Context,
|
|
db bun.IDB,
|
|
fusers []uuid.UUID,
|
|
query string,
|
|
utype string,
|
|
orderBy string,
|
|
order string,
|
|
limit int,
|
|
offset int,
|
|
) ([]models.KratosIdentities, error) {
|
|
var users []models.KratosIdentities
|
|
q := db.NewSelect().Model(&users)
|
|
listFilteredUsersQuery(q, fusers, query, utype, orderBy, order, limit, offset)
|
|
|
|
//restrict oidc users, this is required as kratos creates entry with credential type password for oidc users as well
|
|
if utype == KratosPasswordType {
|
|
var ssousers []models.KratosIdentities
|
|
oq := db.NewSelect().Model(&ssousers).
|
|
Relation("IdentityCredential", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.ExcludeColumn("*")
|
|
}).
|
|
Relation("IdentityCredential.IdentityCredentialType", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.ExcludeColumn("*").Where("name = ?", KratosOidcType)
|
|
})
|
|
if len(fusers) > 0 {
|
|
// filter with precomputed users if we have any
|
|
oq = oq.Where("identities.id IN (?)", bun.In(fusers))
|
|
}
|
|
q.Except(oq)
|
|
}
|
|
|
|
err := q.Scan(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return users, nil
|
|
}
|
|
|
|
// ListFilteredUsersWithGroup is ListFilteredUsers but with Group fileter as well
|
|
func ListFilteredUsersWithGroup(
|
|
ctx context.Context,
|
|
db bun.IDB,
|
|
fusers []uuid.UUID,
|
|
group uuid.UUID,
|
|
query string,
|
|
utype string,
|
|
orderBy string,
|
|
order string,
|
|
limit int,
|
|
offset int,
|
|
) ([]models.KratosIdentities, error) {
|
|
var users []models.KratosIdentities
|
|
var gaccs []models.GroupAccount
|
|
q := db.NewSelect().Model(&gaccs)
|
|
q.Where("group_id = ?", group).Where("groupaccount.trash = ?", false)
|
|
|
|
q = q.Relation("Account", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return listFilteredUsersQuery(q, fusers, query, utype, orderBy, order, limit, offset)
|
|
})
|
|
err := q.Scan(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, ga := range gaccs {
|
|
users = append(users, *ga.Account)
|
|
}
|
|
return users, nil
|
|
}
|
|
|
|
func GetUserNamesByIds(ctx context.Context, db bun.IDB, id []uuid.UUID, entity interface{}) ([]string, error) {
|
|
names := []string{}
|
|
if len(id) == 0 {
|
|
return names, nil
|
|
}
|
|
err := db.NewSelect().ColumnExpr("traits ->> 'email' as name").Model(entity).
|
|
Where("id = (?)", bun.In(id)).
|
|
Scan(ctx, &names)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return names, nil
|
|
}
|
|
|
|
func IsSSOAccount(ctx context.Context, db bun.IDB, id uuid.UUID) (bool, error) {
|
|
var user models.KratosIdentities
|
|
q := db.NewSelect().Model(&user)
|
|
q = q.Relation("IdentityCredential").
|
|
Relation("IdentityCredential.IdentityCredentialType", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Where("name = ?", KratosOidcType)
|
|
})
|
|
q = q.Where("identities.id = ?", id)
|
|
err := q.Scan(ctx)
|
|
if err != nil && err == sql.ErrNoRows {
|
|
return false, nil
|
|
} else if err == nil && user.ID != uuid.Nil {
|
|
return true, nil
|
|
}
|
|
return false, err
|
|
}
|