From cabbc17581346fb39402ff9a3e019f62f20f5079 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 25 Jul 2021 14:38:14 +0200 Subject: [PATCH] wip --- package.json | 3 +- src/components/home.component.ts | 2 +- src/components/login.component.pug | 2 +- src/components/login.component.ts | 2 + src/interceptor.ts | 3 +- src/server.ts | 55 ++++++++++------------------ src/services/appConnector.service.ts | 2 +- src/services/common.service.ts | 23 +++++++----- tabby/settings.py | 20 +++++++++- tabby/urls.py | 2 +- webpack.config.js | 8 +++- yarn.lock | 5 +++ 12 files changed, 74 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index 86e1322..21bb1e6 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "main": "index.js", "scripts": { "build": "webpack --progress", - "watch": "BACKEND_URL=http://localhost:8001 DEV=1 webpack --progress --watch", + "watch": "DEV=1 webpack --progress --watch", "build:server": "webpack --progress -c webpack.config.server.js", "watch:server": "DEV=1 webpack --progress --watch -c webpack.config.server.js", "start": "./manage.py runserver 8001", @@ -42,6 +42,7 @@ "core-js": "^3.14.0", "css-loader": "^2.1.0", "deepmerge": "^4.2.2", + "dotenv": "^10.0.0", "eslint": "^7.31.0", "file-loader": "^1.1.11", "html-loader": "^2.1.2", diff --git a/src/components/home.component.ts b/src/components/home.component.ts index de7c894..432873d 100644 --- a/src/components/home.component.ts +++ b/src/components/home.component.ts @@ -37,7 +37,7 @@ class DemoConnector { } async getDistURL (): Promise { - return await this.commonService.getBackendURL() + '/app-dist' + return await this.commonService.backendURL$ + '/app-dist' } getPluginsToLoad (): string[] { diff --git a/src/components/login.component.pug b/src/components/login.component.pug index 314c3e1..9e3e9b0 100644 --- a/src/components/login.component.pug +++ b/src/components/login.component.pug @@ -4,7 +4,7 @@ main(*ngIf='ready && loggedIn') a.btn( *ngFor='let provider of providers', [class]='provider.cls', - href='/api/1/auth/social/login/{{provider.id}}' + href='{{commonService.backendURL$|async}}/api/1/auth/social/login/{{provider.id}}' ) fa-icon([icon]='provider.icon', [fixedWidth]='true') span Log in with {{provider.name}} diff --git a/src/components/login.component.ts b/src/components/login.component.ts index dfec865..885945b 100644 --- a/src/components/login.component.ts +++ b/src/components/login.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core' import { LoginService } from '../services/login.service' +import { CommonService } from '../services/common.service' import { faGithub, faGitlab, faGoogle, faMicrosoft } from '@fortawesome/free-brands-svg-icons' @@ -21,6 +22,7 @@ export class LoginComponent { constructor ( private loginService: LoginService, + public commonService: CommonService, ) { } async ngOnInit () { diff --git a/src/interceptor.ts b/src/interceptor.ts index 851d8db..9fb9faa 100644 --- a/src/interceptor.ts +++ b/src/interceptor.ts @@ -10,11 +10,12 @@ export class UniversalInterceptor implements HttpInterceptor { intercept (request: HttpRequest, next: HttpHandler): Observable> { if (!request.url.startsWith('//') && request.url.startsWith('/')) { - return from(this.commonService.getBackendURL()).pipe(switchMap((baseUrl: string) => { + return from(this.commonService.backendURL$).pipe(switchMap((baseUrl: string) => { const endpoint = request.url request = request.clone({ url: `${baseUrl}${endpoint}`, + withCredentials: true, }) return next.handle(request) })) diff --git a/src/server.ts b/src/server.ts index 244f22a..bd208a2 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,54 +1,39 @@ -require('source-map-support').install() +import { install } from 'source-map-support' -import 'zone.js/dist/zone-node'; +import 'zone.js/dist/zone-node' import './ssr-polyfills' -import { enableProdMode } from '@angular/core'; - -// Express Engine -import { ngExpressEngine } from '@nguniversal/express-engine'; - +import { enableProdMode } from '@angular/core' +import { ngExpressEngine } from '@nguniversal/express-engine' import * as express from 'express' import { join } from 'path' -// Faster server renders w/ Prod mode (dev mode never needed) -enableProdMode(); +install() +enableProdMode() -// Express server -const app = express(); +const app = express() -const PORT = process.env.PORT || 4000; -const DIST_FOLDER = join(process.cwd(), 'build'); +const PORT = process.env.PORT || 4000 +const DIST_FOLDER = join(process.cwd(), 'build') import { AppServerModule } from './app.server.module' app.engine('html', ngExpressEngine({ - bootstrap: AppServerModule, -})); + bootstrap: AppServerModule, +})) -app.set('view engine', 'html'); -app.set('views', DIST_FOLDER); +app.set('view engine', 'html') +app.set('views', DIST_FOLDER) -// Example Express Rest API endpoints -// app.get('/api/**', (req, res) => { }); - -// Server static files from /browser -app.use('/static', express.static(DIST_FOLDER, { - maxAge: '1y' -})); - -// var proxy = require('express-http-proxy'); +app.get('*.*', express.static(DIST_FOLDER, { + maxAge: '1y', +})) app.get('*', (req, res) => { - res.render('index', { req }); -}); + res.render('index', { req }) +}) - -// app.use('/', proxy('http://tabby.local:8000/api/', { -// })) - -// Start up the Node server app.listen(PORT, () => { - console.log(`Node Express server listening on http://localhost:${PORT}`); -}); + console.log(`Node Express server listening on http://localhost:${PORT}`) +}) diff --git a/src/services/appConnector.service.ts b/src/services/appConnector.service.ts index e4fee5f..0707bd8 100644 --- a/src/services/appConnector.service.ts +++ b/src/services/appConnector.service.ts @@ -160,7 +160,7 @@ export class AppConnectorService { } async getDistURL (): Promise { - return await this.commonService.getBackendURL() + '/app-dist' + return await this.commonService.backendURL$ + '/app-dist' } getPluginsToLoad (): string[] { diff --git a/src/services/common.service.ts b/src/services/common.service.ts index 36ef8c5..ee10dda 100644 --- a/src/services/common.service.ts +++ b/src/services/common.service.ts @@ -3,16 +3,21 @@ import { Injectable } from '@angular/core' @Injectable({ providedIn: 'root' }) export class CommonService { - private backendURL?: string + private configPromise: Promise + backendURL$: Promise - async getBackendURL (): Promise { - if (!this.backendURL) { - const config = await (await fetch('/config.json')).json() - this.backendURL = config.backendURL - if (this.backendURL.endsWith('/')) { - this.backendURL = this.backendURL.slice(0, -1) + constructor () { + this.configPromise = this.getConfig() + this.backendURL$ = this.configPromise.then(cfg => { + let backendURL = cfg.backendURL + if (backendURL.endsWith('/')) { + backendURL = backendURL.slice(0, -1) } - } - return this.backendURL + return backendURL + }) + } + + private async getConfig () { + return (await fetch('/config.json')).json() } } diff --git a/tabby/settings.py b/tabby/settings.py index e223cb7..05165d2 100644 --- a/tabby/settings.py +++ b/tabby/settings.py @@ -169,8 +169,6 @@ SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.user.user_details', ) -LOGIN_REDIRECT_URL = '/app' - APP_DIST_PATH = Path(os.getenv('APP_DIST_PATH', BASE_DIR / 'app-dist')) NPM_REGISTRY = os.getenv('NPM_REGISTRY', 'https://registry.npmjs.org').rstrip('/') @@ -229,3 +227,21 @@ else: if FRONTEND_URL: CORS_ALLOWED_ORIGINS = [FRONTEND_URL] + CORS_ALLOW_CREDENTIALS = True + CORS_ALLOW_HEADERS = [ + 'accept', + 'accept-encoding', + 'authorization', + 'content-type', + 'dnt', + 'origin', + 'user-agent', + 'x-xsrf-token', + 'x-requested-with', + ] + CSRF_TRUSTED_ORIGINS = [FRONTEND_URL] + FRONTEND_URL = FRONTEND_URL.rstrip('/') +else: + FRONTEND_URL = '' + +LOGIN_REDIRECT_URL = FRONTEND_URL + '/app' diff --git a/tabby/urls.py b/tabby/urls.py index b1eaeff..7a7e29f 100644 --- a/tabby/urls.py +++ b/tabby/urls.py @@ -8,7 +8,7 @@ urlpatterns = [ path('', include(app_urlpatterns)), path('api/1/auth/social/', include('social_django.urls', namespace='social')), path('admin/', admin.site.urls), - path(f'^{settings.STATIC_URL}', serve, kwargs={ + path(f'{settings.STATIC_URL}', serve, kwargs={ 'document_root': settings.STATIC_ROOT, }), ] diff --git a/webpack.config.js b/webpack.config.js index 90f94f4..c519107 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,3 +1,4 @@ +require('dotenv').config() const baseConfig = require('./webpack.config.base.js') const fs = require('fs') const path = require('path') @@ -12,6 +13,11 @@ const htmlPluginOptions = { const outputPath = path.join(__dirname, 'build') const backendURL = process.env.BACKEND_URL + +if (process.env.DEV && !backendURL) { + backendURL = 'http://localhost:8001' +} + if (!backendURL) { throw new Error('BACKEND_URL env var is required') } @@ -45,7 +51,7 @@ module.exports = { }), { apply: (compiler) => { - compiler.hooks.afterEmit.tap('AfterEmitPlugin', _ => { + compiler.hooks.afterEmit.tap('AfterEmitPlugin', () => { fs.writeFileSync(path.join(outputPath, 'config.json'), JSON.stringify({ backendURL, })) diff --git a/yarn.lock b/yarn.lock index b43cd85..1bcf69b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1826,6 +1826,11 @@ dot-case@^3.0.4: no-case "^3.0.4" tslib "^2.0.3" +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"