|
@@ -1155,201 +1155,6 @@ async function jwt_auth(req){
|
|
return ancestors;
|
|
return ancestors;
|
|
}
|
|
}
|
|
|
|
|
|
-// THIS LEGACY FUNCTION IS STILL IN USE
|
|
|
|
-// by: generate_system_fsentries
|
|
|
|
-// TODO: migrate generate_system_fsentries to use QuickMkdir
|
|
|
|
-async function mkdir(options){
|
|
|
|
- const fs = systemfs;
|
|
|
|
-
|
|
|
|
- debugger;
|
|
|
|
-
|
|
|
|
- const resolved_path = PathBuilder.resolve(options.path, { puterfs: true });
|
|
|
|
-
|
|
|
|
- const dirpath = _path.dirname(resolved_path);
|
|
|
|
- let target_name = _path.basename(resolved_path);
|
|
|
|
- const overwrite = options.overwrite ?? false;
|
|
|
|
- const dedupe_name = options.dedupe_name ?? false;
|
|
|
|
- const immutable = options.immutable ?? false;
|
|
|
|
- const return_id = options.return_id ?? false;
|
|
|
|
- const no_perm_check = options.no_perm_check ?? false;
|
|
|
|
-
|
|
|
|
- // make parent directories as needed
|
|
|
|
- const create_missing_parents = options.create_missing_parents ?? false;
|
|
|
|
-
|
|
|
|
- // hold a list of all parent directories created in the process
|
|
|
|
- let parent_dirs_created = [];
|
|
|
|
- let overwritten_uid;
|
|
|
|
-
|
|
|
|
- // target_name validation
|
|
|
|
- try{
|
|
|
|
- validate_fsentry_name(target_name)
|
|
|
|
- }catch(e){
|
|
|
|
- throw e.message;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // resolve dirpath to its fsentry
|
|
|
|
- let parent = await convert_path_to_fsentry(dirpath);
|
|
|
|
-
|
|
|
|
- // dirpath not found
|
|
|
|
- if(parent === false && !create_missing_parents)
|
|
|
|
- throw new Error("Target path not found");
|
|
|
|
- // create missing parent directories
|
|
|
|
- else if(parent === false && create_missing_parents){
|
|
|
|
- const dirs = _path.resolve('/', dirpath).split('/');
|
|
|
|
- let cur_path = '';
|
|
|
|
- for(let j=0; j < dirs.length; j++){
|
|
|
|
- if(dirs[j] === '')
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- cur_path += '/'+dirs[j];
|
|
|
|
- // skip creating '/[username]'
|
|
|
|
- if(j === 1)
|
|
|
|
- continue;
|
|
|
|
- try{
|
|
|
|
- let d = await mkdir(fs, {path: cur_path, user: options.user});
|
|
|
|
- d.path = cur_path;
|
|
|
|
- parent_dirs_created.push(d);
|
|
|
|
- }catch(e){
|
|
|
|
- console.log(`Skipped mkdir ${cur_path}`);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- // try setting parent again
|
|
|
|
- parent = await convert_path_to_fsentry(dirpath);
|
|
|
|
- if(parent === false)
|
|
|
|
- throw new Error("Target path not found");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // check permission
|
|
|
|
- if(!no_perm_check && !await chkperm(parent, options.user.id, 'write'))
|
|
|
|
- throw { code:`forbidden`, message: `permission denied.`};
|
|
|
|
-
|
|
|
|
- // check if a fsentry with the same name exists under this path
|
|
|
|
- const existing_fsentry = await convert_path_to_fsentry(_path.resolve('/', dirpath + '/' + target_name ));
|
|
|
|
-
|
|
|
|
- /** @type BaseDatabaseAccessService */
|
|
|
|
- const db = services.get('database').get(DB_WRITE, 'filesystem');
|
|
|
|
-
|
|
|
|
- // if trying to create a directory with an existing path and overwrite==false, throw an error
|
|
|
|
- if(!overwrite && !dedupe_name && existing_fsentry !== false){
|
|
|
|
- throw {
|
|
|
|
- code: 'path_exists',
|
|
|
|
- message:"A file/directory with the same path already exists.",
|
|
|
|
- entry_name: existing_fsentry.name,
|
|
|
|
- existing_fsentry: {
|
|
|
|
- name: existing_fsentry.name,
|
|
|
|
- uid: existing_fsentry.uuid,
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
- else if(overwrite && existing_fsentry){
|
|
|
|
- overwritten_uid = existing_fsentry.uuid;
|
|
|
|
- // check permission
|
|
|
|
- if(!await chkperm(existing_fsentry, options.user.id, 'write'))
|
|
|
|
- throw {code:`forbidden`, message: `permission denied.`};
|
|
|
|
- // delete existing dir
|
|
|
|
- await db.write(
|
|
|
|
- `DELETE FROM fsentries WHERE id = ? AND user_id = ?`,
|
|
|
|
- [
|
|
|
|
- //parent_uid
|
|
|
|
- existing_fsentry.uuid,
|
|
|
|
- //user_id
|
|
|
|
- options.user.id,
|
|
|
|
- ]);
|
|
|
|
- }
|
|
|
|
- // dedupe name, generate a new name until its unique
|
|
|
|
- else if(dedupe_name && existing_fsentry !== false){
|
|
|
|
- for( let i = 1; ; i++){
|
|
|
|
- let try_new_name = existing_fsentry.name + ' (' + i + ')';
|
|
|
|
- let check_dupe = await db.read(
|
|
|
|
- "SELECT `id` FROM `fsentries` WHERE `parent_uid` = ? AND name = ? LIMIT 1",
|
|
|
|
- [existing_fsentry.parent_uid, try_new_name]
|
|
|
|
- );
|
|
|
|
- if(check_dupe[0] === undefined){
|
|
|
|
- target_name = try_new_name;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // shrotcut?
|
|
|
|
- let shortcut_fsentry;
|
|
|
|
- if(options.shortcut_to){
|
|
|
|
- shortcut_fsentry = await uuid2fsentry(options.shortcut_to);
|
|
|
|
- if(shortcut_fsentry === false){
|
|
|
|
- throw ({ code:`not_found`, message: `shortcut_to not found.`})
|
|
|
|
- }else if(!parent.is_dir){
|
|
|
|
- throw ({ code:`not_dir`, message: `parent of shortcut_to must be a directory`})
|
|
|
|
- }else if(!await chkperm(shortcut_fsentry, options.user.id, 'read')){
|
|
|
|
- throw ({ code:`forbidden`, message: `shortcut_to permission denied.`})
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // current epoch
|
|
|
|
- const ts = Math.round(Date.now() / 1000)
|
|
|
|
- const uid = uuidv4();
|
|
|
|
-
|
|
|
|
- // record in db
|
|
|
|
- let user_id = (parent === null ? options.user.id : parent.user_id);
|
|
|
|
- const { insertId: mkdir_db_id } = await db.write(
|
|
|
|
- `INSERT INTO fsentries
|
|
|
|
- (uuid, parent_uid, user_id, name, is_dir, created, modified, immutable, shortcut_to, is_shortcut) VALUES
|
|
|
|
- ( ?, ?, ?, ?, true, ?, ?, ?, ?, ?)`,
|
|
|
|
- [
|
|
|
|
- //uuid
|
|
|
|
- uid,
|
|
|
|
- //parent_uid
|
|
|
|
- (parent === null) ? null : parent.uuid,
|
|
|
|
- //user_id
|
|
|
|
- user_id,
|
|
|
|
- //name
|
|
|
|
- target_name,
|
|
|
|
- //created
|
|
|
|
- ts,
|
|
|
|
- //modified
|
|
|
|
- ts,
|
|
|
|
- //immutable
|
|
|
|
- immutable,
|
|
|
|
- //shortcut_to,
|
|
|
|
- shortcut_fsentry ? shortcut_fsentry.id : null,
|
|
|
|
- //is_shortcut,
|
|
|
|
- shortcut_fsentry ? 1 : 0,
|
|
|
|
- ]
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- const ret_obj = {
|
|
|
|
- uid : uid,
|
|
|
|
- name: target_name,
|
|
|
|
- immutable: immutable,
|
|
|
|
- is_dir: true,
|
|
|
|
- path: options.path ?? false,
|
|
|
|
- dirpath: dirpath,
|
|
|
|
- is_shared: await is_shared_with_anyone(mkdir_db_id),
|
|
|
|
- overwritten_uid: overwritten_uid,
|
|
|
|
- shortcut_to: shortcut_fsentry ? shortcut_fsentry.uuid : null,
|
|
|
|
- shortcut_to_path: shortcut_fsentry ? await id2path(shortcut_fsentry.id) : null,
|
|
|
|
- parent_dirs_created: parent_dirs_created,
|
|
|
|
- original_client_socket_id: options.original_client_socket_id,
|
|
|
|
- };
|
|
|
|
- // add existing_fsentry if exists
|
|
|
|
- if(existing_fsentry){
|
|
|
|
- ret_obj.existing_fsentry ={
|
|
|
|
- name: existing_fsentry.name,
|
|
|
|
- uid: existing_fsentry.uuid,
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if(return_id)
|
|
|
|
- ret_obj.id = mkdir_db_id;
|
|
|
|
-
|
|
|
|
- // send realtime success msg to client
|
|
|
|
- let socketio = require('./socketio.js').getio();
|
|
|
|
- if(socketio){
|
|
|
|
- socketio.to(user_id).emit('item.added', ret_obj)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return ret_obj;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
function is_valid_uuid ( uuid ) {
|
|
function is_valid_uuid ( uuid ) {
|
|
let s = "" + uuid;
|
|
let s = "" + uuid;
|
|
s = s.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
|
|
s = s.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
|
|
@@ -1412,100 +1217,6 @@ async function app_name_exists(name){
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-// generates all the default files and directories a user needs,
|
|
|
|
-// generally used for a brand new account
|
|
|
|
-async function generate_system_fsentries(user){
|
|
|
|
- /** @type BaseDatabaseAccessService */
|
|
|
|
- const db = services.get('database').get(DB_WRITE, 'filesystem');
|
|
|
|
-
|
|
|
|
- //-------------------------------------------------------------
|
|
|
|
- // create root `/[username]/`
|
|
|
|
- //-------------------------------------------------------------
|
|
|
|
- const root_dir = await mkdir({
|
|
|
|
- path: '/' + user.username,
|
|
|
|
- user: user,
|
|
|
|
- immutable: true,
|
|
|
|
- no_perm_check: true,
|
|
|
|
- return_id: true,
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- // Normally, it is recommended to use mkdir() to create new folders,
|
|
|
|
- // but during signup this could result in multiple queries to the DB server
|
|
|
|
- // and for servers in remote regions such as Asia this could result in a
|
|
|
|
- // very long time for /signup to finish, sometimes up to 30-40 seconds!
|
|
|
|
- // by combining as many queries as we can into one and avoiding multiple back-and-forth
|
|
|
|
- // with the DB server, we can speed this process up significantly.
|
|
|
|
- const ts = Date.now()/1000;
|
|
|
|
-
|
|
|
|
- // Generate UUIDs for all the default folders and files
|
|
|
|
- let trash_uuid = uuidv4();
|
|
|
|
- let appdata_uuid = uuidv4();
|
|
|
|
- let desktop_uuid = uuidv4();
|
|
|
|
- let documents_uuid = uuidv4();
|
|
|
|
- let pictures_uuid = uuidv4();
|
|
|
|
- let videos_uuid = uuidv4();
|
|
|
|
- let public_uuid = uuidv4();
|
|
|
|
-
|
|
|
|
- const insert_res = await db.write(
|
|
|
|
- `INSERT INTO fsentries
|
|
|
|
- (uuid, parent_uid, user_id, name, path, is_dir, created, modified, immutable) VALUES
|
|
|
|
- ( ?, ?, ?, ?, ?, true, ?, ?, true),
|
|
|
|
- ( ?, ?, ?, ?, ?, true, ?, ?, true),
|
|
|
|
- ( ?, ?, ?, ?, ?, true, ?, ?, true),
|
|
|
|
- ( ?, ?, ?, ?, ?, true, ?, ?, true),
|
|
|
|
- ( ?, ?, ?, ?, ?, true, ?, ?, true),
|
|
|
|
- ( ?, ?, ?, ?, ?, true, ?, ?, true),
|
|
|
|
- ( ?, ?, ?, ?, ?, true, ?, ?, true)
|
|
|
|
- `,
|
|
|
|
- [
|
|
|
|
- // Trash
|
|
|
|
- trash_uuid, root_dir.uid, user.id, 'Trash', `/${user.username}/Trash`, ts, ts,
|
|
|
|
- // AppData
|
|
|
|
- appdata_uuid, root_dir.uid, user.id, 'AppData', `/${user.username}/AppData`, ts, ts,
|
|
|
|
- // Desktop
|
|
|
|
- desktop_uuid, root_dir.uid, user.id, 'Desktop', `/${user.username}/Desktop`, ts, ts,
|
|
|
|
- // Documents
|
|
|
|
- documents_uuid, root_dir.uid, user.id, 'Documents', `/${user.username}/Documents`, ts, ts,
|
|
|
|
- // Pictures
|
|
|
|
- pictures_uuid, root_dir.uid, user.id, 'Pictures', `/${user.username}/Pictures`, ts, ts,
|
|
|
|
- // Videos
|
|
|
|
- videos_uuid, root_dir.uid, user.id, 'Videos', `/${user.username}/Videos`, ts, ts,
|
|
|
|
- // Public
|
|
|
|
- public_uuid, root_dir.uid, user.id, 'Public', `/${user.username}/Public`, ts, ts,
|
|
|
|
- ]
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- // https://stackoverflow.com/a/50103616
|
|
|
|
- let trash_id = insert_res.insertId;
|
|
|
|
- let appdata_id = insert_res.insertId + 1;
|
|
|
|
- let desktop_id = insert_res.insertId + 2;
|
|
|
|
- let documents_id = insert_res.insertId + 3;
|
|
|
|
- let pictures_id = insert_res.insertId + 4;
|
|
|
|
- let videos_id = insert_res.insertId + 5;
|
|
|
|
- let public_id = insert_res.insertId + 6;
|
|
|
|
-
|
|
|
|
- // Asynchronously set the user's system folders uuids in database
|
|
|
|
- // This is for caching purposes, so we don't have to query the DB every time we need to access these folders
|
|
|
|
- // This is also possible because we know the user's system folders uuids will never change
|
|
|
|
-
|
|
|
|
- // TODO: pass to IIAFE manager to avoid unhandled promise rejection
|
|
|
|
- // (IIAFE manager doesn't exist yet, hence this is a TODO)
|
|
|
|
- db.write(
|
|
|
|
- `UPDATE user SET
|
|
|
|
- trash_uuid=?, appdata_uuid=?, desktop_uuid=?, documents_uuid=?, pictures_uuid=?, videos_uuid=?, public_uuid=?,
|
|
|
|
- trash_id=?, appdata_id=?, desktop_id=?, documents_id=?, pictures_id=?, videos_id=?, public_id=?
|
|
|
|
-
|
|
|
|
- WHERE id=?`,
|
|
|
|
- [
|
|
|
|
- trash_uuid, appdata_uuid, desktop_uuid, documents_uuid, pictures_uuid, videos_uuid, public_uuid,
|
|
|
|
- trash_id, appdata_id, desktop_id, documents_id, pictures_id, videos_id, public_id,
|
|
|
|
- user.id
|
|
|
|
- ]
|
|
|
|
- );
|
|
|
|
- invalidate_cached_user(user);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
function send_email_verification_code(email_confirm_code, email){
|
|
function send_email_verification_code(email_confirm_code, email){
|
|
const svc_email = Context.get('services').get('email');
|
|
const svc_email = Context.get('services').get('email');
|
|
svc_email.send_email({ email }, 'email_verification_code', {
|
|
svc_email.send_email({ email }, 'email_verification_code', {
|
|
@@ -1905,7 +1616,6 @@ module.exports = {
|
|
gen_public_token,
|
|
gen_public_token,
|
|
get_taskbar_items,
|
|
get_taskbar_items,
|
|
get_url_from_req,
|
|
get_url_from_req,
|
|
- generate_system_fsentries,
|
|
|
|
generate_random_str,
|
|
generate_random_str,
|
|
generate_random_username,
|
|
generate_random_username,
|
|
get_app,
|
|
get_app,
|
|
@@ -1926,7 +1636,6 @@ module.exports = {
|
|
is_specifically_uuidv4,
|
|
is_specifically_uuidv4,
|
|
is_valid_url,
|
|
is_valid_url,
|
|
jwt_auth,
|
|
jwt_auth,
|
|
- mkdir,
|
|
|
|
mv,
|
|
mv,
|
|
number_format,
|
|
number_format,
|
|
refresh_apps_cache,
|
|
refresh_apps_cache,
|