fix: 修复多个服务的 TypeScript 编译错误

- admin-service: 添加 kafkajs 依赖,修复 SystemConfigEntity null vs undefined 类型
- authorization-service: 修复 selfPlantingCount 属性名,修复 AuthorizationRole factory 参数
- identity-service: 修复测试文件 accountSequence 类型(number -> string)
- admin-web: 在 authSlice 中添加 refreshToken 支持

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-19 06:29:49 -08:00
parent 943fd9efe9
commit f20643599e
8 changed files with 105 additions and 57 deletions

View File

@ -24,6 +24,7 @@
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.0", "class-validator": "^0.14.0",
"ioredis": "^5.3.2", "ioredis": "^5.3.2",
"kafkajs": "^2.2.4",
"passport-jwt": "^4.0.1", "passport-jwt": "^4.0.1",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
@ -7116,6 +7117,15 @@
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
}, },
"node_modules/kafkajs": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/kafkajs/-/kafkajs-2.2.4.tgz",
"integrity": "sha512-j/YeapB1vfPT2iOIUn/vxdyKEuhuY2PxMBvf5JWux6iSaukAccrMtXEY/Lb7OvavDhOWME589bpLrEdnVHjfjA==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/keyv": { "node_modules/keyv": {
"version": "4.5.4", "version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",

View File

@ -44,6 +44,7 @@
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.0", "class-validator": "^0.14.0",
"ioredis": "^5.3.2", "ioredis": "^5.3.2",
"kafkajs": "^2.2.4",
"passport-jwt": "^4.0.1", "passport-jwt": "^4.0.1",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
@ -51,7 +52,6 @@
"uuid": "^9.0.1" "uuid": "^9.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/uuid": "^9.0.7",
"@nestjs/cli": "^10.0.0", "@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0", "@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0", "@nestjs/testing": "^10.0.0",
@ -61,6 +61,7 @@
"@types/passport-jwt": "^3.0.13", "@types/passport-jwt": "^3.0.13",
"@types/supertest": "^6.0.0", "@types/supertest": "^6.0.0",
"@types/unzipper": "^0.10.11", "@types/unzipper": "^0.10.11",
"@types/uuid": "^9.0.7",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0", "@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.42.0", "eslint": "^8.42.0",

View File

@ -30,7 +30,7 @@ export const CONFIG_KEYS = {
interface SystemConfigResponseDto { interface SystemConfigResponseDto {
key: string; key: string;
value: string; value: string;
description?: string; description: string | null;
updatedAt: Date; updatedAt: Date;
} }

View File

@ -7,10 +7,10 @@ export interface SystemConfigEntity {
id: string; id: string;
key: string; key: string;
value: string; value: string;
description?: string; description: string | null;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
updatedBy?: string; updatedBy: string | null;
} }
export interface ISystemConfigRepository { export interface ISystemConfigRepository {

View File

@ -2775,8 +2775,8 @@ export class AuthorizationApplicationService {
// 1. 获取用户认种数据 // 1. 获取用户认种数据
const teamStats = await this.statsRepository.findByAccountSequence(accountSequence) const teamStats = await this.statsRepository.findByAccountSequence(accountSequence)
const hasPlanted = (teamStats?.personalPlantingCount || 0) > 0 const hasPlanted = (teamStats?.selfPlantingCount || 0) > 0
const plantedCount = teamStats?.personalPlantingCount || 0 const plantedCount = teamStats?.selfPlantingCount || 0
// 2. 获取用户已有的授权 // 2. 获取用户已有的授权
const authorizations = await this.authorizationRepository.findByAccountSequence(accountSequence) const authorizations = await this.authorizationRepository.findByAccountSequence(accountSequence)
@ -2812,8 +2812,8 @@ export class AuthorizationApplicationService {
// 1. 验证用户已认种 // 1. 验证用户已认种
const teamStats = await this.statsRepository.findByAccountSequence(command.accountSequence) const teamStats = await this.statsRepository.findByAccountSequence(command.accountSequence)
const personalPlantingCount = teamStats?.personalPlantingCount || 0 const selfPlantingCount = teamStats?.selfPlantingCount || 0
if (personalPlantingCount <= 0) { if (selfPlantingCount <= 0) {
throw new ApplicationError('申请授权需要先完成认种') throw new ApplicationError('申请授权需要先完成认种')
} }
@ -2891,7 +2891,7 @@ export class AuthorizationApplicationService {
authorization.clearDomainEvents() authorization.clearDomainEvents()
return { return {
applicationId: authorization.id, applicationId: authorization.authorizationId.value,
status: 'APPROVED', status: 'APPROVED',
type: SelfApplyAuthorizationType.COMMUNITY, type: SelfApplyAuthorizationType.COMMUNITY,
appliedAt: new Date(), appliedAt: new Date(),
@ -2907,20 +2907,19 @@ export class AuthorizationApplicationService {
command: SelfApplyAuthorizationCommand, command: SelfApplyAuthorizationCommand,
): Promise<SelfApplyAuthorizationResponseDto> { ): Promise<SelfApplyAuthorizationResponseDto> {
// 检查是否已有该市的授权市公司 // 检查是否已有该市的授权市公司
const existing = await this.authorizationRepository.findByRegionCodeAndRoleType( const existingList = await this.authorizationRepository.findActiveByRoleTypeAndRegion(
RegionCode.create(command.cityCode!),
RoleType.AUTH_CITY_COMPANY, RoleType.AUTH_CITY_COMPANY,
RegionCode.create(command.cityCode!),
) )
if (existing && existing.status !== AuthorizationStatus.REVOKED) { if (existingList.length > 0) {
throw new ApplicationError('该市已有授权市公司') throw new ApplicationError('该市已有授权市公司')
} }
// 创建授权市公司授权 // 创建授权市公司授权
const userId = UserId.create(command.userId, command.accountSequence) const userId = UserId.create(command.userId, command.accountSequence)
const regionCode = RegionCode.create(command.cityCode!)
const authorization = AuthorizationRole.createAuthCityCompany({ const authorization = AuthorizationRole.createAuthCityCompany({
userId, userId,
regionCode, cityCode: command.cityCode!,
cityName: command.cityName!, cityName: command.cityName!,
}) })
@ -2936,7 +2935,7 @@ export class AuthorizationApplicationService {
authorization.clearDomainEvents() authorization.clearDomainEvents()
return { return {
applicationId: authorization.id, applicationId: authorization.authorizationId.value,
status: 'APPROVED', status: 'APPROVED',
type: SelfApplyAuthorizationType.CITY_TEAM, type: SelfApplyAuthorizationType.CITY_TEAM,
appliedAt: new Date(), appliedAt: new Date(),
@ -2952,20 +2951,19 @@ export class AuthorizationApplicationService {
command: SelfApplyAuthorizationCommand, command: SelfApplyAuthorizationCommand,
): Promise<SelfApplyAuthorizationResponseDto> { ): Promise<SelfApplyAuthorizationResponseDto> {
// 检查是否已有该省的授权省公司 // 检查是否已有该省的授权省公司
const existing = await this.authorizationRepository.findByRegionCodeAndRoleType( const existingList = await this.authorizationRepository.findActiveByRoleTypeAndRegion(
RegionCode.create(command.provinceCode!),
RoleType.AUTH_PROVINCE_COMPANY, RoleType.AUTH_PROVINCE_COMPANY,
RegionCode.create(command.provinceCode!),
) )
if (existing && existing.status !== AuthorizationStatus.REVOKED) { if (existingList.length > 0) {
throw new ApplicationError('该省已有授权省公司') throw new ApplicationError('该省已有授权省公司')
} }
// 创建授权省公司授权 // 创建授权省公司授权
const userId = UserId.create(command.userId, command.accountSequence) const userId = UserId.create(command.userId, command.accountSequence)
const regionCode = RegionCode.create(command.provinceCode!)
const authorization = AuthorizationRole.createAuthProvinceCompany({ const authorization = AuthorizationRole.createAuthProvinceCompany({
userId, userId,
regionCode, provinceCode: command.provinceCode!,
provinceName: command.provinceName!, provinceName: command.provinceName!,
}) })
@ -2981,7 +2979,7 @@ export class AuthorizationApplicationService {
authorization.clearDomainEvents() authorization.clearDomainEvents()
return { return {
applicationId: authorization.id, applicationId: authorization.authorizationId.value,
status: 'APPROVED', status: 'APPROVED',
type: SelfApplyAuthorizationType.PROVINCE_TEAM, type: SelfApplyAuthorizationType.PROVINCE_TEAM,
appliedAt: new Date(), appliedAt: new Date(),

View File

@ -7,12 +7,16 @@ import { AccountSequence, ReferralCode, UserId, AccountStatus, KYCStatus, Device
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { ValidateReferralCodeQuery, GetReferralStatsQuery, GenerateReferralLinkCommand } from '@/application/commands'; import { ValidateReferralCodeQuery, GetReferralStatsQuery, GenerateReferralLinkCommand } from '@/application/commands';
import { ApplicationError } from '@/shared/exceptions/domain.exception'; import { ApplicationError } from '@/shared/exceptions/domain.exception';
import { AccountSequenceGeneratorService, UserValidatorService, WalletGeneratorService } from '@/domain/services'; import { AccountSequenceGeneratorService, UserValidatorService } from '@/domain/services';
import { TokenService } from './token.service'; import { TokenService } from './token.service';
import { RedisService } from '@/infrastructure/redis/redis.service'; import { RedisService } from '@/infrastructure/redis/redis.service';
import { SmsService } from '@/infrastructure/external/sms/sms.service'; import { SmsService } from '@/infrastructure/external/sms/sms.service';
import { EventPublisherService } from '@/infrastructure/kafka/event-publisher.service'; import { EventPublisherService } from '@/infrastructure/kafka/event-publisher.service';
import { MpcWalletService } from '@/infrastructure/external/mpc'; import { MpcWalletService } from '@/infrastructure/external/mpc';
import { BlockchainClientService } from '@/infrastructure/external/blockchain/blockchain-client.service';
import { PrismaService } from '@/infrastructure/persistence/prisma/prisma.service';
import { BlockchainWalletHandler } from '@/application/event-handlers/blockchain-wallet.handler';
import { MpcKeygenCompletedHandler } from '@/application/event-handlers/mpc-keygen-completed.handler';
describe('UserApplicationService - Referral APIs', () => { describe('UserApplicationService - Referral APIs', () => {
let service: UserApplicationService; let service: UserApplicationService;
@ -21,12 +25,12 @@ describe('UserApplicationService - Referral APIs', () => {
// Helper function to create a test account using UserAccount.reconstruct // Helper function to create a test account using UserAccount.reconstruct
const createMockAccount = (params: { const createMockAccount = (params: {
userId?: string; userId?: string;
accountSequence?: number; accountSequence?: string;
referralCode?: string; referralCode?: string;
nickname?: string; nickname?: string;
avatarUrl?: string | null; avatarUrl?: string | null;
isActive?: boolean; isActive?: boolean;
inviterSequence?: number | null; inviterSequence?: string | null;
registeredAt?: Date; registeredAt?: Date;
} = {}): UserAccount => { } = {}): UserAccount => {
const devices = [ const devices = [
@ -35,7 +39,7 @@ describe('UserApplicationService - Referral APIs', () => {
return UserAccount.reconstruct({ return UserAccount.reconstruct({
userId: params.userId || '123456789', userId: params.userId || '123456789',
accountSequence: params.accountSequence || 1, accountSequence: params.accountSequence || 'D2412190001',
devices, devices,
phoneNumber: '13800138000', phoneNumber: '13800138000',
nickname: params.nickname || '用户1', nickname: params.nickname || '用户1',
@ -90,15 +94,15 @@ describe('UserApplicationService - Referral APIs', () => {
}; };
const mockAccountSequenceGeneratorService = { const mockAccountSequenceGeneratorService = {
getNext: jest.fn().mockResolvedValue(AccountSequence.create(1)), getNext: jest.fn().mockResolvedValue(AccountSequence.create('D2412190001')),
}; };
const mockUserValidatorService = { const mockUserValidatorService = {
validateUniquePhone: jest.fn(), validateUniquePhone: jest.fn(),
}; };
const mockWalletGeneratorService = { const mockBlockchainClientService = {
generateWallets: jest.fn(), getBalance: jest.fn(),
}; };
const mockTokenService = { const mockTokenService = {
@ -127,6 +131,18 @@ describe('UserApplicationService - Referral APIs', () => {
generateMpcWallet: jest.fn(), generateMpcWallet: jest.fn(),
}; };
const mockPrismaService = {
userAccount: { findUnique: jest.fn() },
};
const mockBlockchainWalletHandler = {
handle: jest.fn(),
};
const mockMpcKeygenCompletedHandler = {
handle: jest.fn(),
};
const module: TestingModule = await Test.createTestingModule({ const module: TestingModule = await Test.createTestingModule({
providers: [ providers: [
UserApplicationService, UserApplicationService,
@ -151,8 +167,8 @@ describe('UserApplicationService - Referral APIs', () => {
useValue: mockUserValidatorService, useValue: mockUserValidatorService,
}, },
{ {
provide: WalletGeneratorService, provide: BlockchainClientService,
useValue: mockWalletGeneratorService, useValue: mockBlockchainClientService,
}, },
{ {
provide: TokenService, provide: TokenService,
@ -174,6 +190,18 @@ describe('UserApplicationService - Referral APIs', () => {
provide: MpcWalletService, provide: MpcWalletService,
useValue: mockMpcWalletService, useValue: mockMpcWalletService,
}, },
{
provide: PrismaService,
useValue: mockPrismaService,
},
{
provide: BlockchainWalletHandler,
useValue: mockBlockchainWalletHandler,
},
{
provide: MpcKeygenCompletedHandler,
useValue: mockMpcKeygenCompletedHandler,
},
], ],
}).compile(); }).compile();
@ -189,7 +217,7 @@ describe('UserApplicationService - Referral APIs', () => {
it('should return current user info with referral code and link', async () => { it('should return current user info with referral code and link', async () => {
const mockAccount = createMockAccount({ const mockAccount = createMockAccount({
userId: '123456789', userId: '123456789',
accountSequence: 1, accountSequence: 'D2412190001',
nickname: '测试用户', nickname: '测试用户',
referralCode: 'ABC123', referralCode: 'ABC123',
}); });
@ -200,7 +228,7 @@ describe('UserApplicationService - Referral APIs', () => {
expect(result).toEqual({ expect(result).toEqual({
userId: '123456789', userId: '123456789',
accountSequence: 1, accountSequence: 'D2412190001',
phoneNumber: '138****8000', // masked phoneNumber: '138****8000', // masked
nickname: '测试用户', nickname: '测试用户',
avatarUrl: null, avatarUrl: null,
@ -228,7 +256,7 @@ describe('UserApplicationService - Referral APIs', () => {
describe('validateReferralCode', () => { describe('validateReferralCode', () => {
it('should return valid=true for existing active referral code', async () => { it('should return valid=true for existing active referral code', async () => {
const mockInviter = createMockAccount({ const mockInviter = createMockAccount({
accountSequence: 100, accountSequence: 'D2412190100',
nickname: '邀请人', nickname: '邀请人',
avatarUrl: 'https://example.com/avatar.jpg', avatarUrl: 'https://example.com/avatar.jpg',
referralCode: 'INVTE1', referralCode: 'INVTE1',
@ -245,7 +273,7 @@ describe('UserApplicationService - Referral APIs', () => {
valid: true, valid: true,
referralCode: 'INVTE1', referralCode: 'INVTE1',
inviterInfo: { inviterInfo: {
accountSequence: 100, accountSequence: 'D2412190100',
nickname: '邀请人', nickname: '邀请人',
avatarUrl: 'https://example.com/avatar.jpg', avatarUrl: 'https://example.com/avatar.jpg',
}, },
@ -406,33 +434,33 @@ describe('UserApplicationService - Referral APIs', () => {
it('should return referral stats with direct and indirect invites', async () => { it('should return referral stats with direct and indirect invites', async () => {
const mockAccount = createMockAccount({ const mockAccount = createMockAccount({
userId: '123456789', userId: '123456789',
accountSequence: 1, accountSequence: 'D2412190001',
referralCode: 'ABC123', referralCode: 'ABC123',
}); });
// Direct invites (invited by user 1) // Direct invites (invited by user 1)
const directInvite1 = createMockAccount({ const directInvite1 = createMockAccount({
userId: '200000001', userId: '200000001',
accountSequence: 2, accountSequence: 'D2412190002',
nickname: '直接邀请1', nickname: '直接邀请1',
inviterSequence: 1, inviterSequence: 'D2412190001',
registeredAt: new Date(), registeredAt: new Date(),
}); });
const directInvite2 = createMockAccount({ const directInvite2 = createMockAccount({
userId: '200000002', userId: '200000002',
accountSequence: 3, accountSequence: 'D2412190003',
nickname: '直接邀请2', nickname: '直接邀请2',
inviterSequence: 1, inviterSequence: 'D2412190001',
registeredAt: new Date(), registeredAt: new Date(),
}); });
// Indirect invite (invited by user 2, who was invited by user 1) // Indirect invite (invited by user 2, who was invited by user 1)
const indirectInvite1 = createMockAccount({ const indirectInvite1 = createMockAccount({
userId: '300000001', userId: '300000001',
accountSequence: 4, accountSequence: 'D2412190004',
nickname: '间接邀请1', nickname: '间接邀请1',
inviterSequence: 2, inviterSequence: 'D2412190002',
registeredAt: new Date(), registeredAt: new Date(),
}); });
@ -456,7 +484,7 @@ describe('UserApplicationService - Referral APIs', () => {
thisMonthInvites: expect.any(Number), thisMonthInvites: expect.any(Number),
recentInvites: expect.arrayContaining([ recentInvites: expect.arrayContaining([
expect.objectContaining({ expect.objectContaining({
accountSequence: expect.any(Number), accountSequence: expect.any(String),
nickname: expect.any(String), nickname: expect.any(String),
level: expect.any(Number), // 1 for direct, 2 for indirect level: expect.any(Number), // 1 for direct, 2 for indirect
}), }),
@ -469,7 +497,7 @@ describe('UserApplicationService - Referral APIs', () => {
it('should return empty stats when no invites', async () => { it('should return empty stats when no invites', async () => {
const mockAccount = createMockAccount({ const mockAccount = createMockAccount({
userId: '123456789', userId: '123456789',
accountSequence: 1, accountSequence: 'D2412190001',
referralCode: 'ABC123', referralCode: 'ABC123',
}); });
@ -495,29 +523,29 @@ describe('UserApplicationService - Referral APIs', () => {
it('should correctly calculate time-based stats', async () => { it('should correctly calculate time-based stats', async () => {
const mockAccount = createMockAccount({ const mockAccount = createMockAccount({
userId: '123456789', userId: '123456789',
accountSequence: 1, accountSequence: 'D2412190001',
referralCode: 'ABC123', referralCode: 'ABC123',
}); });
const now = new Date(); const now = new Date();
const todayInvite = createMockAccount({ const todayInvite = createMockAccount({
accountSequence: 2, accountSequence: 'D2412190002',
nickname: '今日邀请', nickname: '今日邀请',
inviterSequence: 1, inviterSequence: 'D2412190001',
registeredAt: now, registeredAt: now,
}); });
const yesterdayInvite = createMockAccount({ const yesterdayInvite = createMockAccount({
accountSequence: 3, accountSequence: 'D2412190003',
nickname: '昨日邀请', nickname: '昨日邀请',
inviterSequence: 1, inviterSequence: 'D2412190001',
registeredAt: new Date(now.getTime() - 24 * 60 * 60 * 1000), // yesterday registeredAt: new Date(now.getTime() - 24 * 60 * 60 * 1000), // yesterday
}); });
const lastMonthInvite = createMockAccount({ const lastMonthInvite = createMockAccount({
accountSequence: 4, accountSequence: 'D2412190004',
nickname: '上月邀请', nickname: '上月邀请',
inviterSequence: 1, inviterSequence: 'D2412190001',
registeredAt: new Date(now.getFullYear(), now.getMonth() - 1, 15), registeredAt: new Date(now.getFullYear(), now.getMonth() - 1, 15),
}); });
@ -546,22 +574,22 @@ describe('UserApplicationService - Referral APIs', () => {
it('should sort recent invites by registration date (newest first)', async () => { it('should sort recent invites by registration date (newest first)', async () => {
const mockAccount = createMockAccount({ const mockAccount = createMockAccount({
userId: '123456789', userId: '123456789',
accountSequence: 1, accountSequence: 'D2412190001',
referralCode: 'ABC123', referralCode: 'ABC123',
}); });
const now = new Date(); const now = new Date();
const oldInvite = createMockAccount({ const oldInvite = createMockAccount({
accountSequence: 2, accountSequence: 'D2412190002',
nickname: '旧邀请', nickname: '旧邀请',
inviterSequence: 1, inviterSequence: 'D2412190001',
registeredAt: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000), // 7 days ago registeredAt: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000), // 7 days ago
}); });
const newInvite = createMockAccount({ const newInvite = createMockAccount({
accountSequence: 3, accountSequence: 'D2412190003',
nickname: '新邀请', nickname: '新邀请',
inviterSequence: 1, inviterSequence: 'D2412190001',
registeredAt: now, registeredAt: now,
}); });

View File

@ -65,10 +65,17 @@ describe('Identity Service E2E Tests', () => {
// 初始化账户序列号生成器 // 初始化账户序列号生成器
await prisma.accountSequenceGenerator.deleteMany(); await prisma.accountSequenceGenerator.deleteMany();
const today = new Date();
const year = String(today.getFullYear()).slice(-2);
const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0');
const dateKey = `${year}${month}${day}`;
await prisma.accountSequenceGenerator.create({ await prisma.accountSequenceGenerator.create({
data: { data: {
id: 1, id: 1,
currentSequence: BigInt(100000), dateKey: dateKey,
currentSequence: 0,
}, },
}); });
}); });

View File

@ -4,6 +4,7 @@ import type { User } from '@/types/user.types';
interface AuthState { interface AuthState {
user: User | null; user: User | null;
token: string | null; token: string | null;
refreshToken: string | null;
isAuthenticated: boolean; isAuthenticated: boolean;
permissions: string[]; permissions: string[];
loading: boolean; loading: boolean;
@ -12,6 +13,7 @@ interface AuthState {
const initialState: AuthState = { const initialState: AuthState = {
user: null, user: null,
token: null, token: null,
refreshToken: null,
isAuthenticated: false, isAuthenticated: false,
permissions: [], permissions: [],
loading: true, loading: true,
@ -23,10 +25,11 @@ const authSlice = createSlice({
reducers: { reducers: {
setCredentials: ( setCredentials: (
state, state,
action: PayloadAction<{ user: User; token: string; permissions?: string[] }> action: PayloadAction<{ user: User; token: string; refreshToken?: string; permissions?: string[] }>
) => { ) => {
state.user = action.payload.user; state.user = action.payload.user;
state.token = action.payload.token; state.token = action.payload.token;
state.refreshToken = action.payload.refreshToken || null;
state.permissions = action.payload.permissions || []; state.permissions = action.payload.permissions || [];
state.isAuthenticated = true; state.isAuthenticated = true;
state.loading = false; state.loading = false;
@ -34,6 +37,7 @@ const authSlice = createSlice({
logout: (state) => { logout: (state) => {
state.user = null; state.user = null;
state.token = null; state.token = null;
state.refreshToken = null;
state.permissions = []; state.permissions = [];
state.isAuthenticated = false; state.isAuthenticated = false;
state.loading = false; state.loading = false;