diff --git a/extensions/puterfs/fsentries/FSEntryController.js b/extensions/puterfs/fsentries/FSEntryController.js index a24675c66..0ce5b3802 100644 --- a/extensions/puterfs/fsentries/FSEntryController.js +++ b/extensions/puterfs/fsentries/FSEntryController.js @@ -69,6 +69,11 @@ export default class FSEntryController { 'layout', 'path', ]; + + this.subdomainProperties = [ + 'uuid', + 'subdomain', + ]; } init () { @@ -223,18 +228,43 @@ export default class FSEntryController { async get_descendants_full (uuid, fetch_entry_options) { const { thumbnail } = fetch_entry_options; const columns = `${ - this.defaultProperties.join(', ') + [ + ...this.defaultProperties.map(v => `f.${v}`), + ...this.subdomainProperties + .map(v => `s.${v} AS subdomain_${v}`), + ].join(', ') }${thumbnail ? ', thumbnail' : ''}`; - return uuid === PuterPath.NULL_UUID + const results_with_dupes = uuid === PuterPath.NULL_UUID ? await db.read( `SELECT ${columns} FROM fsentries WHERE parent_uid IS NULL`, [uuid], ) : await db.read( - `SELECT ${columns} FROM fsentries WHERE parent_uid = ?`, + `SELECT ${columns} FROM fsentries AS f ` + + 'LEFT JOIN subdomains AS s ON f.id=s.root_dir_id ' + + 'WHERE parent_uid = ? ORDER BY f.id', [uuid], ) ; + + const byId = new Map(); + for ( const row of results_with_dupes ) { + const id = row.id; + let entry = byId.get(id); + if ( ! entry ) { + entry = { ...row }; + if ( thumbnail ) entry.thumbnail = row.thumbnail; + entry.subdomains = []; + byId.set(id, entry); + } + if ( row.subdomain_uuid != null ) { + entry.subdomains.push({ + uuid: row.subdomain_uuid, + subdomain: row.subdomain_subdomain, + }); + } + } + return Array.from(byId.values()); } async get_recursive_size (uuid) { diff --git a/src/backend/src/filesystem/hl_operations/hl_readdir.js b/src/backend/src/filesystem/hl_operations/hl_readdir.js index 66c646d18..488defcf5 100644 --- a/src/backend/src/filesystem/hl_operations/hl_readdir.js +++ b/src/backend/src/filesystem/hl_operations/hl_readdir.js @@ -66,11 +66,13 @@ class HLReadDir extends HLFilesystemOperation { let children; - this.log.debug('READDIR', - { - userdir: await subject.isUserDirectory(), - namediff: await subject.get('name') !== user.username, - }); + this.log.debug( + 'READDIR', + { + userdir: await subject.isUserDirectory(), + namediff: await subject.get('name') !== user.username, + }, + ); if ( subject.isRoot ) { const ll_listusers = new LLListUsers(); children = await ll_listusers.run(this.values); @@ -123,7 +125,8 @@ class HLReadDir extends HLFilesystemOperation { } if ( ! no_subdomains ) { - await this.#batchFetchSubdomains(children, user); + // await this.#batchFetchSubdomains(children, user); + await this.#applySubdomains(children); } return Promise.all(children.map(async child => { @@ -142,6 +145,17 @@ class HLReadDir extends HLFilesystemOperation { })); } + async #applySubdomains (children) { + for ( const child of children ) { + if ( ! child.subdomains ) return; + if ( child.subdomains.length > 0 ) child.has_website = true; + for ( const subdomain of child.subdomains ) { + subdomain.address = + `${config.protocol}://${subdomain.subdomain}.puter.site`; + } + } + } + async #batchFetchSubdomains (children, user) { const childIds = []; const childById = new Map(); @@ -160,10 +174,12 @@ class HLReadDir extends HLFilesystemOperation { const placeholders = childIds.map(() => '?').join(','); const db = this.context.get('services').get('database').get(DB_READ, 'filesystem'); - const rows = await db.read(`SELECT root_dir_id, subdomain, uuid + const rows = await db.read( + `SELECT root_dir_id, subdomain, uuid FROM subdomains WHERE root_dir_id IN (${placeholders}) AND user_id = ?`, - [...childIds, user.id]); + [...childIds, user.id], + ); for ( const row of rows ) { const child = childById.get(row.root_dir_id); diff --git a/src/backend/src/filesystem/node/selectors.js b/src/backend/src/filesystem/node/selectors.js index 3572ac3ba..ce8ad529f 100644 --- a/src/backend/src/filesystem/node/selectors.js +++ b/src/backend/src/filesystem/node/selectors.js @@ -169,6 +169,10 @@ class NodeRawEntrySelector extends NodeSelector { node.uid = this.entry.uid ?? this.entry.uuid; node.name = this.entry.name; if ( this.entry.path ) node.path = this.entry.path; + + if ( this.entry.subdomains ) { + node.subdomains = this.entry.subdomains; + } } describe () {