mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
fix(api): credit self-hosted gift codes to the issuing admin (#3119)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {Config} from '@app/api/Config';
|
||||
import {SYSTEM_USER_ID} from '@app/api/constants/Core';
|
||||
import {requireAdminACL} from '@app/api/middleware/AdminMiddleware';
|
||||
import {RateLimitMiddleware} from '@app/api/middleware/RateLimitMiddleware';
|
||||
import {OpenAPI} from '@app/api/middleware/ResponseTypeMiddleware';
|
||||
@@ -42,6 +43,7 @@ export function CodesAdminController(app: HonoApp) {
|
||||
count,
|
||||
durationType: duration_type,
|
||||
durationQuantity: duration_quantity,
|
||||
createdByUserId: Config.instance.selfHosted ? ctx.get('adminUserId') : SYSTEM_USER_ID,
|
||||
});
|
||||
await adminService.auditService.createAuditLog({
|
||||
adminUserId: ctx.get('adminUserId'),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {SYSTEM_USER_ID} from '@app/api/constants/Core';
|
||||
import type {UserID} from '@app/api/BrandedTypes';
|
||||
import type {GiftCodeDurationType, GiftCodeRow} from '@app/api/database/types/PaymentTypes';
|
||||
import {mapGiftCodeDurationToMonths} from '@app/api/models/GiftCode';
|
||||
import type {IUserRepository} from '@app/api/user/IUserRepository';
|
||||
@@ -15,13 +15,14 @@ interface GenerateGiftCodesOptions {
|
||||
count: number;
|
||||
durationType: GiftCodeDurationType;
|
||||
durationQuantity: number;
|
||||
createdByUserId: UserID;
|
||||
}
|
||||
|
||||
export class AdminCodeGenerationService {
|
||||
constructor(private readonly userRepository: IUserRepository) {}
|
||||
|
||||
async generateGiftCodes(options: GenerateGiftCodesOptions): Promise<Array<string>> {
|
||||
const {count, durationType, durationQuantity} = this.validateOptions(options);
|
||||
const {count, durationType, durationQuantity, createdByUserId} = this.validateOptions(options);
|
||||
const durationMonths = mapGiftCodeDurationToMonths(durationType, durationQuantity);
|
||||
const codes: Array<string> = [];
|
||||
for (let i = 0; i < count; i += 1) {
|
||||
@@ -32,7 +33,7 @@ export class AdminCodeGenerationService {
|
||||
duration_type: durationType,
|
||||
duration_quantity: durationQuantity,
|
||||
created_at: new Date(),
|
||||
created_by_user_id: SYSTEM_USER_ID,
|
||||
created_by_user_id: createdByUserId,
|
||||
redeemed_at: null,
|
||||
redeemed_by_user_id: null,
|
||||
stripe_payment_intent_id: null,
|
||||
|
||||
@@ -284,6 +284,22 @@ describe('self-hosted premium routes', () => {
|
||||
expect(gifts).toEqual([]);
|
||||
});
|
||||
|
||||
test('credits admin generated gift codes to the issuing admin', async () => {
|
||||
const admin = await setUserACLs(harness, await createTestAccount(harness), [
|
||||
AdminACLs.AUTHENTICATE,
|
||||
AdminACLs.GIFT_CODES_GENERATE,
|
||||
]);
|
||||
const {codes} = await createBuilder<{codes: Array<string>}>(harness, admin.token)
|
||||
.post('/admin/gift-codes')
|
||||
.body({count: 1, duration_type: 'months', duration_quantity: 1})
|
||||
.execute();
|
||||
const code = codes[0]?.split('/').pop();
|
||||
const gift = await createBuilderWithoutAuth<{created_by: {id: string} | null}>(harness)
|
||||
.get(`/gifts/${code}`)
|
||||
.execute();
|
||||
expect(gift.created_by?.id).toBe(admin.userId);
|
||||
});
|
||||
|
||||
test('keeps purchase and hosted-only routes unavailable', async () => {
|
||||
const account = await createTestAccount(harness);
|
||||
await expectRoutesNotFound(harness, account.token, [
|
||||
|
||||
Reference in New Issue
Block a user