Rename user into identity

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2025-12-20 14:14:31 +01:00
parent fa0295f481
commit 0f7c755d53
35 changed files with 606 additions and 664 deletions

View File

@@ -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

View File

@@ -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: {

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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)

View 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;

View File

@@ -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 {

View File

@@ -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

View File

@@ -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
}

View File

@@ -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,