|
4 | 4 | AuthFlow, |
5 | 5 | AuthStep, |
6 | 6 | } from '../../../src/authentication'; |
| 7 | +import { BaseApiRouter } from '../../../src/router'; |
7 | 8 | import { InMemorySessionDriver } from '../../../src/session'; |
8 | 9 | import { SessionDriver } from '../../../src/session'; |
9 | 10 | import { Session } from '../../../src/session/session'; |
@@ -471,4 +472,145 @@ describe('SessionAuthenticationScheme', () => { |
471 | 472 | }); |
472 | 473 | }); |
473 | 474 | }); |
| 475 | + |
| 476 | + describe('getAuthRouter()', () => { |
| 477 | + it('should return a router instance', () => { |
| 478 | + const scheme = new TestSessionScheme(); |
| 479 | + const router = scheme.getAuthRouter(); |
| 480 | + |
| 481 | + expect(router).toBeDefined(); |
| 482 | + expect(router.path).toBe(''); |
| 483 | + }); |
| 484 | + |
| 485 | + it('should set router path from basePath parameter', () => { |
| 486 | + const scheme = new TestSessionScheme(); |
| 487 | + const router = scheme.getAuthRouter('/auth'); |
| 488 | + |
| 489 | + expect(router.path).toBe('/auth'); |
| 490 | + }); |
| 491 | + |
| 492 | + it('should expose all auth steps as routes', () => { |
| 493 | + class ChallengeStep extends AuthStep { |
| 494 | + override path = '/challenge'; |
| 495 | + async handle() { |
| 496 | + return { challenge: 'test' }; |
| 497 | + } |
| 498 | + } |
| 499 | + |
| 500 | + class AuthStep2 extends AuthStep { |
| 501 | + override path = '/authorize'; |
| 502 | + async handle() { |
| 503 | + return { code: 'abc123' }; |
| 504 | + } |
| 505 | + } |
| 506 | + |
| 507 | + class TokenStep extends AuthStep { |
| 508 | + override path = '/token'; |
| 509 | + async handle() { |
| 510 | + return { token: 'xyz789' }; |
| 511 | + } |
| 512 | + } |
| 513 | + |
| 514 | + class TestSchemeWithSteps extends SessionAuthenticationScheme { |
| 515 | + public readonly schemeName = 'TestScheme'; |
| 516 | + public readonly type = 'oauth2' as const; |
| 517 | + |
| 518 | + public getSecurityScheme(): SecuritySchemeObject { |
| 519 | + return { |
| 520 | + type: 'oauth2' as const, |
| 521 | + flows: { |
| 522 | + authorizationCode: { |
| 523 | + authorizationUrl: 'http://example.com/auth', |
| 524 | + tokenUrl: 'http://example.com/token', |
| 525 | + scopes: {}, |
| 526 | + }, |
| 527 | + }, |
| 528 | + }; |
| 529 | + } |
| 530 | + |
| 531 | + public getAuthFlow(): AuthFlow { |
| 532 | + return { |
| 533 | + challenge: ChallengeStep, |
| 534 | + authorize: AuthStep2, |
| 535 | + token: TokenStep, |
| 536 | + }; |
| 537 | + } |
| 538 | + } |
| 539 | + |
| 540 | + const scheme = new TestSchemeWithSteps(); |
| 541 | + const router = scheme.getAuthRouter('/oauth'); |
| 542 | + |
| 543 | + // Verify router has correct path and is a BaseApiRouter |
| 544 | + expect(router).toBeDefined(); |
| 545 | + expect(router.path).toBe('/oauth'); |
| 546 | + expect(router).toBeInstanceOf(BaseApiRouter); |
| 547 | + }); |
| 548 | + |
| 549 | + it('should work with empty basePath', () => { |
| 550 | + const scheme = new TestSessionScheme(); |
| 551 | + const router = scheme.getAuthRouter(); |
| 552 | + |
| 553 | + expect(router.path).toBe(''); |
| 554 | + }); |
| 555 | + |
| 556 | + it('should return different router instances on each call', () => { |
| 557 | + const scheme = new TestSessionScheme(); |
| 558 | + const router1 = scheme.getAuthRouter('/auth'); |
| 559 | + const router2 = scheme.getAuthRouter('/auth'); |
| 560 | + |
| 561 | + expect(router1).not.toBe(router2); |
| 562 | + }); |
| 563 | + |
| 564 | + it('should return auth steps from routes() method', async () => { |
| 565 | + class ChallengeStep extends AuthStep { |
| 566 | + override path = '/challenge'; |
| 567 | + async handle() { |
| 568 | + return { challenge: 'test' }; |
| 569 | + } |
| 570 | + } |
| 571 | + |
| 572 | + class TokenStep extends AuthStep { |
| 573 | + override path = '/token'; |
| 574 | + async handle() { |
| 575 | + return { token: 'xyz789' }; |
| 576 | + } |
| 577 | + } |
| 578 | + |
| 579 | + class TestSchemeWithRoutes extends SessionAuthenticationScheme { |
| 580 | + public readonly schemeName = 'TestScheme'; |
| 581 | + public readonly type = 'oauth2' as const; |
| 582 | + |
| 583 | + public getSecurityScheme(): SecuritySchemeObject { |
| 584 | + return { |
| 585 | + type: 'oauth2' as const, |
| 586 | + flows: { |
| 587 | + authorizationCode: { |
| 588 | + authorizationUrl: 'http://example.com/auth', |
| 589 | + tokenUrl: 'http://example.com/token', |
| 590 | + scopes: {}, |
| 591 | + }, |
| 592 | + }, |
| 593 | + }; |
| 594 | + } |
| 595 | + |
| 596 | + public getAuthFlow(): AuthFlow { |
| 597 | + return { |
| 598 | + challenge: ChallengeStep, |
| 599 | + token: TokenStep, |
| 600 | + }; |
| 601 | + } |
| 602 | + } |
| 603 | + |
| 604 | + const scheme = new TestSchemeWithRoutes(); |
| 605 | + const router = scheme.getAuthRouter('/auth'); |
| 606 | + |
| 607 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 608 | + const routes = await (router as any).routes(); |
| 609 | + |
| 610 | + expect(routes).toBeDefined(); |
| 611 | + expect(routes.length).toBe(2); |
| 612 | + expect(routes[0]).toBe(ChallengeStep); |
| 613 | + expect(routes[1]).toBe(TokenStep); |
| 614 | + }); |
| 615 | + }); |
474 | 616 | }); |
0 commit comments