refactor(tbank): centralize access rules

This commit is contained in:
2026-08-25 12:06:41 +03:00
parent 5375e5598a
commit 130b303ec1
18 changed files with 573 additions and 327 deletions
+59
View File
@@ -0,0 +1,59 @@
import {
ConflictException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { BrokerageAccountDto } from './brokerage-account.dto';
import {
accessibleTbankAccount,
supportedTbankAccounts,
} from './tbank-account-policy';
import { TbankClient, TbankAccount } from './tbank.client';
import { TbankTokenService } from './tbank-token.service';
export type TbankAccountContext = {
token: string;
account: TbankAccount;
};
@Injectable()
export class TbankAccessService {
constructor(
private readonly prisma: PrismaService,
private readonly tokens: TbankTokenService,
private readonly tbank: TbankClient,
) {}
async listSupportedAccounts(userId: string): Promise<BrokerageAccountDto[]> {
const { token } = await this.connection(userId);
return this.tokens.translateInvalidToken(async () =>
supportedTbankAccounts(await this.tbank.getOpenAccounts(token)),
);
}
async withAccount<T>(
userId: string,
accountId: string,
handler: (context: TbankAccountContext) => Promise<T>,
): Promise<T> {
const { token } = await this.connection(userId);
return this.tokens.translateInvalidToken(async () => {
const account = accessibleTbankAccount(
await this.tbank.getOpenAccounts(token),
accountId,
);
if (!account) throw new NotFoundException();
return handler({ token, account });
});
}
private async connection(userId: string): Promise<{ token: string }> {
const connection = await this.prisma.tbankConnection.findUnique({
where: { userId },
});
if (!connection)
throw new ConflictException({ code: 'TBANK_NOT_CONNECTED' });
return { token: this.tokens.decrypt(connection.encryptedToken) };
}
}