From 353cf397cb43c6369bada698a784ef4914546a83 Mon Sep 17 00:00:00 2001 From: KernelDeimos <7225168+KernelDeimos@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:43:47 -0400 Subject: [PATCH] dev: remove legacy whoami and use extension --- extensions/whoami/routes.js | 4 +- src/backend/src/routers/whoami.js | 264 -------------------- src/backend/src/services/PuterAPIService.js | 1 - 3 files changed, 2 insertions(+), 267 deletions(-) delete mode 100644 src/backend/src/routers/whoami.js diff --git a/extensions/whoami/routes.js b/extensions/whoami/routes.js index 5020d1243..b552fc699 100644 --- a/extensions/whoami/routes.js +++ b/extensions/whoami/routes.js @@ -58,7 +58,7 @@ const whoami_common = ({ is_user, user }) => { return details; }; -extension.get('/future/whoami', { subdomain: 'api' }, async (req, res, next) => { +extension.get('/whoami', { subdomain: 'api' }, async (req, res, next) => { const actor = req.actor; if ( ! actor ) { throw Error('actor not found in context'); @@ -134,7 +134,7 @@ extension.get('/future/whoami', { subdomain: 'api' }, async (req, res, next) => res.send(details); }); -extension.post('/future/whoami', { subdomain: 'api' }, async (req, res) => { +extension.post('/whoami', { subdomain: 'api' }, async (req, res) => { const actor = req.actor; if ( ! actor ) { throw Error('actor not found in context'); diff --git a/src/backend/src/routers/whoami.js b/src/backend/src/routers/whoami.js deleted file mode 100644 index bb14469d5..000000000 --- a/src/backend/src/routers/whoami.js +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2024-present Puter Technologies Inc. - * - * This file is part of Puter. - * - * Puter is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -"use strict" -const express = require('express'); - -// Timeago is so inconvenient to instantiate that I'm using an IIFE -// to reduce the impact on the scope. -const timeago = (() => { - const TimeAgo = require('javascript-time-ago'); - TimeAgo.addDefaultLocale(require('javascript-time-ago/locale/en')); - return new TimeAgo('en-US'); -})(); - -const { get_taskbar_items, is_shared_with_anyone, suggest_app_for_fsentry, get_app, get_descendants, id2uuid } = require('../helpers'); -const auth = require('../middleware/auth.js'); -const _path = require('path'); -const eggspress = require('../api/eggspress'); -const { Context } = require('../util/context'); -const { UserActorType, AppUnderUserActorType } = require('../services/auth/Actor'); - -const whoami_common = ({ is_user, user }) => { - const details = {}; - - // User's immutable default (often called "system") directories' - // alternative (to path) identifiers are sent to the user's client - // (but not to apps; they don't need this information) - if ( is_user ) { - const directories = details.directories = {}; - const name_to_path = { - 'desktop_uuid': `/${user.username}/Desktop`, - 'appdata_uuid': `/${user.username}/AppData`, - 'documents_uuid': `/${user.username}/Documents`, - 'pictures_uuid': `/${user.username}/Pictures`, - 'videos_uuid': `/${user.username}/Videos`, - 'trash_uuid': `/${user.username}/Trash`, - }; - for ( const k in name_to_path ) { - directories[name_to_path[k]] = user[k]; - } - } - - if(user.last_activity_ts){ - - // Create a Date object and get the epoch timestamp - let epoch; - try{ - epoch = new Date(user.last_activity_ts).getTime(); - // round to 1 decimal place - epoch = Math.round(epoch/1000); - }catch(e){ - // console.error('Error parsing last_activity_ts', e); - } - - // add last_activity_ts - details.last_activity_ts = epoch; - } - - return details; -}; - -// -----------------------------------------------------------------------// -// GET /whoami -// -----------------------------------------------------------------------// -const WHOAMI_GET = eggspress('/whoami', { - subdomain: 'api', - auth2: true, - allowedMethods: ['GET'], -}, async (req, res, next) => { - const actor = Context.get('actor'); - if ( ! actor ) { - throw Error('actor not found in context'); - } - - const is_user = actor.type instanceof UserActorType; - - if ( req.query.icon_size ) { - const ALLOWED_SIZES = ['16', '32', '64', '128', '256', '512']; - - if ( ! ALLOWED_SIZES.includes(req.query.icon_size) ) { - res.status(400).send({ error: 'Invalid icon_size' }); - } - } - - // send user object - const details = { - username: req.user.username, - uuid: req.user.uuid, - email: req.user.email, - unconfirmed_email: req.user.email, - email_confirmed: req.user.email_confirmed - || req.user.username === 'admin', - requires_email_confirmation: req.user.requires_email_confirmation, - desktop_bg_url: req.user.desktop_bg_url, - desktop_bg_color: req.user.desktop_bg_color, - desktop_bg_fit: req.user.desktop_bg_fit, - is_temp: (req.user.password === null && req.user.email === null), - taskbar_items: await get_taskbar_items(req.user, { - ...(req.query.icon_size - ? { icon_size: req.query.icon_size } - : { no_icons: true }), - }), - referral_code: req.user.referral_code, - otp: !! req.user.otp_enabled, - human_readable_age: timeago.format( - new Date(req.user.timestamp)), - ...(req.new_token ? { token: req.token } : {}) - }; - - // TODO: redundant? GetUserService already puts these values on 'user' - // Get whoami values from other services - const svc_whoami = req.services.get('whoami'); - const provider_details = await svc_whoami.get_details({ - user: req.user, - actor: actor, - }); - Object.assign(details, provider_details); - - if ( ! is_user ) { - // When apps call /whoami they should not see these attributes - // delete details.username; - // delete details.uuid; - delete details.email; - delete details.unconfirmed_email; - delete details.desktop_bg_url; - delete details.desktop_bg_color; - delete details.desktop_bg_fit; - delete details.taskbar_items; - delete details.token; - delete details.human_readable_age; - } - - if ( actor.type instanceof AppUnderUserActorType ) { - details.app_name = actor.type.app.name; - - // IDEA: maybe we do this in the future - // details.app = { - // name: actor.type.app.name, - // }; - } - - Object.assign(details, whoami_common({ is_user, user: req.user })); - - res.send(details); -}) - -// -----------------------------------------------------------------------// -// POST /whoami -// -----------------------------------------------------------------------// -const WHOAMI_POST = new express.Router(); -WHOAMI_POST.post('/whoami', auth, express.json(), async (req, response, next)=>{ - // check subdomain - if(require('../helpers').subdomain(req) !== 'api') { - return; - } - - const actor = Context.get('actor'); - if ( ! actor ) { - throw Error('actor not found in context'); - } - - const is_user = actor.type instanceof UserActorType; - if ( ! is_user ) { - throw Error('actor is not a user'); - } - - let desktop_items = []; - - // check if user asked for desktop items - if(req.query.return_desktop_items === 1 || req.query.return_desktop_items === '1' || req.query.return_desktop_items === 'true'){ - // by cached desktop id - if(req.user.desktop_id){ - // TODO: Check if used anywhere, maybe remove - // eslint-disable-next-line no-undef - desktop_items = await db.read( - `SELECT * FROM fsentries - WHERE user_id = ? AND parent_uid = ?`, - [req.user.id, await id2uuid(req.user.desktop_id)] - ) - } - // by desktop path - else{ - desktop_items = await get_descendants(req.user.username +'/Desktop', req.user, 1, true); - } - - // clean up desktop items and add some extra information - if(desktop_items.length > 0){ - if(desktop_items.length > 0){ - for (let i = 0; i < desktop_items.length; i++) { - if(desktop_items[i].id !== null){ - // suggested_apps for files - if(!desktop_items[i].is_dir){ - desktop_items[i].suggested_apps = await suggest_app_for_fsentry(desktop_items[i], {user: req.user}); - } - // is_shared - desktop_items[i].is_shared = await is_shared_with_anyone(desktop_items[i].id); - - // associated_app - if(desktop_items[i].associated_app_id){ - const app = await get_app({id: desktop_items[i].associated_app_id}) - - // remove some privileged information - delete app.id; - delete app.approved_for_listing; - delete app.approved_for_opening_items; - delete app.godmode; - delete app.owner_user_id; - // add to array - desktop_items[i].associated_app = app; - - }else{ - desktop_items[i].associated_app = {}; - } - - // remove associated_app_id since it's sensitive info - // delete desktop_items[i].associated_app_id; - } - // id is sesitive info - delete desktop_items[i].id; - delete desktop_items[i].user_id; - delete desktop_items[i].bucket; - desktop_items[i].path = _path.join('/', req.user.username, desktop_items[i].name) - } - } - } - } - - // send user object - response.send(Object.assign({ - username: req.user.username, - uuid: req.user.uuid, - email: req.user.email, - email_confirmed: req.user.email_confirmed - || req.user.username === 'admin', - requires_email_confirmation: req.user.requires_email_confirmation, - desktop_bg_url: req.user.desktop_bg_url, - desktop_bg_color: req.user.desktop_bg_color, - desktop_bg_fit: req.user.desktop_bg_fit, - is_temp: (req.user.password === null && req.user.email === null), - taskbar_items: await get_taskbar_items(req.user), - desktop_items: desktop_items, - referral_code: req.user.referral_code, - }, whoami_common({ is_user, user: req.user }))); -}); - -module.exports = app => { - app.use(WHOAMI_GET); - app.use(WHOAMI_POST); -}; \ No newline at end of file diff --git a/src/backend/src/services/PuterAPIService.js b/src/backend/src/services/PuterAPIService.js index 977d5ec32..d3b588fc7 100644 --- a/src/backend/src/services/PuterAPIService.js +++ b/src/backend/src/services/PuterAPIService.js @@ -91,7 +91,6 @@ class PuterAPIService extends BaseService { app.use(require('../routers/healthcheck')) app.use(require('../routers/test')) app.use(require('../routers/update-taskbar-items')) - require('../routers/whoami')(app); Endpoint({