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

233 lines
5.5 KiB

import { ConfigurationService } from '@ghostfolio/api/services/configuration.service';
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
import { locale } from '@ghostfolio/common/config';
import { resetHours } from '@ghostfolio/common/helper';
import { User as IUser, UserWithSettings } from '@ghostfolio/common/interfaces';
import { getPermissions, permissions } from '@ghostfolio/common/permissions';
4 years ago
import { Injectable } from '@nestjs/common';
import { Currency, Prisma, Provider, User, ViewMode } from '@prisma/client';
4 years ago
import { add } from 'date-fns';
const crypto = require('crypto');
@Injectable()
export class UserService {
public static DEFAULT_CURRENCY = Currency.USD;
public constructor(
private readonly configurationService: ConfigurationService,
private prisma: PrismaService
) {}
4 years ago
public async getUser({
Account,
4 years ago
alias,
id,
role,
Settings
}: UserWithSettings): Promise<IUser> {
const access = await this.prisma.access.findMany({
include: {
User: true
},
orderBy: { User: { alias: 'asc' } },
where: { GranteeUser: { id } }
});
const currentPermissions = getPermissions(role);
if (this.configurationService.get('ENABLE_FEATURE_FEAR_AND_GREED_INDEX')) {
currentPermissions.push(permissions.accessFearAndGreedIndex);
}
4 years ago
return {
alias,
id,
access: access.map((accessItem) => {
return {
alias: accessItem.User.alias,
id: accessItem.id
};
}),
accounts: Account,
permissions: currentPermissions,
4 years ago
settings: {
locale,
baseCurrency: Settings?.currency ?? UserService.DEFAULT_CURRENCY,
viewMode: Settings.viewMode ?? ViewMode.DEFAULT
4 years ago
},
subscription: {
expiresAt: resetHours(add(new Date(), { days: 7 })),
type: 'Trial'
4 years ago
}
};
}
public async user(
userWhereUniqueInput: Prisma.UserWhereUniqueInput
): Promise<UserWithSettings | null> {
const user = await this.prisma.user.findUnique({
include: { Account: true, Settings: true },
4 years ago
where: userWhereUniqueInput
});
if (user?.Settings) {
if (!user.Settings.currency) {
// Set default currency if needed
user.Settings.currency = UserService.DEFAULT_CURRENCY;
}
} else if (user) {
// Set default settings if needed
user.Settings = {
currency: UserService.DEFAULT_CURRENCY,
updatedAt: new Date(),
userId: user?.id,
viewMode: ViewMode.DEFAULT
4 years ago
};
}
return user;
}
public async users(params: {
skip?: number;
take?: number;
cursor?: Prisma.UserWhereUniqueInput;
where?: Prisma.UserWhereInput;
orderBy?: Prisma.UserOrderByInput;
}): Promise<User[]> {
const { skip, take, cursor, where, orderBy } = params;
return this.prisma.user.findMany({
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.prisma.user.create({
data: {
...data,
Account: {
create: {
isDefault: true,
name: 'Default Account'
}
}
}
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.prisma.user.update({
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.prisma.user.update({
data,
where
});
}
public async deleteUser(where: Prisma.UserWhereUniqueInput): Promise<User> {
await this.prisma.access.deleteMany({
where: { OR: [{ granteeUserId: where.id }, { userId: where.id }] }
});
await this.prisma.account.deleteMany({
where: { userId: where.id }
});
await this.prisma.analytics.delete({
where: { userId: where.id }
});
await this.prisma.order.deleteMany({
where: { userId: where.id }
});
try {
await this.prisma.settings.delete({
where: { userId: where.id }
});
} catch {}
4 years ago
return this.prisma.user.delete({
where
});
}
public async updateUserSettings({
currency,
userId,
viewMode
4 years ago
}: {
currency?: Currency;
4 years ago
userId: string;
viewMode?: ViewMode;
4 years ago
}) {
await this.prisma.settings.upsert({
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
}