mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-04 08:30:39 +00:00
dev: remove legacy whoami and use extension
This commit is contained in:
@@ -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');
|
||||
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
"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);
|
||||
};
|
||||
@@ -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({
|
||||
|
||||
Reference in New Issue
Block a user