Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/admin/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@
"resetPasswordTokenMissing": "This reset link is missing its token. Request a new one.",
"resetPasswordTokenDead": "This reset link is invalid or has expired. Request a new one.",
"requestNewResetLink": "Request a new reset link",
"newPassword": "New password"
"newPassword": "New password",
"signInWithSso": "Sign in with SSO"
Comment thread
alex-budanov marked this conversation as resolved.
},
"dashboard": {
"title": "Dashboard",
Expand Down
3 changes: 2 additions & 1 deletion apps/admin/src/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@
"resetPasswordTokenMissing": "В ссылке для сброса отсутствует токен. Запросите новую.",
"resetPasswordTokenDead": "Ссылка для сброса недействительна или истекла. Запросите новую.",
"requestNewResetLink": "Запросить новую ссылку",
"newPassword": "Новый пароль"
"newPassword": "Новый пароль",
"signInWithSso": "Войти через SSO"
},
"dashboard": {
"title": "Панель управления",
Expand Down
15 changes: 15 additions & 0 deletions apps/admin/src/services/auth-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ export const authService = {
return response.data.data;
},

/**
* Resolve whether the current tenant (by host/subdomain) has made SSO
* mandatory. Unauthenticated, same pre-auth shape as getRegistrationStatus().
*/
getSsoStatus: async (): Promise<{ enforceSso: boolean }> => {
const response = await api.get<{ success: boolean; data: { enforceSso: boolean } }>(
// Path matches #414's specified route contract (backend endpoint,
// tracked separately as this slice's blocking prerequisite). Inlined
// rather than added to api-constants.ts; mirrors auth.registrationStatus()'s
// `/api/v1/auth/registration-status` naming.
'/api/v1/auth/sso-status'
);
Comment thread
alex-budanov marked this conversation as resolved.
return response.data.data;
},

logout: async (): Promise<void> => {
await api.post(API_ENDPOINTS.auth.logout());
},
Expand Down
19 changes: 19 additions & 0 deletions apps/admin/src/tests/services/auth-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,25 @@ describe('Auth Service', () => {
});
});

describe('getSsoStatus', () => {
it('should return enforceSso: true when SSO is mandatory for the tenant', async () => {
vi.mocked(api.get).mockResolvedValueOnce({
data: { success: true, data: { enforceSso: true } },
} as AxiosResponse);

const result = await authService.getSsoStatus();

expect(result).toEqual({ enforceSso: true });
expect(api.get).toHaveBeenCalledWith('/api/v1/auth/sso-status');
});

it('should propagate API errors', async () => {
vi.mocked(api.get).mockRejectedValueOnce(new Error('Network error'));

await expect(authService.getSsoStatus()).rejects.toThrow('Network error');
});
});
Comment thread
alex-budanov marked this conversation as resolved.

describe('login', () => {
it('should login with email and password', async () => {
const mockResponse = {
Expand Down
Loading