From df602d5edb01510dcbab0e6af149a43a18afce34 Mon Sep 17 00:00:00 2001 From: KernelDeimos Date: Tue, 13 May 2025 15:21:15 -0400 Subject: [PATCH] dev: continue work on custom domains Adds service for querying controlling user for a domain. If no user is verified as allowed to control the domain then we give control to the 'admin' user (to support local configurations of Puter). After this point, I find myself a bit stuck because DNS queries are incredibly difficult to test locally when you use tailscale. --- src/backend/exports.js | 4 +++ .../src/modules/domain/DomainModule.js | 16 ++++++++++++ .../domain/DomainVerificationService.js | 26 +++++++++++++++++++ .../src/modules/domain/TXTVerifyService.js | 21 +++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 src/backend/src/modules/domain/DomainModule.js create mode 100644 src/backend/src/modules/domain/DomainVerificationService.js create mode 100644 src/backend/src/modules/domain/TXTVerifyService.js diff --git a/src/backend/exports.js b/src/backend/exports.js index d4a836b0..993cec01 100644 --- a/src/backend/exports.js +++ b/src/backend/exports.js @@ -39,6 +39,9 @@ const { InternetModule } = require("./src/modules/internet/InternetModule.js"); const { CaptchaModule } = require("./src/modules/captcha/CaptchaModule.js"); const { EntityStoreModule } = require("./src/modules/entitystore/EntityStoreModule.js"); const { KVStoreModule } = require("./src/modules/kvstore/KVStoreModule.js"); +const { ExternalExtrasModule } = require("./src/modules/external-extras/ExternalExtrasModule.js"); +const { FirebaseModule } = require("./src/modules/firebase/FirebaseModule.js"); +const { DomainModule } = require("./src/modules/domain/DomainModule.js"); module.exports = { helloworld: () => { @@ -64,6 +67,7 @@ module.exports = { CaptchaModule, EntityStoreModule, KVStoreModule, + DomainModule, ], // Pre-built modules diff --git a/src/backend/src/modules/domain/DomainModule.js b/src/backend/src/modules/domain/DomainModule.js new file mode 100644 index 00000000..8713b80b --- /dev/null +++ b/src/backend/src/modules/domain/DomainModule.js @@ -0,0 +1,16 @@ +const { AdvancedBase } = require("@heyputer/putility"); + +class DomainModule extends AdvancedBase { + async install (context) { + const services = context.get('services'); + + const { DomainVerificationService } = require('./DomainVerificationService'); + services.registerService('domain-verification', DomainVerificationService); + + // TODO: enable flag + const { TXTVerifyService } = require('./TXTVerifyService'); + services.registerService('__txt-verify', TXTVerifyService); + } +} + +module.exports = { DomainModule }; diff --git a/src/backend/src/modules/domain/DomainVerificationService.js b/src/backend/src/modules/domain/DomainVerificationService.js new file mode 100644 index 00000000..eded1424 --- /dev/null +++ b/src/backend/src/modules/domain/DomainVerificationService.js @@ -0,0 +1,26 @@ +const { get_user } = require("../../helpers"); +const BaseService = require("../../services/BaseService"); + +class DomainVerificationService extends BaseService { + async get_controlling_user ({ domain }) { + const svc_event = this.services.get('event'); + + // 1 :: Allow event listeners to verify domains + const event = { + domain, + user: undefined, + }; + await svc_event.emit('domain.get-controlling-user', event); + if ( event.user ) { + return event.user; + } + + // 2 :: If there is no controlling user, 'admin' is the + // controlling user. + return await get_user({ username: 'admin' }); + } +} + +module.exports = { + DomainVerificationService, +}; diff --git a/src/backend/src/modules/domain/TXTVerifyService.js b/src/backend/src/modules/domain/TXTVerifyService.js new file mode 100644 index 00000000..583212fc --- /dev/null +++ b/src/backend/src/modules/domain/TXTVerifyService.js @@ -0,0 +1,21 @@ +const { get_user } = require("../../helpers"); +const BaseService = require("../../services/BaseService"); + +class TXTVerifyService extends BaseService { + async _init () { + const require = this.require; + const dns = require('dns').promises; + + const svc_event = this.services.get('event'); + svc_event.on('domain.get-controlling-user', async (_, event) => { + let records = await dns.resolveTxt(`_puter-verify.${event.domain}`); + records = records.flat(); + + console.log('got records :: ', records); + }) + } +} + +module.exports = { + TXTVerifyService, +}