MAJOR UPPDATE: "First Ai"

feat: add AI categorization for products and enhance user management

- Integrated AI service for category suggestions in receipt import and product management.
- Added premium subscription feature for users with corresponding API endpoints.
- Implemented admin interface for managing pending product suggestions.
- Enhanced user management to include premium status and corresponding UI updates.
- Updated database schema to support new fields for premium status and product status.
This commit is contained in:
Nils-Johan Gynther
2026-04-19 10:34:21 +02:00
parent 0286ab0991
commit 054a19ed7c
30 changed files with 917 additions and 77 deletions
+5 -4
View File
@@ -27,7 +27,7 @@ export class AuthService {
passwordHash,
});
return this.issueToken(user.id, user.username, user.role);
return this.issueToken(user.id, user.username, user.role, user.isPremium);
}
async login(dto: LoginDto) {
@@ -37,16 +37,17 @@ export class AuthService {
const valid = await bcrypt.compare(dto.password, user.passwordHash);
if (!valid) throw new UnauthorizedException('Felaktigt användarnamn eller lösenord');
return this.issueToken(user.id, user.username, user.role);
return this.issueToken(user.id, user.username, user.role, user.isPremium);
}
private issueToken(userId: number, username: string, role: string) {
const payload = { sub: userId, username, role };
private issueToken(userId: number, username: string, role: string, isPremium: boolean) {
const payload = { sub: userId, username, role, isPremium };
return {
accessToken: this.jwtService.sign(payload),
userId,
username,
role,
isPremium,
};
}
}
+2 -2
View File
@@ -12,7 +12,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
});
}
async validate(payload: { sub: number; username: string; role: string }) {
return { userId: payload.sub, username: payload.username, role: payload.role ?? 'user' };
async validate(payload: { sub: number; username: string; role: string; isPremium: boolean }) {
return { userId: payload.sub, username: payload.username, role: payload.role ?? 'user', isPremium: payload.isPremium ?? false };
}
}