mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 13:35:42 +09:00
feat: add role via system to rejoining visionaries (#1198)
Co-authored-by: Hampus <[email protected]>
This commit is contained in:
1 parent
8e1e9a67de
commit
4545fe018e
7 files changed
+43
-4
No files matched your search
@@ -370,6 +370,7 @@ export function buildAPIConfigFromMaster(master: MasterConfig): APIConfig {
|
||||
selfHosted: master.instance.self_hosted,
|
||||
autoJoinInviteCode: master.instance.auto_join_invite_code,
|
||||
visionariesGuildId: master.instance.visionaries_guild_id,
|
||||
visionariesGuildVisionaryRoleId: master.instance.visionaries_guild_visionary_role_id,
|
||||
branding: {
|
||||
productName: master.instance.branding.product_name,
|
||||
iconUrl: master.instance.branding.icon_url,
|
||||
|
||||
@@ -281,6 +281,7 @@ export interface APIConfig {
|
||||
selfHosted: boolean;
|
||||
autoJoinInviteCode?: string;
|
||||
visionariesGuildId?: string;
|
||||
visionariesGuildVisionaryRoleId?: string;
|
||||
branding: {
|
||||
productName: string;
|
||||
iconUrl?: string;
|
||||
|
||||
@@ -4,8 +4,9 @@ import {UserPremiumTypes} from '@fluxer/constants/src/UserConstants';
|
||||
import {MissingAccessError} from '@fluxer/errors/src/domains/core/MissingAccessError';
|
||||
import {StripeError} from '@fluxer/errors/src/domains/payment/StripeError';
|
||||
import type {UserID} from '../../BrandedTypes';
|
||||
import {createGuildID} from '../../BrandedTypes';
|
||||
import {createGuildID, createRoleID} from '../../BrandedTypes';
|
||||
import {Config} from '../../Config';
|
||||
import {SYSTEM_USER_ID} from '../../constants/Core';
|
||||
import type {GiftCodeDurationType} from '../../database/types/PaymentTypes';
|
||||
import type {UserRow} from '../../database/types/UserTypes';
|
||||
import type {IGuildRepositoryAggregate} from '../../guild/repositories/IGuildRepositoryAggregate';
|
||||
@@ -286,7 +287,12 @@ export class StripePremiumService {
|
||||
if (!Config.instance.visionariesGuildId) {
|
||||
throw new StripeError('Visionaries guild id not configured');
|
||||
}
|
||||
if (!Config.instance.visionariesGuildVisionaryRoleId) {
|
||||
throw new StripeError('Visionaries guild visionary role id not configured');
|
||||
}
|
||||
const visionariesGuildId = createGuildID(BigInt(Config.instance.visionariesGuildId));
|
||||
const visionaryRoleId = createRoleID(BigInt(Config.instance.visionariesGuildVisionaryRoleId));
|
||||
const requestCache = createRequestCache();
|
||||
const existingMember = await this.guildRepository.getMember(visionariesGuildId, userId);
|
||||
if (!existingMember) {
|
||||
await this.guildService.members.addUserToGuild({
|
||||
@@ -294,10 +300,25 @@ export class StripePremiumService {
|
||||
guildId: visionariesGuildId,
|
||||
sendJoinMessage: true,
|
||||
skipBanCheck: true,
|
||||
requestCache: createRequestCache(),
|
||||
requestCache,
|
||||
});
|
||||
Logger.debug({userId, guildId: visionariesGuildId}, 'Added visionary user to visionaries guild');
|
||||
}
|
||||
|
||||
try {
|
||||
await this.guildService.members.systemAddMemberRole({
|
||||
targetId: userId,
|
||||
guildId: visionariesGuildId,
|
||||
roleId: visionaryRoleId,
|
||||
initiatorId: SYSTEM_USER_ID,
|
||||
requestCache,
|
||||
});
|
||||
} catch (error) {
|
||||
Logger.error(
|
||||
{userId, guildId: visionariesGuildId, roleId: visionaryRoleId, error},
|
||||
'Failed to add visionary role to a rejoining visionary.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async dispatchUser(user: User): Promise<void> {
|
||||
|
||||
@@ -5,26 +5,31 @@ import {UserPremiumTypes} from '@fluxer/constants/src/UserConstants';
|
||||
import {afterAll, beforeAll, beforeEach, describe, expect, test} from 'vitest';
|
||||
import {createTestAccount} from '../../auth/tests/AuthTestUtils';
|
||||
import {Config} from '../../Config';
|
||||
import {createGuild} from '../../guild/tests/GuildTestUtils';
|
||||
import {createGuild, createRole, getMember} from '../../guild/tests/GuildTestUtils';
|
||||
import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness';
|
||||
import {createBuilder} from '../../test/TestRequestBuilder';
|
||||
|
||||
describe('StripePremiumService', () => {
|
||||
let harness: ApiTestHarness;
|
||||
let originalVisionariesGuildId: string | undefined;
|
||||
let originalVisionariesGuildVisionaryRoleId: string | undefined;
|
||||
beforeAll(async () => {
|
||||
harness = await createApiTestHarness();
|
||||
originalVisionariesGuildId = Config.instance.visionariesGuildId ?? undefined;
|
||||
originalVisionariesGuildVisionaryRoleId = Config.instance.visionariesGuildVisionaryRoleId ?? undefined;
|
||||
});
|
||||
afterAll(async () => {
|
||||
await harness.shutdown();
|
||||
Config.instance.visionariesGuildId = originalVisionariesGuildId;
|
||||
Config.instance.visionariesGuildVisionaryRoleId = originalVisionariesGuildVisionaryRoleId;
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await harness.resetData();
|
||||
const owner = await createTestAccount(harness);
|
||||
const visionariesGuild = await createGuild(harness, owner.token, 'Visionaries Test Guild');
|
||||
const visionaryRole = await createRole(harness, owner.token, visionariesGuild.id, {name: 'Visionary'});
|
||||
Config.instance.visionariesGuildId = visionariesGuild.id;
|
||||
Config.instance.visionariesGuildVisionaryRoleId = visionaryRole.id;
|
||||
});
|
||||
describe('POST /premium/visionary/rejoin', () => {
|
||||
test('allows visionary users to rejoin guild', async () => {
|
||||
@@ -37,6 +42,8 @@ describe('StripePremiumService', () => {
|
||||
})
|
||||
.execute();
|
||||
await createBuilder(harness, account.token).post('/premium/visionary/rejoin').expect(204).execute();
|
||||
const member = await getMember(harness, account.token, Config.instance.visionariesGuildId!, account.userId);
|
||||
expect(member.roles).toContain(Config.instance.visionariesGuildVisionaryRoleId);
|
||||
});
|
||||
test('rejects users without visionary access', async () => {
|
||||
const account = await createTestAccount(harness);
|
||||
|
||||
@@ -5,26 +5,31 @@ import {UserPremiumTypes} from '@fluxer/constants/src/UserConstants';
|
||||
import {afterAll, beforeAll, beforeEach, describe, expect, test} from 'vitest';
|
||||
import {createTestAccount} from '../../auth/tests/AuthTestUtils';
|
||||
import {Config} from '../../Config';
|
||||
import {createGuild} from '../../guild/tests/GuildTestUtils';
|
||||
import {createGuild, createRole, getMember} from '../../guild/tests/GuildTestUtils';
|
||||
import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness';
|
||||
import {createBuilder} from '../../test/TestRequestBuilder';
|
||||
|
||||
describe('Stripe Webhook Edge Cases', () => {
|
||||
let harness: ApiTestHarness;
|
||||
let originalVisionariesGuildId: string | undefined;
|
||||
let originalVisionariesGuildVisionaryRoleId: string | undefined;
|
||||
beforeAll(async () => {
|
||||
harness = await createApiTestHarness();
|
||||
originalVisionariesGuildId = Config.instance.visionariesGuildId ?? undefined;
|
||||
originalVisionariesGuildVisionaryRoleId = Config.instance.visionariesGuildVisionaryRoleId ?? undefined;
|
||||
});
|
||||
afterAll(async () => {
|
||||
await harness.shutdown();
|
||||
Config.instance.visionariesGuildId = originalVisionariesGuildId;
|
||||
Config.instance.visionariesGuildVisionaryRoleId = originalVisionariesGuildVisionaryRoleId;
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await harness.resetData();
|
||||
const owner = await createTestAccount(harness);
|
||||
const visionariesGuild = await createGuild(harness, owner.token, 'Visionaries Webhook Test Guild');
|
||||
const visionaryRole = await createRole(harness, owner.token, visionariesGuild.id, {name: 'Visionary'});
|
||||
Config.instance.visionariesGuildId = visionariesGuild.id;
|
||||
Config.instance.visionariesGuildVisionaryRoleId = visionaryRole.id;
|
||||
});
|
||||
describe('Premium stacking - consecutive grants extending duration', () => {
|
||||
test('stacks multiple monthly subscriptions end-to-end', async () => {
|
||||
@@ -366,6 +371,8 @@ describe('Stripe Webhook Edge Cases', () => {
|
||||
.execute();
|
||||
expect(receiverAfter.premium_type).toBe(UserPremiumTypes.LIFETIME);
|
||||
expect(receiverAfter.premium_lifetime_sequence).toBe(0);
|
||||
const member = await getMember(harness, receiver.token, Config.instance.visionariesGuildId!, receiver.userId);
|
||||
expect(member.roles).toContain(Config.instance.visionariesGuildVisionaryRoleId);
|
||||
});
|
||||
test('redeeming 1-month gift code grants subscription premium', async () => {
|
||||
const gifter = await createTestAccount(harness);
|
||||
|
||||
Reference in new issue
Block a user