From cb6ef0414b9436060ec89649fafd89f1cf509f08 Mon Sep 17 00:00:00 2001 From: haim kastner Date: Sat, 7 Mar 2020 21:57:17 +0200 Subject: [PATCH 1/3] Download Last Log BE & FE #102 - Open option to ends the request within the controller and not by the generated TSOA routs. --- backend/src/app.ts | 1 + backend/src/controllers/logsController.ts | 23 ++++++++++++++ .../src/routers/expressRoutesTemplate.ts.tsoa | 6 +++- backend/src/routers/routes.ts | 31 ++++++++++++++++++- backend/swagger.yaml | 17 ++++++++++ .../app/core/sidebar/sidebar.component.html | 12 ++++++- .../src/app/core/sidebar/sidebar.component.ts | 4 +++ frontend/src/app/services/settings.service.ts | 4 +++ frontend/src/assets/i18n/en.json | 1 + frontend/src/assets/i18n/he.json | 1 + 10 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 backend/src/controllers/logsController.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index d1ff8492..907fc198 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -19,6 +19,7 @@ import './controllers/authController'; import './controllers/devicesController'; import './controllers/feedController'; import './controllers/iftttController'; +import './controllers/logsController'; import './controllers/minionsController'; import './controllers/operationsController'; import './controllers/radioFrequencyController'; diff --git a/backend/src/controllers/logsController.ts b/backend/src/controllers/logsController.ts new file mode 100644 index 00000000..1c7a7049 --- /dev/null +++ b/backend/src/controllers/logsController.ts @@ -0,0 +1,23 @@ +import * as express from 'express'; +import * as fse from 'fs-extra'; +import * as path from 'path'; +import { Controller, Get, Request, Response, Route, Security } from 'tsoa'; +import { ErrorResponse, UpdateResults, VersionInfo, VersionUpdateStatus } from '../models/sharedInterfaces'; +import { logger } from '../utilities/logger'; + +@Route('logs') +export class LogsController extends Controller { + /** + * Get the last logs of the local-server (download as text file) + */ + @Security('adminAuth') + @Response(501, 'Server error') + @Get('last') + public async getLastLogs(@Request() request: express.Request) { + const res = request.res as express.Response; + logger.info('[logs controller] Downloading log file...'); + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Disposition', `attachment; filename=casalogs_${new Date().toLocaleDateString()}.log`); + res.end(await fse.promises.readFile('./logs/tech_log.log')); + } +} diff --git a/backend/src/routers/expressRoutesTemplate.ts.tsoa b/backend/src/routers/expressRoutesTemplate.ts.tsoa index 681499a9..22a7c6c7 100644 --- a/backend/src/routers/expressRoutesTemplate.ts.tsoa +++ b/backend/src/routers/expressRoutesTemplate.ts.tsoa @@ -125,7 +125,11 @@ export function RegisterRoutes(app: express.Express) { statusCode = controllerObj.getStatus(); } - if (data || data === false) { // === false allows boolean result + // If the controller ends the request by own code, ignore any action. + if (response.finished) { + return; + } else if (data || data === false) { + // === false allows boolean result response.status(statusCode || 200).json(data); } else { response.status(statusCode || 204).end(); diff --git a/backend/src/routers/routes.ts b/backend/src/routers/routes.ts index dc4626c6..4ec50e3d 100644 --- a/backend/src/routers/routes.ts +++ b/backend/src/routers/routes.ts @@ -13,6 +13,7 @@ import { StaticAssetsController } from './../controllers/staticAssetsController' import { IftttController } from './../controllers/iftttController'; import { VersionsController } from './../controllers/versionsController'; import { RfController } from './../controllers/radioFrequencyController'; +import { LogsController } from './../controllers/logsController'; import { expressAuthentication } from './../security/authentication'; import * as express from 'express'; import { ErrorResponse, User } from '../../../backend/src/models/sharedInterfaces'; @@ -1858,6 +1859,30 @@ export function RegisterRoutes(app: express.Express) { const promise = controller.generateMinionCommand.apply(controller, validatedArgs as any); promiseHandler(controller, promise, response, next); }); + app.get('/API/logs/last', + authenticateMiddleware([{ "adminAuth": [] }]), + function(request: any, response: any, next: any) { + const args = { + request: { "in": "request", "name": "request", "required": true, "dataType": "object" }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + response.status(422).send({ + responseCode: 1422, + message: JSON.stringify(err.fields), + } as ErrorResponse); + return; + } + + const controller = new LogsController(); + + + const promise = controller.getLastLogs.apply(controller, validatedArgs as any); + promiseHandler(controller, promise, response, next); + }); function authenticateMiddleware(security: TsoaRoute.Security[] = []) { return (request: any, _response: any, next: any) => { @@ -1904,7 +1929,11 @@ export function RegisterRoutes(app: express.Express) { statusCode = controllerObj.getStatus(); } - if (data || data === false) { // === false allows boolean result + // If the controller ends the request by own code, ignore any action. + if (response.finished) { + return; + } else if (data || data === false) { + // === false allows boolean result response.status(statusCode || 200).json(data); } else { response.status(statusCode || 204).end(); diff --git a/backend/swagger.yaml b/backend/swagger.yaml index 3f047a88..a5e41dba 100644 --- a/backend/swagger.yaml +++ b/backend/swagger.yaml @@ -2592,6 +2592,23 @@ paths: required: true schema: $ref: '#/definitions/MinionStatus' + /logs/last: + get: + operationId: GetLastLogs + produces: + - application/json + responses: + '204': + description: 'No content' + '501': + description: 'Server error' + schema: + $ref: '#/definitions/ErrorResponse' + description: 'Get the last logs of the local-server (download as text file)' + security: + - + adminAuth: [] + parameters: [] produces: - application/json swagger: '2.0' diff --git a/frontend/src/app/core/sidebar/sidebar.component.html b/frontend/src/app/core/sidebar/sidebar.component.html index 8e320096..7e3fcfc6 100644 --- a/frontend/src/app/core/sidebar/sidebar.component.html +++ b/frontend/src/app/core/sidebar/sidebar.component.html @@ -79,11 +79,21 @@ +
+
+
{{ 'DOWNLOAD_LOGS' | translate }}
+ +
+
+
{{ 'PWA' | translate }}
diff --git a/frontend/src/app/core/sidebar/sidebar.component.ts b/frontend/src/app/core/sidebar/sidebar.component.ts index b58f403c..1850a701 100644 --- a/frontend/src/app/core/sidebar/sidebar.component.ts +++ b/frontend/src/app/core/sidebar/sidebar.component.ts @@ -325,4 +325,8 @@ export class SidebarComponent implements OnInit, OnDestroy { registration.unregister(); } } + + public async downloadLogs() { + await this.settingsService.downloadLogs(); + } } diff --git a/frontend/src/app/services/settings.service.ts b/frontend/src/app/services/settings.service.ts index 64b29e07..70d23c67 100644 --- a/frontend/src/app/services/settings.service.ts +++ b/frontend/src/app/services/settings.service.ts @@ -185,6 +185,10 @@ export class SettingsService { return updateStatus; } + public async downloadLogs() { + window.open(`${environment.baseUrl}/logs/last`); + } + private sleep(delayMs: number): Promise { return new Promise((resolve, reject) => { setTimeout(() => { diff --git a/frontend/src/assets/i18n/en.json b/frontend/src/assets/i18n/en.json index 7d5b235b..d3bc5633 100644 --- a/frontend/src/assets/i18n/en.json +++ b/frontend/src/assets/i18n/en.json @@ -245,6 +245,7 @@ "OVERRIDE_LOCK_IF_EXISTS" : "Override Lock Is exists", "LOCK_STATUSES" : "Lock Status", "OVERRIDE_LOCKS" : "Override Locks", + "DOWNLOAD_LOGS" : "Download Logs", "notConfigured": "Remote server not configured", "cantReachRemoteServer": "Remote server offline", "authorizationFail": "Local server fail to authenticate", diff --git a/frontend/src/assets/i18n/he.json b/frontend/src/assets/i18n/he.json index 258ac923..ef2716a8 100644 --- a/frontend/src/assets/i18n/he.json +++ b/frontend/src/assets/i18n/he.json @@ -244,6 +244,7 @@ "LOCK_STATUS_BY_TIMING" : "נעילת שינוי הסטטוס של התזמון", "OVERRIDE_LOCK_IF_EXISTS" : "דריסת נעילת סטטוס אם קיימת", "LOCK_STATUSES" : "נעילת סטטוסים", + "DOWNLOAD_LOGS" : "הורדת לוגים", "OVERRIDE_LOCKS" : "דרוס נעילות", "notConfigured": "לא הוגדר שרת מרוחק", "cantReachRemoteServer": "שרת מרוחק לא נגיש", From b63589ad6af5ed564ad493c441caa622df956a1a Mon Sep 17 00:00:00 2001 From: haim kastner Date: Sun, 8 Mar 2020 19:52:42 +0200 Subject: [PATCH 2/3] Send responses hreaders to the remote-server used to support not only Json responses --- backend/src/business-layer/remoteConnectionBl.ts | 12 +++++++----- backend/src/controllers/logsController.ts | 2 +- .../src/controllers/remoteConnectionController.ts | 1 + backend/src/models/remote2localProtocol.ts | 2 ++ backend/src/routers/routes.ts | 2 +- backend/swagger.yaml | 2 +- frontend/src/app/services/settings.service.ts | 2 +- 7 files changed, 14 insertions(+), 9 deletions(-) diff --git a/backend/src/business-layer/remoteConnectionBl.ts b/backend/src/business-layer/remoteConnectionBl.ts index 59af6b62..9e39a23e 100644 --- a/backend/src/business-layer/remoteConnectionBl.ts +++ b/backend/src/business-layer/remoteConnectionBl.ts @@ -104,8 +104,8 @@ export class RemoteConnectionBl { /** Start sending ack message interval */ setInterval(() => { /** If status is not OK or Connection problem - * dont send ack message. - * (If remote server not set yet, ther is no point to try sending ack). + * don't send ack message. + * (If remote server not set yet, there is no point to try sending ack). */ if (this.remoteConnectionStatus !== 'connectionOK' && this.remoteConnectionStatus !== 'cantReachRemoteServer') { return; @@ -204,7 +204,7 @@ export class RemoteConnectionBl { } return new Promise(async (resolve, reject) => { - await this.sendMessage({ + this.sendMessage({ localMessagesType: 'unregisterAccount', message: { unregisterAccount: { @@ -306,7 +306,7 @@ export class RemoteConnectionBl { } catch (error) {} } - /** Close manualy web socket to remote server */ + /** Close manually web socket to remote server */ private closeRemoteConnection() { try { this.webSocketClient.disconnect(); @@ -504,6 +504,7 @@ export class RemoteConnectionBl { request.set('Cookie', `session=${httpRequest.httpSession}`); /** send request and wait for response */ const response = await request.send(httpRequest.httpBody); + /** send response back to remote server */ this.sendMessage({ localMessagesType: 'httpResponse', @@ -511,8 +512,9 @@ export class RemoteConnectionBl { httpResponse: { requestId: httpRequest.requestId, httpStatus: response.status, - httpBody: response.body, + httpBody: response.type === 'application/json' ? response.body : response.text, httpSession: this.extractCookie(response.header), + httpHeaders: response.header, }, }, }); diff --git a/backend/src/controllers/logsController.ts b/backend/src/controllers/logsController.ts index 1c7a7049..eeca4efd 100644 --- a/backend/src/controllers/logsController.ts +++ b/backend/src/controllers/logsController.ts @@ -12,7 +12,7 @@ export class LogsController extends Controller { */ @Security('adminAuth') @Response(501, 'Server error') - @Get('last') + @Get() public async getLastLogs(@Request() request: express.Request) { const res = request.res as express.Response; logger.info('[logs controller] Downloading log file...'); diff --git a/backend/src/controllers/remoteConnectionController.ts b/backend/src/controllers/remoteConnectionController.ts index 62e5117a..ffa688ef 100644 --- a/backend/src/controllers/remoteConnectionController.ts +++ b/backend/src/controllers/remoteConnectionController.ts @@ -40,6 +40,7 @@ export class RemoteConnectionController extends Controller { @Response(501, 'Server error') @Get() public async getRemoteHost(): Promise { + this.setHeader('content-type', 'text/html; charset=UTF-8'); return await RemoteConnectionBlSingleton.getRemoteHost(); } diff --git a/backend/src/models/remote2localProtocol.ts b/backend/src/models/remote2localProtocol.ts index 751f10e6..49fe9f62 100644 --- a/backend/src/models/remote2localProtocol.ts +++ b/backend/src/models/remote2localProtocol.ts @@ -84,6 +84,8 @@ export declare interface HttpResponse { /** Session expires time in seconds. */ maxAge: number; }; + /** Http headers */ + httpHeaders?: { [key: string]: string }; } export declare interface LocalServerFeed { diff --git a/backend/src/routers/routes.ts b/backend/src/routers/routes.ts index 4ec50e3d..6d2ba514 100644 --- a/backend/src/routers/routes.ts +++ b/backend/src/routers/routes.ts @@ -1859,7 +1859,7 @@ export function RegisterRoutes(app: express.Express) { const promise = controller.generateMinionCommand.apply(controller, validatedArgs as any); promiseHandler(controller, promise, response, next); }); - app.get('/API/logs/last', + app.get('/API/logs', authenticateMiddleware([{ "adminAuth": [] }]), function(request: any, response: any, next: any) { const args = { diff --git a/backend/swagger.yaml b/backend/swagger.yaml index a5e41dba..2b7ac503 100644 --- a/backend/swagger.yaml +++ b/backend/swagger.yaml @@ -2592,7 +2592,7 @@ paths: required: true schema: $ref: '#/definitions/MinionStatus' - /logs/last: + /logs: get: operationId: GetLastLogs produces: diff --git a/frontend/src/app/services/settings.service.ts b/frontend/src/app/services/settings.service.ts index 70d23c67..324268e8 100644 --- a/frontend/src/app/services/settings.service.ts +++ b/frontend/src/app/services/settings.service.ts @@ -186,7 +186,7 @@ export class SettingsService { } public async downloadLogs() { - window.open(`${environment.baseUrl}/logs/last`); + window.open(`${environment.baseUrl}/logs`); } private sleep(delayMs: number): Promise { From 8e6c98f41338ff2f8091eb09029ef6207434f6a7 Mon Sep 17 00:00:00 2001 From: haim kastner Date: Tue, 10 Mar 2020 14:47:51 +0200 Subject: [PATCH 3/3] Replace the logger library. - use 'winston' instead of 'log4js' - fix logs new-line issue in Linux environments --- backend/.gitignore | 3 +- backend/package-lock.json | 203 +++++++++++++++------- backend/package.json | 4 +- backend/src/controllers/logsController.ts | 2 +- backend/src/index.ts | 2 +- backend/src/security/authentication.ts | 2 +- backend/src/utilities/logger.ts | 38 ++-- 7 files changed, 170 insertions(+), 84 deletions(-) diff --git a/backend/.gitignore b/backend/.gitignore index e4079083..53fcea29 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,2 +1,3 @@ bundle/ -temp/ \ No newline at end of file +temp/ +dist/ \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index 7dfaebf7..26c37cf2 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -1484,11 +1484,6 @@ "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", "dev": true }, - "circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==" - }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -1575,6 +1570,36 @@ "resolved": "https://registry.npmjs.org/color-temperature/-/color-temperature-0.2.7.tgz", "integrity": "sha1-bDKtndnA/gfM8thoBzR4FxIzK0A=" }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + }, + "dependencies": { + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + } + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1969,11 +1994,6 @@ "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" }, - "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=" - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -2123,6 +2143,16 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "diagnostics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "requires": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" + } + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -2331,6 +2361,14 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "requires": { + "env-variable": "0.0.x" + } + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -2349,6 +2387,11 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" }, + "env-variable": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", + "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==" + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -2810,6 +2853,11 @@ "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz", "integrity": "sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ==" }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -4424,6 +4472,14 @@ "json-buffer": "3.0.0" } }, + "kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "requires": { + "colornames": "^1.1.1" + } + }, "latest-version": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", @@ -4832,25 +4888,22 @@ "chalk": "^2.0.1" } }, - "log4js": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", - "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "rfdc": "^1.1.2", - "streamroller": "0.7.0" + "logform": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", + "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" }, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, "ms": { "version": "2.1.2", @@ -6558,6 +6611,11 @@ "wrappy": "1" } }, + "one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" + }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -8000,11 +8058,6 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, - "rfdc": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", - "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==" - }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -8376,6 +8429,11 @@ } } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "static-eval": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", @@ -8457,32 +8515,6 @@ } } }, - "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", - "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -8667,6 +8699,11 @@ "minimatch": "^3.0.4" } }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", @@ -8797,6 +8834,11 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, "ts-node": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", @@ -9347,6 +9389,51 @@ "string-width": "^2.1.1" } }, + "winston": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", + "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", + "requires": { + "async": "^2.6.1", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^2.1.1", + "one-time": "0.0.4", + "readable-stream": "^3.1.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.3.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "winston-transport": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", + "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", + "requires": { + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/backend/package.json b/backend/package.json index b6e7fe19..fb43a62e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -61,7 +61,6 @@ "ip": "^1.1.5", "is-online": "^8.2.1", "joi": "^14.3.0", - "log4js": "^3.0.6", "macaddress": "^0.2.9", "miio": "^0.15.6", "moment": "^2.23.0", @@ -81,6 +80,7 @@ "suncalc": "^1.8.0", "tsoa": "2.4.3", "tuyapi": "^5.1.2", + "winston": "^3.2.1", "yeelight-awesome": "^1.0.12" }, "devDependencies": { @@ -109,9 +109,9 @@ "del-cli": "^1.1.0", "mocha": "^6.1.4", "nyc": "^15.0.0", + "pkg": "^4.4.3", "prettier": "^1.19.1", "simple-git": "^1.121.0", - "pkg": "^4.4.3", "ts-node": "^7.0.1", "tslint": "^5.20.1", "tslint-config-prettier": "^1.18.0", diff --git a/backend/src/controllers/logsController.ts b/backend/src/controllers/logsController.ts index eeca4efd..dbdd94a6 100644 --- a/backend/src/controllers/logsController.ts +++ b/backend/src/controllers/logsController.ts @@ -18,6 +18,6 @@ export class LogsController extends Controller { logger.info('[logs controller] Downloading log file...'); res.setHeader('Content-Type', 'text/plain'); res.setHeader('Content-Disposition', `attachment; filename=casalogs_${new Date().toLocaleDateString()}.log`); - res.end(await fse.promises.readFile('./logs/tech_log.log')); + res.end(await fse.promises.readFile('./logs/casalogs.log')); } } diff --git a/backend/src/index.ts b/backend/src/index.ts index b0bebbae..a5a1438b 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -51,7 +51,7 @@ if (Configuration.http.useHttps) { logger.info('HTTPS/SSL listen on port ' + Configuration.http.httpsPort); }); } catch (error) { - logger.fatal(`Faild to load SSL certificate ${error}, exit...`); + logger.error(`Faild to load SSL certificate ${error}, exit...`); process.exit(); } } diff --git a/backend/src/security/authentication.ts b/backend/src/security/authentication.ts index 44cfd4ab..466d187d 100644 --- a/backend/src/security/authentication.ts +++ b/backend/src/security/authentication.ts @@ -38,7 +38,7 @@ export const expressAuthentication = async ( ): Promise => { // If the routing security sent wrong security scope. if (!scopes || scopes.length < 1) { - logger.fatal('invalid or empty security scope'); + logger.error('invalid or empty security scope'); throw { responseCode: 1501, } as ErrorResponse; diff --git a/backend/src/utilities/logger.ts b/backend/src/utilities/logger.ts index bc6c8d99..59ae0681 100644 --- a/backend/src/utilities/logger.ts +++ b/backend/src/utilities/logger.ts @@ -1,26 +1,24 @@ -import * as log4js from 'log4js'; import * as path from 'path'; +import * as winston from 'winston'; -const LOG_FILE_NAME: string = path.join('logs', 'tech_log.log'); +const LOG_FILE_NAME: string = path.join('logs', 'casalogs.log'); -log4js.configure({ - appenders: { - file_log: { - type: 'file', +const logFormat = winston.format.printf(info => `[${new Date().toLocaleString()}] [${info.level}] ${info.message}`); + +const casanetLogger = winston.createLogger({ + level: 'silly', + transports: [ + new winston.transports.Console({ + format: winston.format.combine(winston.format.colorize(), logFormat), + }), + new winston.transports.File({ + format: logFormat, filename: LOG_FILE_NAME, - maxLogSize: 10 * 1000000, // 10 mb - backups: 50, - }, - console_log: { - type: 'console', - }, - }, - categories: { - default: { - appenders: ['file_log', 'console_log'], - level: process.env.NODE_ENV !== 'test' ? 'debug' : 'warn', - }, - }, + maxsize: 1e6, + maxFiles: 30, + eol: `\r\n \n`, // For windows & linux new-lines flags + }), + ], }); -export const logger: log4js.Logger = log4js.getLogger(); +export const logger = casanetLogger;