forked from baron/baron-sso
test 코드 수정
This commit is contained in:
@@ -1,16 +1,19 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"baron-sso-backend/internal/service"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type AdminHandler struct{}
|
||||
type AdminHandler struct {
|
||||
Keto service.KetoService
|
||||
}
|
||||
|
||||
func NewAdminHandler() *AdminHandler {
|
||||
return &AdminHandler{}
|
||||
func NewAdminHandler(keto service.KetoService) *AdminHandler {
|
||||
return &AdminHandler{Keto: keto}
|
||||
}
|
||||
|
||||
func (h *AdminHandler) CheckAuth(c *fiber.Ctx) error {
|
||||
|
||||
@@ -24,7 +24,7 @@ type DevHandler struct {
|
||||
ConsentRepo repository.ClientConsentRepository
|
||||
}
|
||||
|
||||
func NewDevHandler(redis domain.RedisRepository, secretRepo domain.ClientSecretRepository, consentRepo repository.ClientConsentRepository) *DevHandler {
|
||||
func NewDevHandler(redis domain.RedisRepository, secretRepo domain.ClientSecretRepository, consentRepo repository.ClientConsentRepository, rpSvc service.RelyingPartyService) *DevHandler {
|
||||
return &DevHandler{
|
||||
Hydra: service.NewHydraAdminService(),
|
||||
Redis: redis,
|
||||
|
||||
@@ -9,11 +9,12 @@ import (
|
||||
)
|
||||
|
||||
type RelyingPartyHandler struct {
|
||||
Service service.RelyingPartyService
|
||||
Service service.RelyingPartyService
|
||||
KratosAdmin *service.KratosAdminService
|
||||
}
|
||||
|
||||
func NewRelyingPartyHandler(s service.RelyingPartyService) *RelyingPartyHandler {
|
||||
return &RelyingPartyHandler{Service: s}
|
||||
func NewRelyingPartyHandler(s service.RelyingPartyService, kratos *service.KratosAdminService) *RelyingPartyHandler {
|
||||
return &RelyingPartyHandler{Service: s, KratosAdmin: kratos}
|
||||
}
|
||||
|
||||
func (h *RelyingPartyHandler) Create(c *fiber.Ctx) error {
|
||||
|
||||
@@ -12,12 +12,19 @@ import (
|
||||
)
|
||||
|
||||
type TenantHandler struct {
|
||||
DB *gorm.DB
|
||||
Service service.TenantService
|
||||
DB *gorm.DB
|
||||
Service service.TenantService
|
||||
Keto service.KetoService
|
||||
KratosAdmin *service.KratosAdminService
|
||||
}
|
||||
|
||||
func NewTenantHandler(db *gorm.DB, svc service.TenantService) *TenantHandler {
|
||||
return &TenantHandler{DB: db, Service: svc}
|
||||
func NewTenantHandler(db *gorm.DB, svc service.TenantService, keto service.KetoService, kratos *service.KratosAdminService) *TenantHandler {
|
||||
return &TenantHandler{
|
||||
DB: db,
|
||||
Service: svc,
|
||||
Keto: keto,
|
||||
KratosAdmin: kratos,
|
||||
}
|
||||
}
|
||||
|
||||
type tenantSummary struct {
|
||||
@@ -301,6 +308,85 @@ func (h *TenantHandler) DeleteTenant(c *fiber.Ctx) error {
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
func (h *TenantHandler) ListAdmins(c *fiber.Ctx) error {
|
||||
tenantID := c.Params("id")
|
||||
if tenantID == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenant id is required"})
|
||||
}
|
||||
|
||||
// Fetch admins from Keto
|
||||
relations, err := h.Keto.ListRelations(c.Context(), "Tenant", tenantID, "admin", "")
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
|
||||
type adminInfo struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
admins := []adminInfo{}
|
||||
|
||||
for _, rel := range relations {
|
||||
if !strings.HasPrefix(rel.SubjectID, "User:") {
|
||||
continue
|
||||
}
|
||||
userID := strings.TrimPrefix(rel.SubjectID, "User:")
|
||||
|
||||
// Fetch user details from Kratos
|
||||
identity, err := h.KratosAdmin.GetIdentity(c.Context(), userID)
|
||||
if err != nil {
|
||||
admins = append(admins, adminInfo{ID: userID, Name: "Unknown", Email: "Unknown"})
|
||||
continue
|
||||
}
|
||||
|
||||
name := ""
|
||||
if n, ok := identity.Traits["name"].(string); ok {
|
||||
name = n
|
||||
}
|
||||
email := ""
|
||||
if e, ok := identity.Traits["email"].(string); ok {
|
||||
email = e
|
||||
}
|
||||
|
||||
admins = append(admins, adminInfo{
|
||||
ID: userID,
|
||||
Name: name,
|
||||
Email: email,
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(admins)
|
||||
}
|
||||
|
||||
func (h *TenantHandler) AddAdmin(c *fiber.Ctx) error {
|
||||
tenantID := c.Params("id")
|
||||
userID := c.Params("userId")
|
||||
if tenantID == "" || userID == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenantId and userId are required"})
|
||||
}
|
||||
|
||||
if err := h.Keto.CreateRelation(c.Context(), "Tenant", tenantID, "admin", "User:"+userID); err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
func (h *TenantHandler) RemoveAdmin(c *fiber.Ctx) error {
|
||||
tenantID := c.Params("id")
|
||||
userID := c.Params("userId")
|
||||
if tenantID == "" || userID == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenantId and userId are required"})
|
||||
}
|
||||
|
||||
if err := h.Keto.DeleteRelation(c.Context(), "Tenant", tenantID, "admin", "User:"+userID); err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
func mapTenantSummary(t domain.Tenant) tenantSummary {
|
||||
domains := make([]string, 0, len(t.Domains))
|
||||
for _, d := range t.Domains {
|
||||
|
||||
@@ -54,6 +54,14 @@ func (m *MockKetoService) ListRelations(ctx context.Context, namespace, object,
|
||||
return args.Get(0).([]service.RelationTuple), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockKetoService) ListObjects(ctx context.Context, namespace, relation, subject string) ([]string, error) {
|
||||
args := m.Called(ctx, namespace, relation, subject)
|
||||
if args.Get(0) == nil {
|
||||
return nil, args.Error(1)
|
||||
}
|
||||
return args.Get(0).([]string), args.Error(1)
|
||||
}
|
||||
|
||||
// Fixed MockKetoService to match service.KetoService exactly if possible.
|
||||
// Wait, middleware/rbac.go imports baron-sso-backend/internal/service.
|
||||
// So I should use service.RelationTuple.
|
||||
|
||||
@@ -4,4 +4,8 @@ import 'locale_storage_stub.dart'
|
||||
abstract class LocaleStorage {
|
||||
static String? read() => localeStorage.read();
|
||||
static void write(String locale) => localeStorage.write(locale);
|
||||
static void forceMemoryStorageForTests(bool value) =>
|
||||
localeStorage.forceMemoryStorageForTests(value);
|
||||
static void forceSessionStorageForTests(bool value) =>
|
||||
localeStorage.forceSessionStorageForTests(value);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,14 @@ class LocaleStorageImpl {
|
||||
void write(String locale) {
|
||||
_locale = locale;
|
||||
}
|
||||
|
||||
void forceMemoryStorageForTests(bool value) {
|
||||
// Stub
|
||||
}
|
||||
|
||||
void forceSessionStorageForTests(bool value) {
|
||||
// Stub
|
||||
}
|
||||
}
|
||||
|
||||
final localeStorage = LocaleStorageImpl();
|
||||
|
||||
@@ -11,7 +11,7 @@ class LocaleStorageImpl {
|
||||
static bool _forceSession = false;
|
||||
|
||||
@visibleForTesting
|
||||
static void forceMemoryStorageForTests(bool value) {
|
||||
void forceMemoryStorageForTests(bool value) {
|
||||
_forceMemory = value;
|
||||
if (!value) {
|
||||
_memory.clear();
|
||||
@@ -19,7 +19,7 @@ class LocaleStorageImpl {
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
static void forceSessionStorageForTests(bool value) {
|
||||
void forceSessionStorageForTests(bool value) {
|
||||
_forceSession = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:userfront/core/i18n/locale_storage.dart';
|
||||
import 'package:userfront/core/i18n/locale_storage_web.dart' as locale_web;
|
||||
|
||||
import 'helpers/web_storage.dart';
|
||||
|
||||
void main() {
|
||||
setUp(() {
|
||||
locale_web.LocaleStorageImpl.forceMemoryStorageForTests(false);
|
||||
locale_web.LocaleStorageImpl.forceSessionStorageForTests(false);
|
||||
LocaleStorage.forceMemoryStorageForTests(false);
|
||||
LocaleStorage.forceSessionStorageForTests(false);
|
||||
if (webStorage.isWeb) {
|
||||
webStorage.clear();
|
||||
webStorage.clearSession();
|
||||
@@ -15,8 +14,8 @@ void main() {
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
locale_web.LocaleStorageImpl.forceMemoryStorageForTests(false);
|
||||
locale_web.LocaleStorageImpl.forceSessionStorageForTests(false);
|
||||
LocaleStorage.forceMemoryStorageForTests(false);
|
||||
LocaleStorage.forceSessionStorageForTests(false);
|
||||
if (webStorage.isWeb) {
|
||||
webStorage.clear();
|
||||
webStorage.clearSession();
|
||||
@@ -59,7 +58,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
locale_web.LocaleStorageImpl.forceMemoryStorageForTests(true);
|
||||
LocaleStorage.forceMemoryStorageForTests(true);
|
||||
|
||||
LocaleStorage.write('en');
|
||||
expect(webStorage.get('locale'), isNull);
|
||||
@@ -76,7 +75,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
locale_web.LocaleStorageImpl.forceSessionStorageForTests(true);
|
||||
LocaleStorage.forceSessionStorageForTests(true);
|
||||
|
||||
LocaleStorage.write('ko');
|
||||
expect(webStorage.get('locale'), isNull);
|
||||
|
||||
Reference in New Issue
Block a user