You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ghostfolio/apps/api/src/app/user/user.service.ts

289 lines
7.2 KiB

import { SubscriptionService } from '@ghostfolio/api/app/subscription/subscription.service';
import { ConfigurationService } from '@ghostfolio/api/services/configuration.service';
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
import { baseCurrency, locale } from '@ghostfolio/common/config';
import { User as IUser, UserWithSettings } from '@ghostfolio/common/interfaces';
import { getPermissions, permissions } from '@ghostfolio/common/permissions';
import { SubscriptionType } from '@ghostfolio/common/types/subscription.type';
4 years ago
import { Injectable } from '@nestjs/common';
import { Prisma, Provider, User, ViewMode } from '@prisma/client';
import { UserSettingsParams } from './interfaces/user-settings-params.interface';
import { UserSettings } from './interfaces/user-settings.interface';
4 years ago
const crypto = require('crypto');
@Injectable()
export class UserService {
public static DEFAULT_CURRENCY = 'USD';
4 years ago
public constructor(
private readonly configurationService: ConfigurationService,
private readonly prismaService: PrismaService,
private readonly subscriptionService: SubscriptionService
) {}
4 years ago
public async getUser({
Account,
4 years ago
alias,
id,
permissions,
Settings,
subscription
4 years ago
}: UserWithSettings): Promise<IUser> {
const access = await this.prismaService.access.findMany({
4 years ago
include: {
User: true
},
orderBy: { User: { alias: 'asc' } },
where: { GranteeUser: { id } }
});
return {
alias,
id,
permissions,
subscription,
4 years ago
access: access.map((accessItem) => {
return {
alias: accessItem.User.alias,
id: accessItem.id
};
}),
accounts: Account,
4 years ago
settings: {
...(<UserSettings>Settings.settings),
locale,
baseCurrency: Settings?.currency ?? UserService.DEFAULT_CURRENCY,
viewMode: Settings?.viewMode ?? ViewMode.DEFAULT
4 years ago
}
};
}
public isRestrictedView(aUser: UserWithSettings) {
return (aUser.Settings.settings as UserSettings)?.isRestrictedView ?? false;
}
4 years ago
public async user(
userWhereUniqueInput: Prisma.UserWhereUniqueInput
): Promise<UserWithSettings | null> {
const userFromDatabase = await this.prismaService.user.findUnique({
include: { Account: true, Settings: true, Subscription: true },
4 years ago
where: userWhereUniqueInput
});
const user: UserWithSettings = userFromDatabase;
const currentPermissions = getPermissions(userFromDatabase.role);
if (this.configurationService.get('ENABLE_FEATURE_FEAR_AND_GREED_INDEX')) {
currentPermissions.push(permissions.accessFearAndGreedIndex);
}
user.permissions = currentPermissions;
if (userFromDatabase?.Settings) {
if (!userFromDatabase.Settings.currency) {
4 years ago
// Set default currency if needed
userFromDatabase.Settings.currency = UserService.DEFAULT_CURRENCY;
4 years ago
}
} else if (userFromDatabase) {
4 years ago
// Set default settings if needed
userFromDatabase.Settings = {
4 years ago
currency: UserService.DEFAULT_CURRENCY,
settings: null,
4 years ago
updatedAt: new Date(),
userId: userFromDatabase?.id,
viewMode: ViewMode.DEFAULT
4 years ago
};
}
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) {
user.subscription = this.subscriptionService.getSubscription(
userFromDatabase?.Subscription
);
if (user.subscription.type === SubscriptionType.Basic) {
user.permissions = user.permissions.filter((permission) => {
return permission !== permissions.updateViewMode;
});
user.Settings.viewMode = ViewMode.ZEN;
}
}
4 years ago
return user;
}
public async users(params: {
skip?: number;
take?: number;
cursor?: Prisma.UserWhereUniqueInput;
where?: Prisma.UserWhereInput;
orderBy?: Prisma.UserOrderByWithRelationInput;
4 years ago
}): Promise<User[]> {
const { skip, take, cursor, where, orderBy } = params;
return this.prismaService.user.findMany({
4 years ago
skip,
take,
cursor,
where,
orderBy
});
}
public createAccessToken(password: string, salt: string): string {
const hash = crypto.createHmac('sha512', salt);
hash.update(password);
return hash.digest('hex');
}
public async createUser(data?: Prisma.UserCreateInput): Promise<User> {
let user = await this.prismaService.user.create({
data: {
...data,
Account: {
create: {
currency: baseCurrency,
isDefault: true,
name: 'Default Account'
}
},
Settings: {
create: {
currency: baseCurrency
}
}
}
4 years ago
});
if (data.provider === Provider.ANONYMOUS) {
const accessToken = this.createAccessToken(
user.id,
this.getRandomString(10)
);
const hashedAccessToken = this.createAccessToken(
accessToken,
process.env.ACCESS_TOKEN_SALT
);
user = await this.prismaService.user.update({
4 years ago
data: { accessToken: hashedAccessToken },
where: { id: user.id }
});
return { ...user, accessToken };
}
return user;
}
public async updateUser(params: {
where: Prisma.UserWhereUniqueInput;
data: Prisma.UserUpdateInput;
}): Promise<User> {
const { where, data } = params;
return this.prismaService.user.update({
4 years ago
data,
where
});
}
public async deleteUser(where: Prisma.UserWhereUniqueInput): Promise<User> {
await this.prismaService.access.deleteMany({
where: { OR: [{ granteeUserId: where.id }, { userId: where.id }] }
});
await this.prismaService.account.deleteMany({
where: { userId: where.id }
});
await this.prismaService.analytics.delete({
where: { userId: where.id }
});
await this.prismaService.order.deleteMany({
where: { userId: where.id }
});
try {
await this.prismaService.settings.delete({
where: { userId: where.id }
});
} catch {}
return this.prismaService.user.delete({
4 years ago
where
});
}
public async updateUserSetting({
userId,
userSettings
}: {
userId: string;
userSettings: UserSettings;
}) {
const settings = userSettings as Prisma.JsonObject;
await this.prismaService.settings.upsert({
create: {
settings,
User: {
connect: {
id: userId
}
}
},
update: {
settings
},
where: {
userId: userId
}
});
return;
}
4 years ago
public async updateUserSettings({
currency,
userId,
viewMode
}: UserSettingsParams) {
await this.prismaService.settings.upsert({
4 years ago
create: {
currency,
User: {
connect: {
id: userId
}
},
viewMode
4 years ago
},
update: {
currency,
viewMode
4 years ago
},
where: {
userId: userId
}
});
return;
}
private getRandomString(length: number) {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const result = [];
for (let i = 0; i < length; i++) {
result.push(
characters.charAt(Math.floor(Math.random() * characters.length))
);
}
return result.join('');
}
4 years ago
}