From 7907bcb8a63421b6c894d35899e68d59ec617cb4 Mon Sep 17 00:00:00 2001 From: Stefan Werfling Date: Wed, 18 Oct 2023 00:02:09 +0200 Subject: [PATCH] #36 ddnsserver update --- backend/src/Routes/Main/DynDnsServer.ts | 13 +++ backend/src/Routes/Main/DynDnsServer/List.ts | 3 +- backend/src/Routes/Main/DynDnsServer/Save.ts | 95 ++++++++++++++++++- .../Db/MariaDb/DynDnsServerDomainService.ts | 31 +++++- .../Db/MariaDb/Entity/DynDnsServerDomain.ts | 2 +- .../inc/Db/MariaDb/Entity/DynDnsServerUser.ts | 2 +- ddnsserver/package.json | 2 + ddnsserver/src/Routes/Main/Update.ts | 7 +- frontend/src/inc/Pages/DynDnsServer.ts | 2 +- .../src/Backend/Routes/DynDnsServer/List.ts | 3 +- 10 files changed, 146 insertions(+), 14 deletions(-) diff --git a/backend/src/Routes/Main/DynDnsServer.ts b/backend/src/Routes/Main/DynDnsServer.ts index e6f5fd76..ad9605d2 100644 --- a/backend/src/Routes/Main/DynDnsServer.ts +++ b/backend/src/Routes/Main/DynDnsServer.ts @@ -1,6 +1,8 @@ import {DefaultRoute} from 'flyingfish_core'; import {Router} from 'express'; +import {SchemaDynDnsServerData} from 'flyingfish_schemas'; import {List} from './DynDnsServer/List.js'; +import {Save} from './DynDnsServer/Save.js'; /** * DynDnsServer @@ -20,6 +22,17 @@ export class DynDnsServer extends DefaultRoute { } ); + this._post( + '/json/dyndnsclient/save', + async(req, res) => { + if (this.isUserLogin(req, res)) { + if (this.isSchemaValidate(SchemaDynDnsServerData, req.body, res)) { + res.status(200).json(await Save.saveUser(req.body)); + } + } + } + ); + return super.getExpressRouter(); } diff --git a/backend/src/Routes/Main/DynDnsServer/List.ts b/backend/src/Routes/Main/DynDnsServer/List.ts index e490ad66..b6776318 100644 --- a/backend/src/Routes/Main/DynDnsServer/List.ts +++ b/backend/src/Routes/Main/DynDnsServer/List.ts @@ -38,8 +38,7 @@ export class List { password: user.password, last_update: user.last_update }, - domains: domainList, - last_update: user.last_update + domains: domainList }); } } diff --git a/backend/src/Routes/Main/DynDnsServer/Save.ts b/backend/src/Routes/Main/DynDnsServer/Save.ts index ff898824..6ff610a9 100644 --- a/backend/src/Routes/Main/DynDnsServer/Save.ts +++ b/backend/src/Routes/Main/DynDnsServer/Save.ts @@ -1,10 +1,99 @@ -import {DefaultReturn, StatusCodes} from 'flyingfish_schemas'; +import * as bcrypt from 'bcrypt'; +import { + DynDnsClientDomainServiceDB, DynDnsServerDomainDB, + DynDnsServerDomainServiceDB, + DynDnsServerUserDB, + DynDnsServerUserServiceDB +} from 'flyingfish_core'; +import {DefaultReturn, DynDnsServerData, StatusCodes} from 'flyingfish_schemas'; export class Save { - public async saveUser(): Promise { + public static async saveUser(data: DynDnsServerData): Promise { + let user: DynDnsServerUserDB|null = null; + + if (data.user.id > 0) { + const tuser = await DynDnsServerUserServiceDB.getInstance().findOne(data.user.id); + + if (tuser) { + user = tuser; + } + } + + if (user === null) { + user = new DynDnsServerUserDB(); + } + + // check username only one exist ------------------------------------------------------------------------------- + + const userByName = await DynDnsServerUserServiceDB.getInstance().findByName(data.user.username); + + if (userByName) { + if ((data.user.id > 0) && (data.user.id !== userByName.id)) { + return { + statusCode: StatusCodes.INTERNAL_ERROR, + msg: 'Username is already in use.' + }; + } + } + + // ------------------------------------------------------------------------------------------------------------- + + user.username = data.user.username; + + if (data.user.password && data.user.password !== '') { + user.password = await bcrypt.hash(data.user.password, 10); + } + + user = await DynDnsServerUserServiceDB.getInstance().save(user); + + if (user) { + if (data.domains.length === 0) { + await DynDnsServerDomainServiceDB.getInstance().removeByUserId(user.id); + } else { + const odomains = await DynDnsServerDomainServiceDB.getInstance().findByUser(user.id); + + if (odomains) { + const checkDomainExistence = (domainId: number): boolean => data.domains.some(({id}) => id === + domainId); + + for await (const oldDomain of odomains) { + if (!checkDomainExistence(oldDomain.domain_id)) { + await DynDnsServerDomainServiceDB.getInstance().remove(oldDomain.id); + } + } + } + + // update or add --------------------------------------------------------------------------------------- + + for await (const domain of data.domains) { + let newDomain: DynDnsServerDomainDB|null = null; + + const tdomain = await DynDnsServerDomainServiceDB.getInstance().findByDomainId(domain.id, user.id); + + if (tdomain) { + newDomain = tdomain; + } + + if (newDomain === null) { + newDomain = new DynDnsServerDomainDB(); + } + + newDomain.user_id = user.id; + newDomain.domain_id = domain.id; + + await DynDnsServerDomainServiceDB.getInstance().save(newDomain); + } + } + + return { + statusCode: StatusCodes.OK + }; + } + return { - statusCode: StatusCodes.OK + statusCode: StatusCodes.INTERNAL_ERROR, + msg: 'User data can not save.' }; } diff --git a/core/src/inc/Db/MariaDb/DynDnsServerDomainService.ts b/core/src/inc/Db/MariaDb/DynDnsServerDomainService.ts index f67a993b..96da64c7 100644 --- a/core/src/inc/Db/MariaDb/DynDnsServerDomainService.ts +++ b/core/src/inc/Db/MariaDb/DynDnsServerDomainService.ts @@ -1,3 +1,4 @@ +import {DeleteResult} from 'typeorm'; import {DBService} from './DBService.js'; import {DynDnsServerDomain} from './Entity/DynDnsServerDomain.js'; @@ -23,8 +24,8 @@ export class DynDnsServerDomainService extends DBService { } /** - * findByUser - * @param userid + * Find all entries by user ID. + * @param {number} userid - DynDns Server user ID. */ public async findByUser(userid: number): Promise { return this._repository.find({ @@ -34,4 +35,30 @@ export class DynDnsServerDomainService extends DBService { }); } + /** + * Remove all domain links by user ID. + * @param {number} userId - DynDns Server user ID. + * @returns {DeleteResult} + */ + public async removeByUserId(userId: number): Promise { + return this._repository.delete({ + user_id: userId + }); + } + + /** + * Find domain by user ID and domain ID. + * @param {number} domainId + * @param {number} userId + * @returns {DynDnsServerDomain|null} + */ + public async findByDomainId(domainId: number, userId: number): Promise { + return this._repository.findOne({ + where: { + domain_id: domainId, + user_id: userId + } + }); + } + } \ No newline at end of file diff --git a/core/src/inc/Db/MariaDb/Entity/DynDnsServerDomain.ts b/core/src/inc/Db/MariaDb/Entity/DynDnsServerDomain.ts index 7d97437a..c7603ac4 100644 --- a/core/src/inc/Db/MariaDb/Entity/DynDnsServerDomain.ts +++ b/core/src/inc/Db/MariaDb/Entity/DynDnsServerDomain.ts @@ -4,7 +4,7 @@ import {DBBaseEntityId} from '../DBBaseEntityId.js'; /** * DynDnsServerDomain */ -@Entity({name: 'dyndnsserver_domain'}) +@Entity({name: 'dyndns_server_domain'}) export class DynDnsServerDomain extends DBBaseEntityId { /** diff --git a/core/src/inc/Db/MariaDb/Entity/DynDnsServerUser.ts b/core/src/inc/Db/MariaDb/Entity/DynDnsServerUser.ts index 877df05e..b3c8697c 100644 --- a/core/src/inc/Db/MariaDb/Entity/DynDnsServerUser.ts +++ b/core/src/inc/Db/MariaDb/Entity/DynDnsServerUser.ts @@ -4,7 +4,7 @@ import {DBBaseEntityId} from '../DBBaseEntityId.js'; /** * DynDnsServerUser */ -@Entity({name: 'ddns_user'}) +@Entity({name: 'dyndns_server_user'}) export class DynDnsServerUser extends DBBaseEntityId { /** diff --git a/ddnsserver/package.json b/ddnsserver/package.json index 2fe9978a..bf6b9fd1 100644 --- a/ddnsserver/package.json +++ b/ddnsserver/package.json @@ -22,6 +22,7 @@ "homepage": "https://github.com/stefanwerfling/flyingfish#readme", "devDependencies": { "@types/basic-auth": "^1.1.3", + "@types/bcrypt": "^5.0.0", "@types/cookie-parser": "^1.4.3", "@types/express": "^4.17.17", "@types/express-session": "^1.17.7", @@ -35,6 +36,7 @@ }, "dependencies": { "basic-auth": "^2.0.1", + "bcrypt": "^5.1.0", "cookie-parser": "^1.4.6", "express": "^4.18.2", "express-rate-limit": "^6.7.1", diff --git a/ddnsserver/src/Routes/Main/Update.ts b/ddnsserver/src/Routes/Main/Update.ts index 4bef6643..0648eea3 100644 --- a/ddnsserver/src/Routes/Main/Update.ts +++ b/ddnsserver/src/Routes/Main/Update.ts @@ -1,3 +1,4 @@ +import * as bcrypt from 'bcrypt'; import {Request, Response, Router} from 'express'; import { DateHelper, @@ -152,7 +153,9 @@ export class Update extends DefaultRoute { if (ddnsUser) { Logger.getLogger().silly(`Update::nic-update: basic auth - user found by id: ${ddnsUser.id}`); - if (ddnsUser.password === credentials.pass) { + const bresult = await bcrypt.compare(credentials.pass, ddnsUser.password); + + if (bresult) { Logger.getLogger().silly(`Update::nic-update: password accept for user id: ${ddnsUser.id}`); granted = true; userId = ddnsUser.id; @@ -174,7 +177,7 @@ export class Update extends DefaultRoute { req.session.user.userid = userId; req.session.user.isLogin = true; - Update.setNicUpdate(req, req.session, res); + await Update.setNicUpdate(req, req.session, res); } } else { res.set('WWW-Authenticate', 'Basic realm="401"'); diff --git a/frontend/src/inc/Pages/DynDnsServer.ts b/frontend/src/inc/Pages/DynDnsServer.ts index 741b5265..ef56d1dc 100644 --- a/frontend/src/inc/Pages/DynDnsServer.ts +++ b/frontend/src/inc/Pages/DynDnsServer.ts @@ -125,7 +125,7 @@ export class DynDnsServer extends BasePage { domainsTd.append(' '); } - const date = moment(entry.last_update * 1000); + const date = moment(entry.user.last_update * 1000); // eslint-disable-next-line no-new new Td(trbody, date.format('YYYY-MM-DD HH:mm:ss')); diff --git a/schemas/src/Backend/Routes/DynDnsServer/List.ts b/schemas/src/Backend/Routes/DynDnsServer/List.ts index 753cabc4..788377aa 100644 --- a/schemas/src/Backend/Routes/DynDnsServer/List.ts +++ b/schemas/src/Backend/Routes/DynDnsServer/List.ts @@ -34,8 +34,7 @@ export type DynDnsServerDomain = ExtractSchemaResultType