diff --git a/pkg/admin/package.json b/pkg/admin/package.json index b34a2cbc2..2646e08c8 100644 --- a/pkg/admin/package.json +++ b/pkg/admin/package.json @@ -37,6 +37,7 @@ "express-formidable": "^1.2.0", "express-session": "^1.17.2", "pg": "^8.6.0", + "read-yaml-file": "^2.1.0", "reflect-metadata": "^0.1.13", "typeorm": "^0.2.34" }, diff --git a/pkg/admin/src/db.ts b/pkg/admin/src/db.ts index 612c70826..95ef60f49 100644 --- a/pkg/admin/src/db.ts +++ b/pkg/admin/src/db.ts @@ -12,29 +12,41 @@ import { import AdminJs from 'adminjs' import { Database, Resource } from '@adminjs/typeorm' -export const registerDatabase = async (): Promise => { +export const registerDatabase = async (secrets: any): Promise => { AdminJs.registerAdapter({ Database, Resource }) let host = 'localhost' if (process.env.K_SERVICE) { console.log( 'connecting to database via Cloud Run connection', - process.env.CLOUD_SQL_CONNECTION_NAME, - process.env.DB_NAME + process.env.CLOUD_SQL_CONNECTION_NAME ) const dbSocketPath = process.env.DB_SOCKET_PATH || '/cloudsql' host = `${dbSocketPath}/${process.env.CLOUD_SQL_CONNECTION_NAME}` } - console.log('connecting to database:', host) + console.log('connecting to database:', { + type: 'postgres', + host: host, + schema: 'omnivore', + database: secrets.DB_DATABASE, + }) + const connection = await createConnection({ type: 'postgres', host: host, schema: 'omnivore', - username: process.env.DB_USER, - password: process.env.DB_PASS, - database: process.env.DB_DATABASE, - entities: [AdminUser, User, UserProfile, UserArticle], + username: secrets.DB_USER, + password: secrets.DB_PASS, + database: secrets.DB_DATABASE, + entities: [ + AdminUser, + User, + UserProfile, + UserArticle, + ReceivedEmail, + ContentDisplayReport, + ], }) return connection @@ -118,3 +130,59 @@ export class UserArticle extends BaseEntity { @Column({ type: 'timestamp', name: 'saved_at' }) savedAt!: Date } + +@Entity({ name: 'content_display_report' }) +export class ContentDisplayReport extends BaseEntity { + @PrimaryGeneratedColumn('uuid') + id!: string + + @JoinColumn({ name: 'user_id' }) + @ManyToOne(() => User, (user) => user.articles, { eager: true }) + user!: User + + @Column({ type: 'text', name: 'original_url' }) + originalUrl!: string + + @Column({ type: 'text', name: 'report_comment' }) + reportComment!: string + + @Column({ type: 'timestamp', name: 'created_at' }) + createdAt!: Date + + @Column({ type: 'timestamp', name: 'updated_at' }) + updatedAt!: Date +} + +@Entity({ name: 'received_emails' }) +export class ReceivedEmail extends BaseEntity { + @PrimaryGeneratedColumn('uuid') + id!: string + + @JoinColumn({ name: 'user_id' }) + @ManyToOne(() => User, (user) => user.articles, { eager: true }) + user!: User + + @Column('text') + from!: string + + @Column('text') + to!: string + + @Column('text') + subject!: string + + @Column('text') + text!: string + + @Column('text') + html!: string + + @Column('text') + type!: 'article' | 'non-article' + + @Column({ type: 'timestamp', name: 'created_at' }) + createdAt!: Date + + @Column({ type: 'timestamp', name: 'updated_at' }) + updatedAt!: Date +} diff --git a/pkg/admin/src/index.ts b/pkg/admin/src/index.ts index d7a312c5f..56faeaaf3 100644 --- a/pkg/admin/src/index.ts +++ b/pkg/admin/src/index.ts @@ -1,15 +1,26 @@ -import express from 'express'; -import AdminJs from 'adminjs'; -import AdminJsExpress from '@adminjs/express'; -import { registerDatabase, AdminUser, User, UserArticle, UserProfile } from './db'; -import { compare, hashSync } from 'bcryptjs'; +import express from 'express' +import AdminJs from 'adminjs' +import AdminJsExpress from '@adminjs/express' +import { + registerDatabase, + AdminUser, + User, + UserArticle, + UserProfile, + ReceivedEmail, + ContentDisplayReport, +} from './db' +import { compare, hashSync } from 'bcryptjs' +const readYamlFile = require('read-yaml-file') -const app = express(); -const port = process.env.PORT || '8000'; -const ADMIN_USER_EMAIL = process.env.ADMIN_USER_EMAIL || 'admin-user@omnivore.app'; +const app = express() +const port = process.env.PORT || '8000' +const ADMIN_USER_EMAIL = + process.env.ADMIN_USER_EMAIL || 'admin-user@omnivore.app' -(async () => { - const db = await registerDatabase(); +;(async () => { + const secrets = await readYamlFile(process.env.SECRETS_FILE) + const db = await registerDatabase(secrets) const adminBro = new AdminJs({ databases: [db], @@ -23,36 +34,45 @@ const ADMIN_USER_EMAIL = process.env.ADMIN_USER_EMAIL || 'admin-user@omnivore.ap }, { resource: UserProfile, options: { parent: { name: 'Users' } } }, { resource: UserArticle, options: { parent: { name: 'Users' } } }, + { resource: ReceivedEmail, options: { parent: { name: 'Users' } } }, + { + resource: ContentDisplayReport, + }, ], - }); + }) const router = AdminJsExpress.buildAuthenticatedRouter(adminBro, { authenticate: async (email, password) => { - const user = await AdminUser.findOne({ email }); + const user = await AdminUser.findOne({ email }) + console.log('looked up user: ', user) if (user) { - const matched = await compare(password, user.password); - return matched ? user : false; + const matched = await compare(password, user.password) + console.log(' -- failed match') + return matched ? user : false } else if (email === ADMIN_USER_EMAIL) { + console.log('user is admin user, creating account') // If no admin user has been created yet, create one // from the environment variables. This is only done // once, and then the admin user should create a user // for each user. - if (!process.env.ADMIN_USER_PASSWORD) { - throw new Error('ADMIN_USER_PASSWORD is not set'); + if (!secrets.ADMIN_USER_PASSWORD) { + throw new Error('ADMIN_USER_PASSWORD is not set') } return AdminUser.create({ email: ADMIN_USER_EMAIL, - password: hashSync(process.env.ADMIN_USER_PASSWORD, 10), - }); + password: hashSync(secrets.ADMIN_USER_PASSWORD, 10), + }) } - return false; + return false }, - cookiePassword: process.env.ADMIN_COOKIE_SECRET || 'some-secret-password-used-to-secure-cookie', - }); + cookiePassword: + secrets.ADMIN_USER_PASSWORD || + 'some-secret-password-used-to-secure-cookie', + }) - app.use(adminBro.options.rootPath, router); + app.use(adminBro.options.rootPath, router) app.listen(port, () => { - return console.log(`Server is listening on ${port}`); - }); -})(); + return console.log(`Server is listening on ${port}`) + }) +})() diff --git a/pkg/admin/yarn.lock b/pkg/admin/yarn.lock index c39f37eab..b9af5576a 100644 --- a/pkg/admin/yarn.lock +++ b/pkg/admin/yarn.lock @@ -4154,6 +4154,14 @@ react@=16.13.1: object-assign "^4.1.1" prop-types "^15.6.2" +read-yaml-file@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/read-yaml-file/-/read-yaml-file-2.1.0.tgz#c5866712db9ef5343b4d02c2413bada53c41c4a9" + integrity sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ== + dependencies: + js-yaml "^4.0.0" + strip-bom "^4.0.0" + readable-stream@^2.3.7: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -4608,6 +4616,11 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"