-
Notifications
You must be signed in to change notification settings - Fork 308
feat(pentest): credits wallet, admin grants, audit logging, UX polish #2691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
db0e7e7
feat(pentest): full v1 rebuild — split-view UI, SDK swap, signed webh…
tofikwest f494299
feat(pentest): credits wallet, admin grants, audit logging, UX polish
tofikwest 9da3780
Merge main into feat/pentest-credits
tofikwest ebed6cc
fix(pentest): address cubic-AI review — refund tx, audit dedup, UX bugs
tofikwest 648ad0e
chore(pentest): delete stale frontend test files
tofikwest 4aeef2a
fix(pentest): api-side maced filter, schema docs, drop stale planning…
tofikwest 23396c6
Merge branch 'main' into feat/pentest-credits
tofikwest f5e2528
fix(pentest): second cubic review pass — refund retry, ux + correctness
tofikwest f7a9ce9
fix(api): purge snapshot — null out stripe IDs from dropped tables
tofikwest File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
apps/api/src/admin-organizations/admin-pentest-credits.controller.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| import { | ||
| BadRequestException, | ||
| Body, | ||
| Controller, | ||
| Get, | ||
| Param, | ||
| Post, | ||
| UseGuards, | ||
| UseInterceptors, | ||
| } from '@nestjs/common'; | ||
| import { ApiExcludeController, ApiOperation, ApiTags } from '@nestjs/swagger'; | ||
| import { Throttle } from '@nestjs/throttler'; | ||
| import { IsInt, IsOptional, IsString, Max, Min } from 'class-validator'; | ||
| import { PlatformAdminGuard } from '../auth/platform-admin.guard'; | ||
| import { PentestCreditsService } from '../security-penetration-tests/pentest-credits.service'; | ||
| import { AdminAuditLogInterceptor } from './admin-audit-log.interceptor'; | ||
|
|
||
| /** | ||
| * Request body for granting credits via the admin panel. `amount` is capped | ||
| * at 1000 to prevent typo-induced runaway grants — admins can submit | ||
| * multiple times if a larger pool is genuinely needed. | ||
| */ | ||
| class GrantPentestCreditsDto { | ||
| @IsInt() | ||
| @Min(1) | ||
| @Max(1000) | ||
| amount!: number; | ||
|
|
||
| /** | ||
| * Free-form note. Persisted on the audit log entry as `data.note` so | ||
| * support / compliance can reconstruct *why* a grant happened. | ||
| */ | ||
| @IsOptional() | ||
| @IsString() | ||
| note?: string; | ||
| } | ||
|
|
||
| @ApiExcludeController() | ||
| @ApiTags('Admin - Pentest Credits') | ||
| @Controller({ path: 'admin/organizations', version: '1' }) | ||
| @UseGuards(PlatformAdminGuard) | ||
| @UseInterceptors(AdminAuditLogInterceptor) | ||
| @Throttle({ default: { ttl: 60_000, limit: 30 } }) | ||
| export class AdminPentestCreditsController { | ||
| constructor(private readonly credits: PentestCreditsService) {} | ||
|
|
||
| @Get(':orgId/pentest-credits') | ||
| @ApiOperation({ | ||
| summary: 'Get pentest credit wallet status for any organization', | ||
| }) | ||
| async getStatus(@Param('orgId') orgId: string) { | ||
| return this.credits.getStatus(orgId); | ||
| } | ||
|
|
||
| // POST /:orgId/pentest-credits (no `/grant` suffix). The | ||
| // AdminAuditLogInterceptor's URL parser treats the segment after the | ||
| // resource as an entity id; if we used `/grant`, the audit log | ||
| // would record `entityId: "grant"` which is meaningless and breaks | ||
| // the admin audit trail. Keeping the route shape standard | ||
| // (`:orgId/<resource>`) lets the interceptor produce correct metadata. | ||
| @Post(':orgId/pentest-credits') | ||
| @ApiOperation({ | ||
| summary: 'Grant pentest credits to an organization (platform admin)', | ||
| }) | ||
| async grant( | ||
| @Param('orgId') orgId: string, | ||
| @Body() body: GrantPentestCreditsDto, | ||
| ) { | ||
| if (!Number.isInteger(body.amount) || body.amount < 1) { | ||
| throw new BadRequestException('amount must be a positive integer'); | ||
| } | ||
| await this.credits.grant(orgId, body.amount, 'manual'); | ||
| return this.credits.getStatus(orgId); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.