From cc6320acfd97e57dcb1e3a11a04a934618e5b1f8 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 4 Mar 2023 10:16:16 +0100 Subject: [PATCH] Feature/simplify database seeding (#1763) * Simplify database seeding * Update documentation * Update changelog --- CHANGELOG.md | 4 + README.md | 12 +- apps/api/src/app/info/info.service.ts | 20 +- .../pages/landing/landing-page.component.ts | 4 +- .../src/app/pages/landing/landing-page.html | 32 +- .../src/app/pages/register/register-page.html | 1 - libs/common/src/lib/config.ts | 3 +- prisma/seed.js | 299 +----------------- 8 files changed, 48 insertions(+), 327 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e1c1dd90..6281aa9fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Changed + +- Simplified the database seeding + ### Fixed - Downgraded `Node.js` from version `18` to `16` (Dockerfile) to resolve `SIGSEGV` (segmentation fault) during the `prisma` database migrations (see https://github.com/prisma/prisma/issues/10649) diff --git a/README.md b/README.md index aebc7129f..37058d6c2 100644 --- a/README.md +++ b/README.md @@ -126,13 +126,10 @@ docker-compose --env-file ./.env -f docker/docker-compose.build.yml build docker-compose --env-file ./.env -f docker/docker-compose.build.yml up -d ``` -#### Fetch Historical Data - -Open http://localhost:3333 in your browser and accomplish these steps: +#### Setup +1. Open http://localhost:3333 in your browser 1. Create a new user via _Get Started_ (this first user will get the role `ADMIN`) -1. Go to the _Market Data_ tab in the _Admin Control Panel_ and click _Gather All Data_ to fetch historical data -1. Click _Sign out_ and check out the _Live Demo_ #### Upgrade Version @@ -159,11 +156,10 @@ Please follow the instructions of the Ghostfolio [Unraid Community App](https:// 1. Run `yarn install` 1. Run `yarn build:dev` to build the source code including the assets 1. Run `docker-compose --env-file ./.env -f docker/docker-compose.dev.yml up -d` to start [PostgreSQL](https://www.postgresql.org) and [Redis](https://redis.io) -1. Run `yarn database:setup` to initialize the database schema and populate your database with (example) data +1. Run `yarn database:setup` to initialize the database schema 1. Start the server and the client (see [_Development_](#Development)) +1. Open http://localhost:4200/en in your browser 1. Create a new user via _Get Started_ (this first user will get the role `ADMIN`) -1. Go to the _Market Data_ tab in the _Admin Control Panel_ and click _Gather All Data_ to fetch historical data -1. Click _Sign out_ and check out the _Live Demo_ ### Start Server diff --git a/apps/api/src/app/info/info.service.ts b/apps/api/src/app/info/info.service.ts index 191c841bd..695920660 100644 --- a/apps/api/src/app/info/info.service.ts +++ b/apps/api/src/app/info/info.service.ts @@ -6,12 +6,12 @@ import { PrismaService } from '@ghostfolio/api/services/prisma.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { TagService } from '@ghostfolio/api/services/tag/tag.service'; import { - DEMO_USER_ID, PROPERTY_COUNTRIES_OF_SUBSCRIBERS, PROPERTY_IS_READ_ONLY_MODE, PROPERTY_SLACK_COMMUNITY_USERS, PROPERTY_STRIPE_CONFIG, PROPERTY_SYSTEM_MESSAGE, + PROPERTY_DEMO_USER_ID, ghostfolioFearAndGreedIndexDataSource } from '@ghostfolio/common/config'; import { @@ -118,7 +118,7 @@ export class InfoService { baseCurrency: this.configurationService.get('BASE_CURRENCY'), benchmarks: await this.benchmarkService.getBenchmarkAssetProfiles(), currencies: this.exchangeRateDataService.getCurrencies(), - demoAuthToken: this.getDemoAuthToken(), + demoAuthToken: await this.getDemoAuthToken(), statistics: await this.getStatistics(), subscriptions: await this.getSubscriptions(), tags: await this.tagService.get() @@ -246,10 +246,18 @@ export class InfoService { )) as string; } - private getDemoAuthToken() { - return this.jwtService.sign({ - id: DEMO_USER_ID - }); + private async getDemoAuthToken() { + const demoUserId = (await this.propertyService.getByKey( + PROPERTY_DEMO_USER_ID + )) as string; + + if (demoUserId) { + return this.jwtService.sign({ + id: demoUserId + }); + } + + return undefined; } private async getStatistics() { diff --git a/apps/client/src/app/pages/landing/landing-page.component.ts b/apps/client/src/app/pages/landing/landing-page.component.ts index e2ad8a592..18f2110ef 100644 --- a/apps/client/src/app/pages/landing/landing-page.component.ts +++ b/apps/client/src/app/pages/landing/landing-page.component.ts @@ -17,8 +17,8 @@ export class LandingPageComponent implements OnDestroy, OnInit { [code: string]: { value: number }; } = {}; public currentYear = format(new Date(), 'yyyy'); - public demoAuthToken: string; public deviceType: string; + public hasPermissionForDemo: boolean; public hasPermissionForStatistics: boolean; public hasPermissionForSubscription: boolean; public hasPermissionToCreateUser: boolean; @@ -54,6 +54,7 @@ export class LandingPageComponent implements OnDestroy, OnInit { ) { const { countriesOfSubscribers = [], + demoAuthToken, globalPermissions, statistics } = this.dataService.fetchInfo(); @@ -64,6 +65,7 @@ export class LandingPageComponent implements OnDestroy, OnInit { }; } + this.hasPermissionForDemo = !!demoAuthToken; this.hasPermissionForStatistics = hasPermission( globalPermissions, permissions.enableStatistics diff --git a/apps/client/src/app/pages/landing/landing-page.html b/apps/client/src/app/pages/landing/landing-page.html index 4ba24f77a..f14aae4ba 100644 --- a/apps/client/src/app/pages/landing/landing-page.html +++ b/apps/client/src/app/pages/landing/landing-page.html @@ -40,12 +40,18 @@ > Get Started -
or
- - - Live Demo - + + +
+ or +
+ + Live Demo + +
@@ -379,16 +385,20 @@

Are you ready?

- Join now or check out the example account + Join now + or check out the example account

Get Started -
or
- - Live Demo - + +
or
+ + Live Demo + +
diff --git a/apps/client/src/app/pages/register/register-page.html b/apps/client/src/app/pages/register/register-page.html index f1fc1a1e1..5147f5bac 100644 --- a/apps/client/src/app/pages/register/register-page.html +++ b/apps/client/src/app/pages/register/register-page.html @@ -21,7 +21,6 @@ class="d-inline-block" color="primary" mat-flat-button - [disabled]="!demoAuthToken" (click)="createAccount()" > Create Account diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts index c7151b89e..3319f9a3b 100644 --- a/libs/common/src/lib/config.ts +++ b/libs/common/src/lib/config.ts @@ -2,8 +2,6 @@ import { DataSource } from '@prisma/client'; import { JobOptions, JobStatus } from 'bull'; import ms from 'ms'; -export const DEMO_USER_ID = '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f'; - export const ghostfolioPrefix = 'GF'; export const ghostfolioScraperApiSymbolPrefix = `_${ghostfolioPrefix}_`; export const ghostfolioCashSymbol = `${ghostfolioScraperApiSymbolPrefix}CASH`; @@ -79,6 +77,7 @@ export const PROPERTY_BENCHMARKS = 'BENCHMARKS'; export const PROPERTY_COUNTRIES_OF_SUBSCRIBERS = 'COUNTRIES_OF_SUBSCRIBERS'; export const PROPERTY_COUPONS = 'COUPONS'; export const PROPERTY_CURRENCIES = 'CURRENCIES'; +export const PROPERTY_DEMO_USER_ID = 'DEMO_USER_ID'; export const PROPERTY_IS_READ_ONLY_MODE = 'IS_READ_ONLY_MODE'; export const PROPERTY_IS_USER_SIGNUP_ENABLED = 'IS_USER_SIGNUP_ENABLED'; export const PROPERTY_SLACK_COMMUNITY_USERS = 'SLACK_COMMUNITY_USERS'; diff --git a/prisma/seed.js b/prisma/seed.js index b94c11316..beafbed44 100644 --- a/prisma/seed.js +++ b/prisma/seed.js @@ -1,293 +1,7 @@ -const { - AccountType, - DataSource, - PrismaClient, - Role, - Type -} = require('@prisma/client'); +const { PrismaClient } = require('@prisma/client'); const prisma = new PrismaClient(); async function main() { - const platformBitcoinSuisse = await prisma.platform.upsert({ - create: { - id: '70b6e475-a2b9-4527-99db-943e4f38ce45', - name: 'Bitcoin Suisse', - url: 'https://www.bitcoinsuisse.com' - }, - update: {}, - where: { id: '70b6e475-a2b9-4527-99db-943e4f38ce45' } - }); - - const platformBitpanda = await prisma.platform.upsert({ - create: { - id: 'debf9110-498f-4811-b972-7ebbd317e730', - name: 'Bitpanda', - url: 'https://www.bitpanda.com' - }, - update: {}, - where: { id: 'debf9110-498f-4811-b972-7ebbd317e730' } - }); - - const platformCoinbase = await prisma.platform.upsert({ - create: { - id: '8dc24b88-bb92-4152-af25-fe6a31643e26', - name: 'Coinbase', - url: 'https://www.coinbase.com' - }, - update: {}, - where: { id: '8dc24b88-bb92-4152-af25-fe6a31643e26' } - }); - - const platformDegiro = await prisma.platform.upsert({ - create: { - id: '94c1a2f4-a666-47be-84cd-4c8952e74c81', - name: 'DEGIRO', - url: 'https://www.degiro.eu' - }, - update: {}, - where: { id: '94c1a2f4-a666-47be-84cd-4c8952e74c81' } - }); - - const platformInteractiveBrokers = await prisma.platform.upsert({ - create: { - id: '9da3a8a7-4795-43e3-a6db-ccb914189737', - name: 'Interactive Brokers', - url: 'https://www.interactivebrokers.com' - }, - update: {}, - where: { id: '9da3a8a7-4795-43e3-a6db-ccb914189737' } - }); - - const platformPostFinance = await prisma.platform.upsert({ - create: { - id: '5377d9df-0d25-42c2-9d9b-e4c63166281e', - name: 'PostFinance', - url: 'https://www.postfinance.ch' - }, - update: {}, - where: { id: '5377d9df-0d25-42c2-9d9b-e4c63166281e' } - }); - - const platformSwissquote = await prisma.platform.upsert({ - create: { - id: '1377d9df-0d25-42c2-9d9b-e4c63156291f', - name: 'Swissquote', - url: 'https://swissquote.com' - }, - update: {}, - where: { id: '1377d9df-0d25-42c2-9d9b-e4c63156291f' } - }); - - const userDemo = await prisma.user.upsert({ - create: { - accessToken: - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjliMTEyYjRkLTNiN2QtNGJhZC05YmRkLTNiMGY3YjRkYWMyZiIsImlhdCI6MTYxODUxMjAxNCwiZXhwIjoxNjIxMTA0MDE0fQ.l3WUxpI0hxuQtdPrD0kd7sem6S2kx_7CrdNvkmlKuWw', - Account: { - create: [ - { - accountType: AccountType.SECURITIES, - balance: 0, - currency: 'USD', - id: 'd804de69-0429-42dc-b6ca-b308fd7dd926', - name: 'Coinbase Account', - platformId: platformCoinbase.id - }, - { - accountType: AccountType.SECURITIES, - balance: 0, - currency: 'EUR', - id: '65cfb79d-b6c7-4591-9d46-73426bc62094', - name: 'DEGIRO Account', - platformId: platformDegiro.id - }, - { - accountType: AccountType.SECURITIES, - balance: 0, - currency: 'USD', - id: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c', - isDefault: true, - name: 'Interactive Brokers Account', - platformId: platformInteractiveBrokers.id - } - ] - }, - id: '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f', - role: Role.DEMO - }, - update: {}, - where: { id: '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f' } - }); - - await prisma.symbolProfile.createMany({ - data: [ - { - assetClass: 'EQUITY', - assetSubClass: 'STOCK', - countries: [{ code: 'US', weight: 1 }], - currency: 'USD', - dataSource: DataSource.YAHOO, - id: '2bd26362-136e-411c-b578-334084b4cdcc', - name: 'Amazon.com Inc.', - sectors: [{ name: 'Consumer Cyclical', weight: 1 }], - symbol: 'AMZN' - }, - { - assetClass: 'CASH', - assetSubClass: 'CRYPTOCURRENCY', - countries: undefined, - currency: 'USD', - dataSource: DataSource.YAHOO, - id: 'fdc42ea6-1321-44f5-9fb0-d7f1f2cf9b1e', - name: 'Bitcoin USD', - sectors: undefined, - symbol: 'BTCUSD' - }, - { - assetClass: 'EQUITY', - assetSubClass: 'STOCK', - countries: [{ code: 'US', weight: 1 }], - currency: 'USD', - dataSource: DataSource.YAHOO, - id: 'd1ee9681-fb21-4f99-a3b7-afd4fc04df2e', - name: 'Tesla Inc.', - sectors: [{ name: 'Consumer Cyclical', weight: 1 }], - symbol: 'TSLA' - }, - { - assetClass: 'EQUITY', - assetSubClass: 'ETF', - countries: [ - { code: 'US', weight: 0.9886789999999981 }, - { code: 'NL', weight: 0.000203 }, - { code: 'CA', weight: 0.000362 } - ], - currency: 'USD', - dataSource: DataSource.YAHOO, - id: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', - name: 'Vanguard Total Stock Market Index Fund ETF', - sectors: [ - { name: 'Technology', weight: 0.31393799999999955 }, - { name: 'Consumer Cyclical', weight: 0.149224 }, - { name: 'Financials', weight: 0.11716100000000002 }, - { name: 'Healthcare', weight: 0.13285199999999994 }, - { name: 'Consumer Staples', weight: 0.053919000000000016 }, - { name: 'Energy', weight: 0.025529999999999997 }, - { name: 'Telecommunications', weight: 0.012579 }, - { name: 'Industrials', weight: 0.09526399999999995 }, - { name: 'Utilities', weight: 0.024791999999999988 }, - { name: 'Materials', weight: 0.027664 }, - { name: 'Real Estate', weight: 0.03239999999999998 }, - { name: 'Communication', weight: 0.0036139999999999996 }, - { name: 'Other', weight: 0.000218 } - ], - symbol: 'VTI' - } - ], - skipDuplicates: true - }); - - await prisma.order.createMany({ - data: [ - { - accountId: '65cfb79d-b6c7-4591-9d46-73426bc62094', - accountUserId: userDemo.id, - date: new Date(Date.UTC(2017, 0, 3, 0, 0, 0)), - fee: 30, - id: 'cf7c0418-8535-4089-ae3d-5dbfa0aec2e1', - quantity: 50, - symbolProfileId: 'd1ee9681-fb21-4f99-a3b7-afd4fc04df2e', // TSLA - type: Type.BUY, - unitPrice: 42.97, - userId: userDemo.id - }, - { - accountId: 'd804de69-0429-42dc-b6ca-b308fd7dd926', - accountUserId: userDemo.id, - date: new Date(Date.UTC(2017, 7, 16, 0, 0, 0)), - fee: 29.9, - id: 'a1c5d73a-8631-44e5-ac44-356827a5212c', - quantity: 0.5614682, - symbolProfileId: 'fdc42ea6-1321-44f5-9fb0-d7f1f2cf9b1e', // BTCUSD - type: Type.BUY, - unitPrice: 3562.089535970158, - userId: userDemo.id - }, - { - accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c', - accountUserId: userDemo.id, - date: new Date(Date.UTC(2018, 9, 1, 0, 0, 0)), - fee: 80.79, - id: '71c08e2a-4a86-44ae-a890-c337de5d5f9b', - quantity: 5, - symbolProfileId: '2bd26362-136e-411c-b578-334084b4cdcc', // AMZN - type: Type.BUY, - unitPrice: 2021.99, - userId: userDemo.id - }, - { - accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c', - accountUserId: userDemo.id, - date: new Date(Date.UTC(2019, 2, 1, 0, 0, 0)), - fee: 19.9, - id: '385f2c2c-d53e-4937-b0e5-e92ef6020d4e', - quantity: 10, - symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI - type: Type.BUY, - unitPrice: 144.38, - userId: userDemo.id - }, - { - accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c', - accountUserId: userDemo.id, - date: new Date(Date.UTC(2019, 8, 3, 0, 0, 0)), - fee: 19.9, - id: '185f2c2c-d53e-4937-b0e5-a93ef6020d4e', - quantity: 10, - symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI - type: Type.BUY, - unitPrice: 147.99, - userId: userDemo.id - }, - { - accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c', - accountUserId: userDemo.id, - date: new Date(Date.UTC(2020, 2, 2, 0, 0, 0)), - fee: 19.9, - id: '347b0430-a84f-4031-a0f9-390399066ad6', - quantity: 10, - symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI - type: Type.BUY, - unitPrice: 151.41, - userId: userDemo.id - }, - { - accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c', - accountUserId: userDemo.id, - date: new Date(Date.UTC(2020, 8, 1, 0, 0, 0)), - fee: 19.9, - id: '67ec3f47-3189-4b63-ba05-60d3a06b302f', - quantity: 10, - symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI - type: Type.BUY, - unitPrice: 177.69, - userId: userDemo.id - }, - { - accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c', - accountUserId: userDemo.id, - date: new Date(Date.UTC(2020, 2, 1, 0, 0, 0)), - fee: 19.9, - id: 'd01c6fbc-fa8d-47e6-8e80-66f882d2bfd2', - quantity: 10, - symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI - type: Type.BUY, - unitPrice: 203.15, - userId: userDemo.id - } - ], - skipDuplicates: true - }); - await prisma.tag.createMany({ data: [ { @@ -297,17 +11,6 @@ async function main() { ], skipDuplicates: true }); - - console.log({ - platformBitcoinSuisse, - platformBitpanda, - platformCoinbase, - platformDegiro, - platformInteractiveBrokers, - platformPostFinance, - platformSwissquote, - userDemo - }); } main()