Rename user into identity
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
@@ -26,9 +26,9 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
UserAPIKeyMembership struct {
|
||||
PersonalAPIKeyMembership struct {
|
||||
ID gid.GID `db:"id"`
|
||||
UserAPIKeyID gid.GID `db:"auth_user_api_key_id"`
|
||||
PersonalAPIKeyID gid.GID `db:"auth_personal_api_key_id"`
|
||||
MembershipID gid.GID `db:"membership_id"`
|
||||
Role APIRole `db:"role"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
@@ -37,21 +37,21 @@ type (
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
UserAPIKeyMemberships []*UserAPIKeyMembership
|
||||
PersonalAPIKeyMemberships []*PersonalAPIKeyMembership
|
||||
)
|
||||
|
||||
func (a *UserAPIKeyMembership) Insert(
|
||||
func (a *PersonalAPIKeyMembership) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO
|
||||
authz_api_keys_memberships (id, tenant_id, auth_user_api_key_id, membership_id, role, organization_id, created_at, updated_at)
|
||||
authz_api_keys_memberships (id, tenant_id, auth_personal_api_key_id, membership_id, role, organization_id, created_at, updated_at)
|
||||
VALUES (
|
||||
@id,
|
||||
@tenant_id,
|
||||
@auth_user_api_key_id,
|
||||
@auth_personal_api_key_id,
|
||||
@membership_id,
|
||||
@role,
|
||||
@organization_id,
|
||||
@@ -61,34 +61,34 @@ VALUES (
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": a.ID,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"auth_user_api_key_id": a.UserAPIKeyID,
|
||||
"membership_id": a.MembershipID,
|
||||
"role": a.Role,
|
||||
"organization_id": a.OrganizationID,
|
||||
"created_at": a.CreatedAt,
|
||||
"updated_at": a.UpdatedAt,
|
||||
"id": a.ID,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"auth_personal_api_key_id": a.PersonalAPIKeyID,
|
||||
"membership_id": a.MembershipID,
|
||||
"role": a.Role,
|
||||
"organization_id": a.OrganizationID,
|
||||
"created_at": a.CreatedAt,
|
||||
"updated_at": a.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert user api key membership: %w", err)
|
||||
return fmt.Errorf("cannot insert personal api key membership: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *UserAPIKeyMemberships) LoadByUserAPIKeyID(
|
||||
func (a *PersonalAPIKeyMemberships) LoadByPersonalAPIKeyID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
userAPIKeyID gid.GID,
|
||||
personalAPIKeyID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
akm.id,
|
||||
akm.auth_user_api_key_id,
|
||||
akm.auth_personal_api_key_id,
|
||||
akm.membership_id,
|
||||
akm.role,
|
||||
akm.created_at,
|
||||
@@ -102,7 +102,7 @@ JOIN
|
||||
JOIN
|
||||
organizations o ON m.organization_id = o.id
|
||||
WHERE
|
||||
akm.auth_user_api_key_id = @auth_user_api_key_id
|
||||
akm.auth_personal_api_key_id = @auth_personal_api_key_id
|
||||
AND m.%s
|
||||
ORDER BY akm.created_at DESC
|
||||
`
|
||||
@@ -110,18 +110,18 @@ ORDER BY akm.created_at DESC
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"auth_user_api_key_id": userAPIKeyID,
|
||||
"auth_personal_api_key_id": personalAPIKeyID,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query user api key memberships: %w", err)
|
||||
return fmt.Errorf("cannot query personal api key memberships: %w", err)
|
||||
}
|
||||
|
||||
memberships, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[UserAPIKeyMembership])
|
||||
memberships, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[PersonalAPIKeyMembership])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect user api key memberships: %w", err)
|
||||
return fmt.Errorf("cannot collect personal api key memberships: %w", err)
|
||||
}
|
||||
|
||||
*a = memberships
|
||||
@@ -130,7 +130,7 @@ ORDER BY akm.created_at DESC
|
||||
}
|
||||
|
||||
// LoadRoleByAPIKeyAndEntityID loads an API key's role by querying any entity to extract its organization_id
|
||||
func (a *UserAPIKeyMembership) LoadRoleByAPIKeyAndEntityID(
|
||||
func (a *PersonalAPIKeyMembership) LoadRoleByAPIKeyAndEntityID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
@@ -152,7 +152,7 @@ func (a *UserAPIKeyMembership) LoadRoleByAPIKeyAndEntityID(
|
||||
query := fmt.Sprintf(`
|
||||
SELECT
|
||||
akm.id,
|
||||
akm.auth_user_api_key_id,
|
||||
akm.auth_personal_api_key_id,
|
||||
akm.membership_id,
|
||||
akm.role,
|
||||
akm.created_at,
|
||||
@@ -163,7 +163,7 @@ FROM
|
||||
INNER JOIN %s e ON e.id = @entity_id
|
||||
WHERE
|
||||
%s
|
||||
AND akm.auth_user_api_key_id = @api_key_id
|
||||
AND akm.auth_personal_api_key_id = @api_key_id
|
||||
AND m.organization_id = e.organization_id
|
||||
LIMIT 1;
|
||||
`, tableName, scope.SQLFragment())
|
||||
@@ -184,10 +184,10 @@ LIMIT 1;
|
||||
return fmt.Errorf("API key membership not found for key %s and entity %s", apiKeyID, entityID)
|
||||
}
|
||||
|
||||
var membership UserAPIKeyMembership
|
||||
var membership PersonalAPIKeyMembership
|
||||
err = rows.Scan(
|
||||
&membership.ID,
|
||||
&membership.UserAPIKeyID,
|
||||
&membership.PersonalAPIKeyID,
|
||||
&membership.MembershipID,
|
||||
&membership.Role,
|
||||
&membership.CreatedAt,
|
||||
@@ -202,7 +202,7 @@ LIMIT 1;
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *UserAPIKeyMembership) LoadByAPIKeyIDAndOrganizationID(
|
||||
func (a *PersonalAPIKeyMembership) LoadByAPIKeyIDAndOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
@@ -212,7 +212,7 @@ func (a *UserAPIKeyMembership) LoadByAPIKeyIDAndOrganizationID(
|
||||
q := `
|
||||
SELECT
|
||||
akm.id,
|
||||
akm.auth_user_api_key_id,
|
||||
akm.auth_personal_api_key_id,
|
||||
akm.membership_id,
|
||||
akm.role,
|
||||
akm.created_at,
|
||||
@@ -226,7 +226,7 @@ JOIN
|
||||
JOIN
|
||||
organizations o ON m.organization_id = o.id
|
||||
WHERE
|
||||
akm.auth_user_api_key_id = @api_key_id
|
||||
akm.auth_personal_api_key_id = @api_key_id
|
||||
AND m.organization_id = @organization_id
|
||||
AND m.%s
|
||||
`
|
||||
@@ -241,22 +241,22 @@ WHERE
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query user api key membership: %w", err)
|
||||
return fmt.Errorf("cannot query personal api key membership: %w", err)
|
||||
}
|
||||
|
||||
membership, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[UserAPIKeyMembership])
|
||||
membership, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[PersonalAPIKeyMembership])
|
||||
if err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return fmt.Errorf("API key does not have access to organization")
|
||||
}
|
||||
return fmt.Errorf("cannot collect user api key membership: %w", err)
|
||||
return fmt.Errorf("cannot collect personal api key membership: %w", err)
|
||||
}
|
||||
|
||||
*a = membership
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *UserAPIKeyMembership) Delete(
|
||||
func (a *PersonalAPIKeyMembership) Delete(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
@@ -278,13 +278,13 @@ WHERE
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete user api key membership: %w", err)
|
||||
return fmt.Errorf("cannot delete personal api key membership: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *UserAPIKeyMemberships) LoadByMembershipID(
|
||||
func (a *PersonalAPIKeyMemberships) LoadByMembershipID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
@@ -293,7 +293,7 @@ func (a *UserAPIKeyMemberships) LoadByMembershipID(
|
||||
q := `
|
||||
SELECT
|
||||
akm.id,
|
||||
akm.auth_user_api_key_id,
|
||||
akm.auth_personal_api_key_id,
|
||||
akm.membership_id,
|
||||
akm.role,
|
||||
akm.created_at,
|
||||
@@ -321,12 +321,12 @@ ORDER BY akm.created_at DESC
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query user api key memberships by membership id: %w", err)
|
||||
return fmt.Errorf("cannot query personal api key memberships by membership id: %w", err)
|
||||
}
|
||||
|
||||
memberships, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[UserAPIKeyMembership])
|
||||
memberships, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[PersonalAPIKeyMembership])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect user api key memberships: %w", err)
|
||||
return fmt.Errorf("cannot collect personal api key memberships: %w", err)
|
||||
}
|
||||
|
||||
*a = memberships
|
||||
@@ -334,25 +334,25 @@ ORDER BY akm.created_at DESC
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteAllUserAPIKeyMembershipsByUserAPIKeyID(
|
||||
func DeleteAllPersonalAPIKeyMembershipsByPersonalAPIKeyID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
userAPIKeyID gid.GID,
|
||||
personalAPIKeyID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM
|
||||
authz_api_keys_memberships
|
||||
WHERE
|
||||
auth_user_api_key_id = @auth_user_api_key_id
|
||||
auth_personal_api_key_id = @auth_personal_api_key_id
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"auth_user_api_key_id": userAPIKeyID,
|
||||
"auth_personal_api_key_id": personalAPIKeyID,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete user api key memberships: %w", err)
|
||||
return fmt.Errorf("cannot delete personal api key memberships: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -32,7 +32,7 @@ const (
|
||||
PeopleEntityType uint16 = 8
|
||||
VendorComplianceReportEntityType uint16 = 9
|
||||
DocumentEntityType uint16 = 10
|
||||
UserEntityType uint16 = 11
|
||||
IdentityEntityType uint16 = 11
|
||||
SessionEntityType uint16 = 12
|
||||
EmailEntityType uint16 = 13
|
||||
ControlEntityType uint16 = 14
|
||||
@@ -64,8 +64,8 @@ const (
|
||||
SlackMessageEntityType uint16 = 40
|
||||
TrustCenterFileEntityType uint16 = 41
|
||||
SAMLConfigurationEntityType uint16 = 42
|
||||
UserAPIKeyEntityType uint16 = 43
|
||||
UserAPIKeyMembershipEntityType uint16 = 44
|
||||
PersonalAPIKeyEntityType uint16 = 43
|
||||
PersonalAPIKeyMembershipEntityType uint16 = 44
|
||||
MeetingEntityType uint16 = 45
|
||||
DataProtectionImpactAssessmentEntityType uint16 = 46
|
||||
TransferImpactAssessmentEntityType uint16 = 47
|
||||
@@ -124,9 +124,9 @@ var entityRegistry = map[uint16]EntityInfo{
|
||||
Model: "Document",
|
||||
Table: "documents",
|
||||
},
|
||||
UserEntityType: {
|
||||
Model: "User",
|
||||
Table: "auth_users",
|
||||
IdentityEntityType: {
|
||||
Model: "Identity",
|
||||
Table: "identities",
|
||||
},
|
||||
SessionEntityType: {
|
||||
Model: "Session",
|
||||
@@ -252,12 +252,12 @@ var entityRegistry = map[uint16]EntityInfo{
|
||||
Model: "SAMLConfiguration",
|
||||
Table: "auth_saml_configurations",
|
||||
},
|
||||
UserAPIKeyEntityType: {
|
||||
Model: "UserAPIKey",
|
||||
Table: "auth_user_api_keys",
|
||||
PersonalAPIKeyEntityType: {
|
||||
Model: "PersonalAPIKey",
|
||||
Table: "auth_personal_api_keys",
|
||||
},
|
||||
UserAPIKeyMembershipEntityType: {
|
||||
Model: "UserAPIKeyMembership",
|
||||
PersonalAPIKeyMembershipEntityType: {
|
||||
Model: "PersonalAPIKeyMembership",
|
||||
Table: "authz_api_keys_memberships",
|
||||
},
|
||||
MeetingEntityType: {
|
||||
|
||||
@@ -31,34 +31,34 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
User struct {
|
||||
Identity struct {
|
||||
ID gid.GID `db:"id"`
|
||||
EmailAddress mail.Addr `db:"email_address"`
|
||||
HashedPassword []byte `db:"hashed_password"`
|
||||
FullName string `db:"fullname"`
|
||||
EmailAddressVerified bool `db:"email_address_verified"`
|
||||
SAMLSubject *string `db:"saml_subject"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
HashedPassword []byte `db:"hashed_password"`
|
||||
FullName string `db:"fullname"`
|
||||
EmailAddressVerified bool `db:"email_address_verified"`
|
||||
SAMLSubject *string `db:"saml_subject"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
Users []*User
|
||||
Identities []*Identity
|
||||
)
|
||||
|
||||
func (u User) CursorKey(orderBy UserOrderField) page.CursorKey {
|
||||
func (i Identity) CursorKey(orderBy IdentityOrderField) page.CursorKey {
|
||||
switch orderBy {
|
||||
case UserOrderFieldCreatedAt:
|
||||
return page.NewCursorKey(u.ID, u.CreatedAt)
|
||||
case IdentityOrderFieldCreatedAt:
|
||||
return page.NewCursorKey(i.ID, i.CreatedAt)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
|
||||
}
|
||||
|
||||
func (u *Users) LoadByOrganizationID(
|
||||
func (i *Identities) LoadByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
organizationID gid.GID,
|
||||
cursor *page.Cursor[UserOrderField],
|
||||
cursor *page.Cursor[IdentityOrderField],
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
@@ -70,10 +70,10 @@ SELECT
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
users
|
||||
identities
|
||||
WHERE
|
||||
id IN (
|
||||
SELECT user_id FROM authz_memberships WHERE organization_id = @organization_id
|
||||
SELECT identity_id FROM authz_memberships WHERE organization_id = @organization_id
|
||||
)
|
||||
AND %s
|
||||
`
|
||||
@@ -85,20 +85,20 @@ WHERE
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query users: %w", err)
|
||||
return fmt.Errorf("cannot query identities: %w", err)
|
||||
}
|
||||
|
||||
users, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[User])
|
||||
identities, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Identity])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect users: %w", err)
|
||||
return fmt.Errorf("cannot collect identities: %w", err)
|
||||
}
|
||||
|
||||
*u = users
|
||||
*i = identities
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *Users) CountByOrganizationID(
|
||||
func (i *Identities) CountByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
@@ -108,10 +108,10 @@ func (u *Users) CountByOrganizationID(
|
||||
SELECT
|
||||
COUNT(*)
|
||||
FROM
|
||||
users
|
||||
identities
|
||||
WHERE
|
||||
id IN (
|
||||
SELECT user_id FROM authz_memberships WHERE organization_id = @organization_id AND %s
|
||||
SELECT identity_id FROM authz_memberships WHERE organization_id = @organization_id AND %s
|
||||
)
|
||||
`
|
||||
|
||||
@@ -125,14 +125,14 @@ WHERE
|
||||
var count int
|
||||
err := row.Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot count users: %w", err)
|
||||
return 0, fmt.Errorf("cannot count identities: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// Tenant id scope is not applied because we want to access users across all tenants for authentication purposes.
|
||||
func (u *User) LoadByEmail(
|
||||
// Tenant id scope is not applied because we want to access identities across all tenants for authentication purposes.
|
||||
func (i *Identity) LoadByEmail(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
email mail.Addr,
|
||||
@@ -148,38 +148,38 @@ SELECT
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
users
|
||||
identities
|
||||
WHERE
|
||||
email_address = @user_email
|
||||
email_address = @identity_email
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{"user_email": email}
|
||||
args := pgx.StrictNamedArgs{"identity_email": email}
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query user: %w", err)
|
||||
return fmt.Errorf("cannot query identity: %w", err)
|
||||
}
|
||||
|
||||
user, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[User])
|
||||
identity, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Identity])
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return ErrResourceNotFound
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot collect user: %w", err)
|
||||
return fmt.Errorf("cannot collect identity: %w", err)
|
||||
}
|
||||
|
||||
*u = user
|
||||
*i = identity
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Tenant id scope is not applied because we want to access users across all tenants for authentication purposes.
|
||||
func (u *User) LoadByID(
|
||||
// Tenant id scope is not applied because we want to access identities across all tenants for authentication purposes.
|
||||
func (i *Identity) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
userID gid.GID,
|
||||
identityID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
@@ -192,42 +192,42 @@ SELECT
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
users
|
||||
identities
|
||||
WHERE
|
||||
id = @user_id
|
||||
id = @identity_id
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{"user_id": userID}
|
||||
args := pgx.StrictNamedArgs{"identity_id": identityID}
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query user: %w", err)
|
||||
return fmt.Errorf("cannot query identity: %w", err)
|
||||
}
|
||||
|
||||
user, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[User])
|
||||
identity, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Identity])
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return ErrResourceNotFound
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot collect user: %w", err)
|
||||
return fmt.Errorf("cannot collect identity: %w", err)
|
||||
}
|
||||
|
||||
*u = user
|
||||
*i = identity
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) Insert(
|
||||
func (i *Identity) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO
|
||||
users (id, email_address, hashed_password, email_address_verified, fullname, saml_subject, created_at, updated_at)
|
||||
identities (id, email_address, hashed_password, email_address_verified, fullname, saml_subject, created_at, updated_at)
|
||||
VALUES (
|
||||
@user_id,
|
||||
@identity_id,
|
||||
@email_address,
|
||||
@hashed_password,
|
||||
@email_address_verified,
|
||||
@@ -239,14 +239,14 @@ VALUES (
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"user_id": u.ID,
|
||||
"email_address": u.EmailAddress,
|
||||
"hashed_password": u.HashedPassword,
|
||||
"fullname": u.FullName,
|
||||
"saml_subject": u.SAMLSubject,
|
||||
"created_at": u.CreatedAt,
|
||||
"updated_at": u.UpdatedAt,
|
||||
"email_address_verified": u.EmailAddressVerified,
|
||||
"identity_id": i.ID,
|
||||
"email_address": i.EmailAddress,
|
||||
"hashed_password": i.HashedPassword,
|
||||
"fullname": i.FullName,
|
||||
"saml_subject": i.SAMLSubject,
|
||||
"created_at": i.CreatedAt,
|
||||
"updated_at": i.UpdatedAt,
|
||||
"email_address_verified": i.EmailAddressVerified,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
@@ -265,10 +265,10 @@ VALUES (
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) Update(ctx context.Context, conn pg.Conn) error {
|
||||
func (i *Identity) Update(ctx context.Context, conn pg.Conn) error {
|
||||
q := `
|
||||
UPDATE
|
||||
users
|
||||
identities
|
||||
SET
|
||||
email_address = @email_address,
|
||||
email_address_verified = @email_address_verified,
|
||||
@@ -277,22 +277,22 @@ SET
|
||||
hashed_password = @hashed_password,
|
||||
updated_at = @updated_at
|
||||
WHERE
|
||||
id = @user_id
|
||||
id = @identity_id
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"user_id": u.ID,
|
||||
"email_address": u.EmailAddress,
|
||||
"email_address_verified": u.EmailAddressVerified,
|
||||
"saml_subject": u.SAMLSubject,
|
||||
"updated_at": u.UpdatedAt,
|
||||
"fullname": u.FullName,
|
||||
"hashed_password": u.HashedPassword,
|
||||
"identity_id": i.ID,
|
||||
"email_address": i.EmailAddress,
|
||||
"email_address_verified": i.EmailAddressVerified,
|
||||
"saml_subject": i.SAMLSubject,
|
||||
"updated_at": i.UpdatedAt,
|
||||
"fullname": i.FullName,
|
||||
"hashed_password": i.HashedPassword,
|
||||
}
|
||||
|
||||
result, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update user: %w", err)
|
||||
return fmt.Errorf("cannot update identity: %w", err)
|
||||
}
|
||||
|
||||
if result.RowsAffected() == 0 {
|
||||
@@ -302,8 +302,8 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadBySAMLSubject loads a user by their SAML subject (NameID)
|
||||
func (u *User) LoadBySAMLSubject(
|
||||
// LoadBySAMLSubject loads an identity by their SAML subject (NameID)
|
||||
func (i *Identity) LoadBySAMLSubject(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
samlSubject string,
|
||||
@@ -319,7 +319,7 @@ SELECT
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
users
|
||||
identities
|
||||
WHERE
|
||||
saml_subject = @saml_subject
|
||||
LIMIT 1;
|
||||
@@ -329,24 +329,24 @@ LIMIT 1;
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query user by SAML subject: %w", err)
|
||||
return fmt.Errorf("cannot query identity by SAML subject: %w", err)
|
||||
}
|
||||
|
||||
user, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[User])
|
||||
identity, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Identity])
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return ErrResourceNotFound
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot collect user: %w", err)
|
||||
return fmt.Errorf("cannot collect identity: %w", err)
|
||||
}
|
||||
|
||||
*u = user
|
||||
*i = identity
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) CountMemberships(
|
||||
func (i *Identity) CountMemberships(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
) (int, error) {
|
||||
@@ -356,19 +356,16 @@ SELECT
|
||||
FROM
|
||||
authz_memberships
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{"user_id": u.ID}
|
||||
args := pgx.StrictNamedArgs{"identity_id": i.ID}
|
||||
|
||||
var count int
|
||||
err := conn.QueryRow(ctx, q, args).Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot count user memberships: %w", err)
|
||||
return 0, fmt.Errorf("cannot count identity memberships: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// ConvertToTenantUser method removed
|
||||
// All users are now global (no tenant conversion needed)
|
||||
@@ -15,26 +15,26 @@
|
||||
package coredata
|
||||
|
||||
type (
|
||||
UserOrderField string
|
||||
IdentityOrderField string
|
||||
)
|
||||
|
||||
const (
|
||||
UserOrderFieldCreatedAt UserOrderField = "CREATED_AT"
|
||||
IdentityOrderFieldCreatedAt IdentityOrderField = "CREATED_AT"
|
||||
)
|
||||
|
||||
func (p UserOrderField) Column() string {
|
||||
func (p IdentityOrderField) Column() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p UserOrderField) String() string {
|
||||
func (p IdentityOrderField) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p UserOrderField) MarshalText() ([]byte, error) {
|
||||
func (p IdentityOrderField) MarshalText() ([]byte, error) {
|
||||
return []byte(p.String()), nil
|
||||
}
|
||||
|
||||
func (p *UserOrderField) UnmarshalText(text []byte) error {
|
||||
*p = UserOrderField(text)
|
||||
func (p *IdentityOrderField) UnmarshalText(text []byte) error {
|
||||
*p = IdentityOrderField(text)
|
||||
return nil
|
||||
}
|
||||
@@ -33,7 +33,7 @@ import (
|
||||
type (
|
||||
Membership struct {
|
||||
ID gid.GID `db:"id"`
|
||||
UserID gid.GID `db:"user_id"`
|
||||
IdentityID gid.GID `db:"identity_id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Role MembershipRole `db:"role"`
|
||||
FullName string `db:"full_name"`
|
||||
@@ -60,11 +60,11 @@ func (m Membership) CursorKey(orderBy MembershipOrderField) page.CursorKey {
|
||||
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
|
||||
}
|
||||
|
||||
func (m *Membership) LoadByUserInOrganization(ctx context.Context, conn pg.Conn, userID gid.GID, organizationID gid.GID) error {
|
||||
func (m *Membership) LoadByIdentityInOrganization(ctx context.Context, conn pg.Conn, identityID gid.GID, organizationID gid.GID) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
organization_id,
|
||||
role,
|
||||
created_at,
|
||||
@@ -72,12 +72,12 @@ SELECT
|
||||
FROM
|
||||
authz_memberships
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
AND organization_id = @organization_id
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"user_id": userID,
|
||||
"identity_id": identityID,
|
||||
"organization_id": organizationID,
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ INSERT INTO
|
||||
authz_memberships (
|
||||
tenant_id,
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
organization_id,
|
||||
role,
|
||||
created_at,
|
||||
@@ -114,7 +114,7 @@ INSERT INTO
|
||||
VALUES (
|
||||
@tenant_id,
|
||||
@id,
|
||||
@user_id,
|
||||
@identity_id,
|
||||
@organization_id,
|
||||
@role,
|
||||
@created_at,
|
||||
@@ -125,7 +125,7 @@ VALUES (
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"id": m.ID,
|
||||
"user_id": m.UserID,
|
||||
"identity_id": m.IdentityID,
|
||||
"organization_id": m.OrganizationID,
|
||||
"role": m.Role,
|
||||
"created_at": m.CreatedAt,
|
||||
@@ -159,7 +159,7 @@ func (m *Membership) LoadByID(
|
||||
WITH mbr AS (
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
organization_id,
|
||||
role,
|
||||
created_at,
|
||||
@@ -172,17 +172,17 @@ WITH mbr AS (
|
||||
)
|
||||
SELECT
|
||||
mbr.id,
|
||||
mbr.user_id,
|
||||
mbr.identity_id,
|
||||
mbr.organization_id,
|
||||
mbr.role,
|
||||
u.fullname as full_name,
|
||||
u.email_address,
|
||||
i.fullname as full_name,
|
||||
i.email_address,
|
||||
mbr.created_at,
|
||||
mbr.updated_at
|
||||
FROM
|
||||
mbr
|
||||
JOIN
|
||||
users u ON mbr.user_id = u.id
|
||||
identities i ON mbr.identity_id = i.id
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
@@ -210,19 +210,19 @@ JOIN
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadRoleByUserAndEntityID loads a user's role by querying any entity to extract its organization_id
|
||||
func (m *Membership) LoadRoleByUserAndEntityID(
|
||||
// LoadRoleByIdentityAndEntityID loads an identity's role by querying any entity to extract its organization_id
|
||||
func (m *Membership) LoadRoleByIdentityAndEntityID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
userID gid.GID,
|
||||
identityID gid.GID,
|
||||
entityID gid.GID,
|
||||
) error {
|
||||
entityType := entityID.EntityType()
|
||||
|
||||
// For organization, the entity ID is the organization ID
|
||||
if entityType == OrganizationEntityType {
|
||||
return m.LoadByUserAndOrg(ctx, conn, scope, userID, entityID)
|
||||
return m.LoadByIdentityAndOrg(ctx, conn, scope, identityID, entityID)
|
||||
}
|
||||
|
||||
tableName, ok := EntityTable(entityType)
|
||||
@@ -238,7 +238,7 @@ func (m *Membership) LoadRoleByUserAndEntityID(
|
||||
query := fmt.Sprintf(`
|
||||
SELECT
|
||||
m.id,
|
||||
m.user_id,
|
||||
m.identity_id,
|
||||
m.organization_id,
|
||||
m.role,
|
||||
m.created_at,
|
||||
@@ -248,14 +248,14 @@ FROM
|
||||
INNER JOIN %s e ON e.id = @entity_id
|
||||
WHERE
|
||||
%s
|
||||
AND m.user_id = @user_id
|
||||
AND m.identity_id = @identity_id
|
||||
AND m.organization_id = e.organization_id
|
||||
LIMIT 1;
|
||||
`, tableName, scopeFragment)
|
||||
|
||||
args := pgx.NamedArgs{
|
||||
"user_id": userID,
|
||||
"entity_id": entityID,
|
||||
"identity_id": identityID,
|
||||
"entity_id": entityID,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
@@ -272,7 +272,7 @@ LIMIT 1;
|
||||
var membership Membership
|
||||
err = rows.Scan(
|
||||
&membership.ID,
|
||||
&membership.UserID,
|
||||
&membership.IdentityID,
|
||||
&membership.OrganizationID,
|
||||
&membership.Role,
|
||||
&membership.CreatedAt,
|
||||
@@ -287,18 +287,18 @@ LIMIT 1;
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Membership) LoadByUserAndOrg(
|
||||
func (m *Membership) LoadByIdentityAndOrg(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
userID gid.GID,
|
||||
identityID gid.GID,
|
||||
organizationID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
WITH mbr AS (
|
||||
SELECT
|
||||
am.id,
|
||||
am.user_id,
|
||||
am.identity_id,
|
||||
am.organization_id,
|
||||
am.role,
|
||||
am.created_at,
|
||||
@@ -306,29 +306,29 @@ WITH mbr AS (
|
||||
FROM
|
||||
authz_memberships am
|
||||
WHERE
|
||||
am.user_id = @user_id
|
||||
am.identity_id = @identity_id
|
||||
AND am.organization_id = @organization_id
|
||||
AND %s
|
||||
)
|
||||
SELECT
|
||||
mbr.id,
|
||||
mbr.user_id,
|
||||
mbr.identity_id,
|
||||
mbr.organization_id,
|
||||
mbr.role,
|
||||
u.fullname as full_name,
|
||||
u.email_address,
|
||||
i.fullname as full_name,
|
||||
i.email_address,
|
||||
mbr.created_at,
|
||||
mbr.updated_at
|
||||
FROM
|
||||
mbr
|
||||
JOIN
|
||||
users u ON mbr.user_id = u.id
|
||||
identities i ON mbr.identity_id = i.id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"user_id": userID,
|
||||
"identity_id": identityID,
|
||||
"organization_id": organizationID,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
@@ -412,18 +412,18 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Memberships) LoadByUserID(
|
||||
func (m *Memberships) LoadByIdentityID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
userID gid.GID,
|
||||
identityID gid.GID,
|
||||
cursor *page.Cursor[MembershipOrderField],
|
||||
) error {
|
||||
query := `
|
||||
WITH mbr AS (
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
organization_id,
|
||||
role,
|
||||
created_at,
|
||||
@@ -431,24 +431,24 @@ WITH mbr AS (
|
||||
FROM
|
||||
authz_memberships
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
AND %s
|
||||
ORDER BY
|
||||
created_at DESC
|
||||
)
|
||||
SELECT
|
||||
mbr.id,
|
||||
mbr.user_id,
|
||||
mbr.identity_id,
|
||||
mbr.organization_id,
|
||||
mbr.role,
|
||||
u.fullname as full_name,
|
||||
u.email_address,
|
||||
i.fullname as full_name,
|
||||
i.email_address,
|
||||
mbr.created_at,
|
||||
mbr.updated_at
|
||||
FROM
|
||||
mbr
|
||||
JOIN
|
||||
users u ON mbr.user_id = u.id
|
||||
identities i ON mbr.identity_id = i.id
|
||||
ORDER BY
|
||||
mbr.created_at DESC
|
||||
`
|
||||
@@ -456,7 +456,7 @@ ORDER BY
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"user_id": userID,
|
||||
"identity_id": identityID,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
@@ -485,7 +485,7 @@ func (m *Memberships) LoadByOrganizationID(
|
||||
WITH mbr AS (
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
organization_id,
|
||||
role,
|
||||
created_at,
|
||||
@@ -498,7 +498,7 @@ WITH mbr AS (
|
||||
)
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
organization_id,
|
||||
role,
|
||||
full_name,
|
||||
@@ -508,18 +508,18 @@ SELECT
|
||||
FROM (
|
||||
SELECT
|
||||
mbr.id,
|
||||
mbr.user_id,
|
||||
mbr.identity_id,
|
||||
mbr.organization_id,
|
||||
mbr.role,
|
||||
u.fullname as full_name,
|
||||
u.email_address,
|
||||
i.fullname as full_name,
|
||||
i.email_address,
|
||||
mbr.created_at,
|
||||
mbr.updated_at
|
||||
FROM
|
||||
mbr
|
||||
JOIN
|
||||
users u ON mbr.user_id = u.id
|
||||
) AS membership_with_user
|
||||
identities i ON mbr.identity_id = i.id
|
||||
) AS membership_with_identity
|
||||
WHERE %s
|
||||
`
|
||||
|
||||
@@ -573,10 +573,10 @@ WHERE
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (m *Memberships) CountByUserID(
|
||||
func (m *Memberships) CountByIdentityID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
userID gid.GID,
|
||||
identityID gid.GID,
|
||||
) (int, error) {
|
||||
query := `
|
||||
SELECT
|
||||
@@ -584,10 +584,10 @@ SELECT
|
||||
FROM
|
||||
authz_memberships
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
`
|
||||
args := pgx.StrictNamedArgs{
|
||||
"user_id": userID,
|
||||
"identity_id": identityID,
|
||||
}
|
||||
|
||||
row := conn.QueryRow(ctx, query, args)
|
||||
|
||||
8
pkg/coredata/migrations/20251220T104530Z.sql
Normal file
8
pkg/coredata/migrations/20251220T104530Z.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
ALTER TABLE users RENAME TO identities;
|
||||
ALTER TABLE sessions RENAME COLUMN user_id TO identity_id;
|
||||
ALTER TABLE authz_memberships RENAME COLUMN user_id TO identity_id;
|
||||
ALTER TABLE peoples RENAME COLUMN user_id TO identity_id;
|
||||
ALTER TABLE auth_user_api_keys RENAME TO auth_personal_api_keys;
|
||||
ALTER TABLE auth_personal_api_keys RENAME COLUMN user_id TO identity_id;
|
||||
ALTER TABLE authz_api_keys_memberships RENAME COLUMN auth_user_api_key_id TO auth_personal_api_key_id;
|
||||
|
||||
@@ -111,21 +111,21 @@ LIMIT 1;
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Organizations) LoadByUserID(
|
||||
func (o *Organizations) LoadByIdentityID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
userID gid.GID,
|
||||
identityID gid.GID,
|
||||
cursor *page.Cursor[OrganizationOrderField],
|
||||
) error {
|
||||
q := `
|
||||
WITH user_org AS (
|
||||
WITH identity_org AS (
|
||||
SELECT
|
||||
organization_id
|
||||
FROM
|
||||
authz_memberships
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
)
|
||||
SELECT
|
||||
tenant_id,
|
||||
@@ -143,7 +143,7 @@ SELECT
|
||||
FROM
|
||||
organizations
|
||||
INNER JOIN
|
||||
user_org ON organizations.id = user_org.organization_id
|
||||
identity_org ON organizations.id = identity_org.organization_id
|
||||
WHERE
|
||||
%s
|
||||
AND %s
|
||||
@@ -151,7 +151,7 @@ WHERE
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"user_id": userID}
|
||||
args := pgx.StrictNamedArgs{"identity_id": identityID}
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
@@ -169,19 +169,19 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Organizations) LoadAllByUserID(
|
||||
func (o *Organizations) LoadAllByIdentityID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
userID gid.GID,
|
||||
identityID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
WITH user_org AS (
|
||||
WITH identity_org AS (
|
||||
SELECT
|
||||
organization_id
|
||||
FROM
|
||||
authz_memberships
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
)
|
||||
SELECT
|
||||
tenant_id,
|
||||
@@ -199,12 +199,12 @@ SELECT
|
||||
FROM
|
||||
organizations
|
||||
INNER JOIN
|
||||
user_org ON organizations.id = user_org.organization_id
|
||||
identity_org ON organizations.id = identity_org.organization_id
|
||||
ORDER BY
|
||||
name ASC
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{"user_id": userID}
|
||||
args := pgx.StrictNamedArgs{"identity_id": identityID}
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
@@ -221,20 +221,20 @@ ORDER BY
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Organizations) LoadAllByUserIDWithRole(
|
||||
func (o *Organizations) LoadAllByIdentityIDWithRole(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
userID gid.GID,
|
||||
identityID gid.GID,
|
||||
role MembershipRole,
|
||||
) error {
|
||||
q := `
|
||||
WITH user_org AS (
|
||||
WITH identity_org AS (
|
||||
SELECT
|
||||
organization_id
|
||||
FROM
|
||||
authz_memberships
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
AND role = @role
|
||||
)
|
||||
SELECT
|
||||
@@ -253,14 +253,14 @@ SELECT
|
||||
FROM
|
||||
organizations
|
||||
INNER JOIN
|
||||
user_org ON organizations.id = user_org.organization_id
|
||||
identity_org ON organizations.id = identity_org.organization_id
|
||||
ORDER BY
|
||||
name ASC
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"user_id": userID,
|
||||
"role": role,
|
||||
"identity_id": identityID,
|
||||
"role": role,
|
||||
}
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
@@ -278,13 +278,13 @@ ORDER BY
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Organizations) LoadAllByUserAPIKeyID(
|
||||
func (o *Organizations) LoadAllByPersonalAPIKeyID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
userAPIKeyID gid.GID,
|
||||
personalAPIKeyID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
WITH user_api_key_org AS (
|
||||
WITH personal_api_key_org AS (
|
||||
SELECT
|
||||
am.organization_id
|
||||
FROM
|
||||
@@ -292,7 +292,7 @@ WITH user_api_key_org AS (
|
||||
INNER JOIN
|
||||
authz_memberships am ON akm.membership_id = am.id
|
||||
WHERE
|
||||
akm.auth_user_api_key_id = @auth_user_api_key_id
|
||||
akm.auth_personal_api_key_id = @auth_personal_api_key_id
|
||||
)
|
||||
SELECT
|
||||
tenant_id,
|
||||
@@ -310,12 +310,12 @@ SELECT
|
||||
FROM
|
||||
organizations
|
||||
INNER JOIN
|
||||
user_api_key_org ON organizations.id = user_api_key_org.organization_id
|
||||
personal_api_key_org ON organizations.id = personal_api_key_org.organization_id
|
||||
ORDER BY
|
||||
name ASC
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{"auth_user_api_key_id": userAPIKeyID}
|
||||
args := pgx.StrictNamedArgs{"auth_personal_api_key_id": personalAPIKeyID}
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -27,9 +27,9 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
UserAPIKey struct {
|
||||
PersonalAPIKey struct {
|
||||
ID gid.GID `db:"id"`
|
||||
UserID gid.GID `db:"user_id"`
|
||||
IdentityID gid.GID `db:"identity_id"`
|
||||
Name string `db:"name"`
|
||||
ExpiresAt time.Time `db:"expires_at"`
|
||||
ExpireReason *ExpireReason `db:"expire_reason"`
|
||||
@@ -37,19 +37,19 @@ type (
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
UserAPIKeys []*UserAPIKey
|
||||
PersonalAPIKeys []*PersonalAPIKey
|
||||
)
|
||||
|
||||
func (a *UserAPIKey) CursorKey(orderBy UserAPIKeyOrderField) page.CursorKey {
|
||||
func (a *PersonalAPIKey) CursorKey(orderBy PersonalAPIKeyOrderField) page.CursorKey {
|
||||
switch orderBy {
|
||||
case UserAPIKeyOrderFieldCreatedAt:
|
||||
case PersonalAPIKeyOrderFieldCreatedAt:
|
||||
return page.NewCursorKey(a.ID, a.CreatedAt)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
|
||||
}
|
||||
|
||||
func (a *UserAPIKey) LoadByID(
|
||||
func (a *PersonalAPIKey) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
apiKeyID gid.GID,
|
||||
@@ -57,14 +57,14 @@ func (a *UserAPIKey) LoadByID(
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
name,
|
||||
expires_at,
|
||||
expire_reason,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
auth_user_api_keys
|
||||
auth_personal_api_keys
|
||||
WHERE
|
||||
id = @api_key_id
|
||||
LIMIT 1;
|
||||
@@ -74,16 +74,16 @@ LIMIT 1;
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query user api key: %w", err)
|
||||
return fmt.Errorf("cannot query personal api key: %w", err)
|
||||
}
|
||||
|
||||
apiKey, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[UserAPIKey])
|
||||
apiKey, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[PersonalAPIKey])
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return ErrResourceNotFound
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot collect user api key: %w", err)
|
||||
return fmt.Errorf("cannot collect personal api key: %w", err)
|
||||
}
|
||||
|
||||
*a = apiKey
|
||||
@@ -91,37 +91,37 @@ LIMIT 1;
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *UserAPIKeys) LoadByUserID(
|
||||
func (a *PersonalAPIKeys) LoadByIdentityID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
userID gid.GID,
|
||||
identityID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
name,
|
||||
expires_at,
|
||||
expire_reason,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
auth_user_api_keys
|
||||
auth_personal_api_keys
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
ORDER BY created_at DESC;
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{"user_id": userID}
|
||||
args := pgx.StrictNamedArgs{"identity_id": identityID}
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query user api keys: %w", err)
|
||||
return fmt.Errorf("cannot query personal api keys: %w", err)
|
||||
}
|
||||
|
||||
apiKeys, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[UserAPIKey])
|
||||
apiKeys, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[PersonalAPIKey])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect user api keys: %w", err)
|
||||
return fmt.Errorf("cannot collect personal api keys: %w", err)
|
||||
}
|
||||
|
||||
*a = apiKeys
|
||||
@@ -129,18 +129,18 @@ ORDER BY created_at DESC;
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *UserAPIKeys) CountByUserID(ctx context.Context, conn pg.Conn, userID gid.GID) (int, error) {
|
||||
func (a *PersonalAPIKeys) CountByIdentityID(ctx context.Context, conn pg.Conn, identityID gid.GID) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(*)
|
||||
FROM
|
||||
auth_user_api_keys
|
||||
auth_personal_api_keys
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
ORDER BY created_at DESC;
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{"user_id": userID}
|
||||
args := pgx.StrictNamedArgs{"identity_id": identityID}
|
||||
row := conn.QueryRow(ctx, q, args)
|
||||
var count int
|
||||
if err := row.Scan(&count); err != nil {
|
||||
@@ -150,16 +150,16 @@ ORDER BY created_at DESC;
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (a *UserAPIKey) Insert(
|
||||
func (a *PersonalAPIKey) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO
|
||||
auth_user_api_keys (id, user_id, name, expires_at, expire_reason, created_at, updated_at)
|
||||
auth_personal_api_keys (id, identity_id, name, expires_at, expire_reason, created_at, updated_at)
|
||||
VALUES (
|
||||
@api_key_id,
|
||||
@user_id,
|
||||
@identity_id,
|
||||
@name,
|
||||
@expires_at,
|
||||
@expire_reason,
|
||||
@@ -170,7 +170,7 @@ VALUES (
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"api_key_id": a.ID,
|
||||
"user_id": a.UserID,
|
||||
"identity_id": a.IdentityID,
|
||||
"name": a.Name,
|
||||
"expires_at": a.ExpiresAt,
|
||||
"expire_reason": a.ExpireReason,
|
||||
@@ -180,19 +180,19 @@ VALUES (
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert user api key: %w", err)
|
||||
return fmt.Errorf("cannot insert personal api key: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *UserAPIKey) Update(
|
||||
func (a *PersonalAPIKey) Update(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
) error {
|
||||
q := `
|
||||
UPDATE
|
||||
auth_user_api_keys
|
||||
auth_personal_api_keys
|
||||
SET
|
||||
name = @name,
|
||||
expires_at = @expires_at,
|
||||
@@ -212,19 +212,19 @@ WHERE
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update user api key: %w", err)
|
||||
return fmt.Errorf("cannot update personal api key: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *UserAPIKey) Delete(
|
||||
func (a *PersonalAPIKey) Delete(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM
|
||||
auth_user_api_keys
|
||||
auth_personal_api_keys
|
||||
WHERE
|
||||
id = @api_key_id
|
||||
`
|
||||
@@ -233,7 +233,7 @@ WHERE
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete user api key: %w", err)
|
||||
return fmt.Errorf("cannot delete personal api key: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -15,26 +15,26 @@
|
||||
package coredata
|
||||
|
||||
type (
|
||||
UserAPIKeyOrderField string
|
||||
PersonalAPIKeyOrderField string
|
||||
)
|
||||
|
||||
const (
|
||||
UserAPIKeyOrderFieldCreatedAt UserAPIKeyOrderField = "CREATED_AT"
|
||||
PersonalAPIKeyOrderFieldCreatedAt PersonalAPIKeyOrderField = "CREATED_AT"
|
||||
)
|
||||
|
||||
func (p UserAPIKeyOrderField) Column() string {
|
||||
func (p PersonalAPIKeyOrderField) Column() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p UserAPIKeyOrderField) String() string {
|
||||
func (p PersonalAPIKeyOrderField) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p UserAPIKeyOrderField) MarshalText() ([]byte, error) {
|
||||
func (p PersonalAPIKeyOrderField) MarshalText() ([]byte, error) {
|
||||
return []byte(p.String()), nil
|
||||
}
|
||||
|
||||
func (p *UserAPIKeyOrderField) UnmarshalText(text []byte) error {
|
||||
*p = UserAPIKeyOrderField(text)
|
||||
func (p *PersonalAPIKeyOrderField) UnmarshalText(text []byte) error {
|
||||
*p = PersonalAPIKeyOrderField(text)
|
||||
return nil
|
||||
}
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
type (
|
||||
Session struct {
|
||||
ID gid.GID `db:"id"`
|
||||
UserID gid.GID `db:"user_id"`
|
||||
IdentityID gid.GID `db:"identity_id"`
|
||||
TenantID *gid.TenantID `db:"tenant_id"`
|
||||
MembershipID *gid.GID `db:"membership_id"`
|
||||
ParentSessionID *gid.GID `db:"parent_session_id"`
|
||||
@@ -58,11 +58,11 @@ const (
|
||||
AuthMethodSAML AuthMethod = "SAML"
|
||||
)
|
||||
|
||||
func NewRootSession(userID gid.GID, method AuthMethod, duration time.Duration) *Session {
|
||||
func NewRootSession(identityID gid.GID, method AuthMethod, duration time.Duration) *Session {
|
||||
now := time.Now()
|
||||
return &Session{
|
||||
ID: gid.New(gid.NilTenant, SessionEntityType),
|
||||
UserID: userID,
|
||||
IdentityID: identityID,
|
||||
ExpiredAt: now.Add(duration),
|
||||
AuthMethod: method,
|
||||
AuthenticatedAt: now,
|
||||
@@ -100,7 +100,7 @@ func (s *Session) LoadByID(
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
tenant_id,
|
||||
membership_id,
|
||||
data,
|
||||
@@ -146,10 +146,10 @@ func (s *Session) Insert(
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO
|
||||
sessions (id, user_id, tenant_id, membership_id, data, parent_session_id, auth_method, authenticated_at, expire_reason, user_agent, ip_address, expired_at, created_at, updated_at)
|
||||
sessions (id, identity_id, tenant_id, membership_id, data, parent_session_id, auth_method, authenticated_at, expire_reason, user_agent, ip_address, expired_at, created_at, updated_at)
|
||||
VALUES (
|
||||
@session_id,
|
||||
@user_id,
|
||||
@identity_id,
|
||||
@tenant_id,
|
||||
@membership_id,
|
||||
@data,
|
||||
@@ -167,7 +167,7 @@ VALUES (
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"session_id": s.ID,
|
||||
"user_id": s.UserID,
|
||||
"identity_id": s.IdentityID,
|
||||
"tenant_id": s.TenantID,
|
||||
"membership_id": s.MembershipID,
|
||||
"data": s.Data,
|
||||
@@ -225,11 +225,11 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Sessions) LoadByUserID(ctx context.Context, conn pg.Conn, userID gid.GID, cursor *page.Cursor[SessionOrderField]) error {
|
||||
func (s *Sessions) LoadByIdentityID(ctx context.Context, conn pg.Conn, identityID gid.GID, cursor *page.Cursor[SessionOrderField]) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
tenant_id,
|
||||
membership_id,
|
||||
data,
|
||||
@@ -245,13 +245,13 @@ SELECT
|
||||
FROM
|
||||
sessions
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, cursor.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"user_id": userID}
|
||||
args := pgx.StrictNamedArgs{"identity_id": identityID}
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
@@ -269,17 +269,17 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Sessions) CountByUserID(ctx context.Context, conn pg.Conn, userID gid.GID) (int, error) {
|
||||
func (s *Sessions) CountByIdentityID(ctx context.Context, conn pg.Conn, identityID gid.GID) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(*)
|
||||
FROM
|
||||
sessions
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
identity_id = @identity_id
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{"user_id": userID}
|
||||
args := pgx.StrictNamedArgs{"identity_id": identityID}
|
||||
|
||||
row := conn.QueryRow(ctx, q, args)
|
||||
|
||||
@@ -291,7 +291,7 @@ WHERE
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (s *Sessions) ExpireAllForUserExceptOneSession(ctx context.Context, conn pg.Conn, userID gid.GID, sessionID gid.GID) (int64, error) {
|
||||
func (s *Sessions) ExpireAllForIdentityExceptOneSession(ctx context.Context, conn pg.Conn, identityID gid.GID, sessionID gid.GID) (int64, error) {
|
||||
q := `
|
||||
UPDATE sessions
|
||||
SET
|
||||
@@ -300,13 +300,13 @@ SET
|
||||
expire_reason = 'revoked'
|
||||
WHERE
|
||||
id != @session_id
|
||||
AND user_id = @user_id
|
||||
AND identity_id = @identity_id
|
||||
AND expire_reason IS NULL
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"session_id": sessionID,
|
||||
"user_id": userID,
|
||||
"session_id": sessionID,
|
||||
"identity_id": identityID,
|
||||
}
|
||||
|
||||
result, err := conn.Exec(ctx, q, args)
|
||||
@@ -321,7 +321,7 @@ func (s *Session) LoadByRootSessionIDAndMembershipID(ctx context.Context, conn p
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
identity_id,
|
||||
tenant_id,
|
||||
membership_id,
|
||||
data,
|
||||
|
||||
Reference in New Issue
Block a user