1
0

whoami.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * Copyright (C) 2024 Puter Technologies Inc.
  3. *
  4. * This file is part of Puter.
  5. *
  6. * Puter is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published
  8. * by the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. "use strict"
  20. const express = require('express');
  21. const { get_taskbar_items, is_shared_with_anyone, suggest_app_for_fsentry, get_app, get_descendants, id2uuid } = require('../helpers');
  22. const auth = require('../middleware/auth.js');
  23. const fs = require('../middleware/fs.js');
  24. const _path = require('path');
  25. const eggspress = require('../api/eggspress');
  26. const { Context } = require('../util/context');
  27. const { UserActorType } = require('../services/auth/Actor');
  28. // -----------------------------------------------------------------------//
  29. // GET /whoami
  30. // -----------------------------------------------------------------------//
  31. const WHOAMI_GET = eggspress('/whoami', {
  32. subdomain: 'api',
  33. auth2: true,
  34. allowedMethods: ['GET'],
  35. }, async (req, res, next) => {
  36. const actor = Context.get('actor');
  37. if ( ! actor ) {
  38. throw Error('actor not found in context');
  39. }
  40. const is_user = actor.type instanceof UserActorType;
  41. // send user object
  42. const details = {
  43. username: req.user.username,
  44. uuid: req.user.uuid,
  45. email: req.user.email,
  46. email_confirmed: req.user.email_confirmed,
  47. requires_email_confirmation: req.user.requires_email_confirmation,
  48. desktop_bg_url: req.user.desktop_bg_url,
  49. desktop_bg_color: req.user.desktop_bg_color,
  50. desktop_bg_fit: req.user.desktop_bg_fit,
  51. is_temp: (req.user.password === null && req.user.email === null),
  52. taskbar_items: await get_taskbar_items(req.user),
  53. referral_code: req.user.referral_code,
  54. otp: !! req.user.otp_enabled,
  55. ...(req.new_token ? { token: req.token } : {})
  56. };
  57. // Get whoami values from other services
  58. const svc_whoami = req.services.get('whoami');
  59. const provider_details = await svc_whoami.get_details({ user: req.user });
  60. Object.assign(details, provider_details);
  61. if ( ! is_user ) {
  62. // When apps call /whoami they should not see these attributes
  63. // delete details.username;
  64. // delete details.uuid;
  65. delete details.email;
  66. delete details.desktop_bg_url;
  67. delete details.desktop_bg_color;
  68. delete details.desktop_bg_fit;
  69. delete details.taskbar_items;
  70. delete details.token;
  71. }
  72. res.send(details);
  73. })
  74. // -----------------------------------------------------------------------//
  75. // POST /whoami
  76. // -----------------------------------------------------------------------//
  77. const WHOAMI_POST = new express.Router();
  78. WHOAMI_POST.post('/whoami', auth, fs, express.json(), async (req, response, next)=>{
  79. // check subdomain
  80. if(require('../helpers').subdomain(req) !== 'api') {
  81. return;
  82. }
  83. const actor = Context.get('actor');
  84. if ( ! actor ) {
  85. throw Error('actor not found in context');
  86. }
  87. const is_user = actor.type instanceof UserActorType;
  88. if ( ! is_user ) {
  89. throw Error('actor is not a user');
  90. }
  91. let desktop_items = [];
  92. // check if user asked for desktop items
  93. if(req.query.return_desktop_items === 1 || req.query.return_desktop_items === '1' || req.query.return_desktop_items === 'true'){
  94. // by cached desktop id
  95. if(req.user.desktop_id){
  96. // TODO: Check if used anywhere, maybe remove
  97. // eslint-disable-next-line no-undef
  98. desktop_items = await db.read(
  99. `SELECT * FROM fsentries
  100. WHERE user_id = ? AND parent_uid = ?`,
  101. [req.user.id, await id2uuid(req.user.desktop_id)]
  102. )
  103. }
  104. // by desktop path
  105. else{
  106. desktop_items = await get_descendants(req.user.username +'/Desktop', req.user, 1, true);
  107. }
  108. // clean up desktop items and add some extra information
  109. if(desktop_items.length > 0){
  110. if(desktop_items.length > 0){
  111. for (let i = 0; i < desktop_items.length; i++) {
  112. if(desktop_items[i].id !== null){
  113. // suggested_apps for files
  114. if(!desktop_items[i].is_dir){
  115. desktop_items[i].suggested_apps = await suggest_app_for_fsentry(desktop_items[i], {user: req.user});
  116. }
  117. // is_shared
  118. desktop_items[i].is_shared = await is_shared_with_anyone(desktop_items[i].id);
  119. // associated_app
  120. if(desktop_items[i].associated_app_id){
  121. const app = await get_app({id: desktop_items[i].associated_app_id})
  122. // remove some privileged information
  123. delete app.id;
  124. delete app.approved_for_listing;
  125. delete app.approved_for_opening_items;
  126. delete app.godmode;
  127. delete app.owner_user_id;
  128. // add to array
  129. desktop_items[i].associated_app = app;
  130. }else{
  131. desktop_items[i].associated_app = {};
  132. }
  133. // remove associated_app_id since it's sensitive info
  134. // delete desktop_items[i].associated_app_id;
  135. }
  136. // id is sesitive info
  137. delete desktop_items[i].id;
  138. delete desktop_items[i].user_id;
  139. delete desktop_items[i].bucket;
  140. desktop_items[i].path = _path.join('/', req.user.username, desktop_items[i].name)
  141. }
  142. }
  143. }
  144. }
  145. // send user object
  146. response.send({
  147. username: req.user.username,
  148. uuid: req.user.uuid,
  149. email: req.user.email,
  150. email_confirmed: req.user.email_confirmed,
  151. requires_email_confirmation: req.user.requires_email_confirmation,
  152. desktop_bg_url: req.user.desktop_bg_url,
  153. desktop_bg_color: req.user.desktop_bg_color,
  154. desktop_bg_fit: req.user.desktop_bg_fit,
  155. is_temp: (req.user.password === null && req.user.email === null),
  156. taskbar_items: await get_taskbar_items(req.user),
  157. desktop_items: desktop_items,
  158. referral_code: req.user.referral_code,
  159. });
  160. });
  161. module.exports = app => {
  162. app.use(WHOAMI_GET);
  163. app.use(WHOAMI_POST);
  164. };