70 lines
1.4 KiB
Go
70 lines
1.4 KiB
Go
|
package db
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/jackc/pgx/v5"
|
||
|
"sigs.k8s.io/controller-runtime/pkg/log"
|
||
|
|
||
|
"code.icb4dc0.de/prskr/supabase-operator/assets/migrations"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
alterUserPwd = `ALTER ROLE %s WITH PASSWORD '%s';`
|
||
|
checkUserExists = `SELECT 1 FROM pg_user WHERE usename = $1;`
|
||
|
)
|
||
|
|
||
|
func NewRolesManager(conn *pgx.Conn) RolesManager {
|
||
|
return RolesManager{
|
||
|
Conn: conn,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type RolesManager struct {
|
||
|
Conn *pgx.Conn
|
||
|
}
|
||
|
|
||
|
func (mgr RolesManager) UpdateRolePassword(ctx context.Context, roleName string, password []byte) error {
|
||
|
if err := mgr.ensureLoginRoleExists(ctx, roleName); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
_, err := mgr.Conn.Exec(ctx, fmt.Sprintf(alterUserPwd, roleName, password))
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (mgr RolesManager) ensureLoginRoleExists(ctx context.Context, roleName string) error {
|
||
|
logger := log.FromContext(ctx).WithValues("role_name", roleName)
|
||
|
|
||
|
rows, err := mgr.Conn.Query(ctx, checkUserExists, roleName)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
defer rows.Close()
|
||
|
|
||
|
_, err = pgx.CollectExactlyOneRow(rows, func(row pgx.CollectableRow) (out int, err error) {
|
||
|
err = row.Scan(&out)
|
||
|
return
|
||
|
})
|
||
|
if err != nil {
|
||
|
if !errors.Is(err, pgx.ErrNoRows) {
|
||
|
return err
|
||
|
}
|
||
|
logger.Info("No rows, this means the role does not exists, creating it now")
|
||
|
} else {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
script, err := migrations.RoleCreationScript(roleName)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
_, err = mgr.Conn.Exec(ctx, script.Content)
|
||
|
|
||
|
return err
|
||
|
}
|