Add admin console access and platform pages (trust, users, keys, workloads, settings)
This commit is contained in:
@@ -35,6 +35,7 @@ func (s stubRepo) SetVerified(context.Context, uuid.UUID, bool) error {
|
||||
func (s stubRepo) SetRole(context.Context, uuid.UUID, domain.Role) error {
|
||||
return usecase.ErrUserNotFound
|
||||
}
|
||||
func (s stubRepo) ListUsers(context.Context) ([]*domain.User, error) { return nil, nil }
|
||||
|
||||
type stubHasher struct {
|
||||
hashErr error
|
||||
|
||||
@@ -28,6 +28,10 @@ type UserRepository interface {
|
||||
// SetRole changes a user's role, returning ErrUserNotFound if no such user
|
||||
// exists.
|
||||
SetRole(ctx context.Context, id uuid.UUID, role domain.Role) error
|
||||
// ListUsers returns every account, oldest first. Admin-only: used by the
|
||||
// coordinator admin console; the response must never carry password hashes
|
||||
// (the caller projects the entity).
|
||||
ListUsers(ctx context.Context) ([]*domain.User, error)
|
||||
}
|
||||
|
||||
// WorkerKeyRepository persists and looks up the long-lived worker keys a user
|
||||
@@ -38,12 +42,18 @@ type WorkerKeyRepository interface {
|
||||
Insert(ctx context.Context, k *domain.WorkerKey) error
|
||||
// ListByUser returns a user's live (non-revoked) keys, newest first.
|
||||
ListByUser(ctx context.Context, userID uuid.UUID) ([]*domain.WorkerKey, error)
|
||||
// ListAll returns every key (revoked included), newest first. Admin-only:
|
||||
// backs the coordinator admin console's key table.
|
||||
ListAll(ctx context.Context) ([]*domain.WorkerKey, error)
|
||||
// GetActiveByHash returns the non-revoked key with the given hash, or
|
||||
// ErrWorkerKeyNotFound.
|
||||
GetActiveByHash(ctx context.Context, tokenHash string) (*domain.WorkerKey, error)
|
||||
// Revoke retires a key the user owns, returning ErrWorkerKeyNotFound when no
|
||||
// live key with that id belongs to the user.
|
||||
Revoke(ctx context.Context, id, userID uuid.UUID) error
|
||||
// RevokeAny retires a key by id regardless of its owner. Admin-only; the
|
||||
// coordinator admin console uses it to cut a key immediately.
|
||||
RevokeAny(ctx context.Context, id uuid.UUID) error
|
||||
// TouchLastUsed records a successful exchange. Best-effort: a failure here
|
||||
// must not fail the exchange itself.
|
||||
TouchLastUsed(ctx context.Context, id uuid.UUID) error
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package usecase
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/emil28092005/SciMesh/coordinator/internal/userservice/domain"
|
||||
)
|
||||
|
||||
// ListUsers returns every account for the coordinator admin console. The
|
||||
// handler must project the entities so password hashes never leave the service.
|
||||
type ListUsers struct {
|
||||
users UserRepository
|
||||
}
|
||||
|
||||
func NewListUsers(users UserRepository) *ListUsers {
|
||||
return &ListUsers{users: users}
|
||||
}
|
||||
|
||||
func (uc *ListUsers) Execute(ctx context.Context) ([]*domain.User, error) {
|
||||
return uc.users.ListUsers(ctx)
|
||||
}
|
||||
@@ -47,6 +47,34 @@ func (uc *ListWorkerKeys) Execute(ctx context.Context, userID uuid.UUID) ([]*dom
|
||||
return uc.keys.ListByUser(ctx, userID)
|
||||
}
|
||||
|
||||
// ListWorkerKeysAll returns every key in the service, revoked included, for
|
||||
// the coordinator admin console. Admin-only.
|
||||
type ListWorkerKeysAll struct {
|
||||
keys WorkerKeyRepository
|
||||
}
|
||||
|
||||
func NewListWorkerKeysAll(keys WorkerKeyRepository) *ListWorkerKeysAll {
|
||||
return &ListWorkerKeysAll{keys: keys}
|
||||
}
|
||||
|
||||
func (uc *ListWorkerKeysAll) Execute(ctx context.Context) ([]*domain.WorkerKey, error) {
|
||||
return uc.keys.ListAll(ctx)
|
||||
}
|
||||
|
||||
// RevokeWorkerKeyAdmin retires any key, regardless of owner. Admin-only; used
|
||||
// by the coordinator admin console when a key must be cut immediately.
|
||||
type RevokeWorkerKeyAdmin struct {
|
||||
keys WorkerKeyRepository
|
||||
}
|
||||
|
||||
func NewRevokeWorkerKeyAdmin(keys WorkerKeyRepository) *RevokeWorkerKeyAdmin {
|
||||
return &RevokeWorkerKeyAdmin{keys: keys}
|
||||
}
|
||||
|
||||
func (uc *RevokeWorkerKeyAdmin) Execute(ctx context.Context, id uuid.UUID) error {
|
||||
return uc.keys.RevokeAny(ctx, id)
|
||||
}
|
||||
|
||||
// RevokeWorkerKey retires one of the caller's keys.
|
||||
type RevokeWorkerKey struct {
|
||||
keys WorkerKeyRepository
|
||||
|
||||
@@ -64,6 +64,24 @@ func (r *fakeKeyRepo) TouchLastUsed(_ context.Context, id uuid.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *fakeKeyRepo) ListAll(_ context.Context) ([]*domain.WorkerKey, error) {
|
||||
out := make([]*domain.WorkerKey, 0, len(r.byID))
|
||||
for _, k := range r.byID {
|
||||
out = append(out, k)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (r *fakeKeyRepo) RevokeAny(_ context.Context, id uuid.UUID) error {
|
||||
k, ok := r.byID[id]
|
||||
if !ok || k.Revoked() {
|
||||
return usecase.ErrWorkerKeyNotFound
|
||||
}
|
||||
now := time.Now()
|
||||
k.RevokedAt = &now
|
||||
return nil
|
||||
}
|
||||
|
||||
func newKeyFixtures(t *testing.T) (*usecase.CreateWorkerKey, *usecase.ExchangeWorkerKey, *usecase.RevokeWorkerKey, *usecase.ListWorkerKeys, *fakeKeyRepo, *domain.User) {
|
||||
t.Helper()
|
||||
users := memstore.NewUserRepo()
|
||||
|
||||
Reference in New Issue
Block a user