Skip to content

Commit

Permalink
feat: add /share/file-by-username endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
KernelDeimos committed Jun 16, 2024
1 parent 1859668 commit 5d214c7
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 1 deletion.
6 changes: 6 additions & 0 deletions packages/backend/src/api/APIError.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,12 @@ module.exports = class APIError {
message: ({ identifier }) => `Entity not found: ${quot(identifier)}`,
},

// Share
'user_does_not_exist': {
status: 422,
message: ({ username }) => `The user ${quot(username)} does not exist.`
},

// Chat
// TODO: specifying these errors here might be a violation
// of separation of concerns. Services could register their
Expand Down
90 changes: 90 additions & 0 deletions packages/backend/src/routers/share.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const express = require('express');
const { Endpoint } = require('../util/expressutil');

const validator = require('validator');
const APIError = require('../api/APIError');
const { get_user } = require('../helpers');
const { Context } = require('../util/context');
const auth2 = require('../middleware/auth2');
const config = require('../config');

const { PermissionUtil } = require('../services/auth/PermissionService');

const uuidv4 = require('uuid').v4;

const router = express.Router();
router.use(auth2);

Endpoint({
route: '/file-by-username',
methods: ['POST'],
handler: async (req, res) => {
const svc_token = req.services.get('token');
const svc_email = req.services.get('email');
const svc_permission = req.services.get('permission');

console.log('which actor exists?',
req.actor,
Context.get('actor'))
const actor = Context.get('actor');

const username = req.body.username;
if ( ! (typeof username === 'string') ) {
throw APIError.create('field_invalid', null, {
key: 'username',
expected: 'string',
got: typeof username,
});
}

let path = req.body.path;
if ( ! (typeof path === 'string') ) {
throw APIError.create('field_invalid', null, {
key: 'path',
expected: 'string',
got: typeof path,
});
}

const access_level = req.body.access_level || 'write';
if ( ! ['read','write'].includes(access_level) ) {
throw APIError.create('field_invalid', null, {
key: 'access_level',
expected: '"read" or "write"',
});
}

const recipient = await get_user({ username });
if ( ! recipient ) {
throw APIError.create('user_does_not_exist', null, {
username
});
}

await svc_permission.grant_user_user_permission(
actor, username,
PermissionUtil.join('fs', path, access_level),
{}, {},
);

if ( path.startsWith('/') ) path = path.slice(1);
const link = `${config.origin}/show/${path}`;

const email_values = {
link,
susername: req.user.username,
...(recipient ? {
rusername: recipient.username,
} : {}),
};

const email_tmpl = recipient ?
'share_existing_user' : 'share_new_user';

await svc_email.send_email({ email: recipient.email }, email_tmpl, email_values);

res.send({});
},
}).attach(router);

module.exports = router;
12 changes: 11 additions & 1 deletion packages/backend/src/services/EmailService.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,17 @@ If this was not you, please contact [email protected] immediately.
<p>Sincerely,</p>
<p>Puter</p>
`
}
},
// TODO: revise email contents
'share_existing_user': {
subject: 'Puter share from {{susername}}',
html: `
<p>Hi there {{rusername}},</p>
<p>{{link}}</p>
<p>Sincerely,</p>
<p>Puter</p>
`
},
}

class Emailservice extends BaseService {
Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/services/PuterAPIService.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class PuterAPIService extends BaseService {
app.use(require('../routers/healthcheck'))
app.use(require('../routers/test'))
app.use(require('../routers/update-taskbar-items'))
app.use('/share', require('../routers/share'));
require('../routers/whoami')(app);

}
Expand Down
20 changes: 20 additions & 0 deletions packages/backend/src/services/auth/PermissionService.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,33 @@ class PermissionUtil {
}
return unescaped_str;
}

static escape_permission_component (component) {
let escaped_str = '';
for ( let i = 0 ; i < component.length ; i++ ) {
const c = component[i];
if ( c === ':' ) {
escaped_str += '\\C';
continue;
}
escaped_str += c;
}
return escaped_str;
}

static split (permission) {
return permission
.split(':')
.map(PermissionUtil.unescape_permission_component)
;
}

static join (...components) {
return components
.map(PermissionUtil.escape_permission_component)
.join(':')
;
}
}

class PermissionService extends BaseService {
Expand Down

0 comments on commit 5d214c7

Please sign in to comment.