mirror of
https://github.com/HeyPuter/puter.git
synced 2025-01-23 06:00:21 +08:00
feat: add /sharelink/request endpoint
This commit is contained in:
parent
b0e067e4ae
commit
742f625309
@ -34,3 +34,15 @@ Comments beginning with `// track:`. See
|
||||
or there's a common behavior that should happen
|
||||
in between. The Sequence class is good for this so
|
||||
it might be a worthy migration.
|
||||
- `track: opposite condition of sibling`
|
||||
A sibling class, function, method, or other construct of
|
||||
source code has a boolean expression which always evaluates
|
||||
to the opposite of the one below this track comment.
|
||||
- `track: null check before processing`
|
||||
An object could be undefined or null, additional processing
|
||||
occurs after a null check, and the unprocessed object is not
|
||||
relevant to the rest of the code. If the code for obtaining
|
||||
the object and processing it is moved to a function outside,
|
||||
then the null check should result in a early return of null;
|
||||
this code with the track comment may have additional logic
|
||||
for the null/undefined case.
|
||||
|
@ -462,6 +462,11 @@ module.exports = class APIError {
|
||||
status: 422,
|
||||
message: 'Email must be confirmed to apply a share.',
|
||||
},
|
||||
'no_need_to_request': {
|
||||
status: 422,
|
||||
message: 'This share is already valid for this user; ' +
|
||||
'POST to /apply for access.'
|
||||
},
|
||||
'can_not_apply_to_this_user': {
|
||||
status: 422,
|
||||
message: 'This share can not be applied to this user.',
|
||||
|
@ -6,6 +6,7 @@ const { whatis } = require("../util/langutil");
|
||||
const { Actor, UserActorType } = require("./auth/Actor");
|
||||
const BaseService = require("./BaseService");
|
||||
const { DB_WRITE } = require("./database/consts");
|
||||
const { UsernameNotifSelector } = require("./NotificationService");
|
||||
|
||||
class ShareService extends BaseService {
|
||||
static MODULES = {
|
||||
@ -85,16 +86,16 @@ class ShareService extends BaseService {
|
||||
uid: share_uid,
|
||||
});
|
||||
|
||||
if ( ! share ) {
|
||||
throw APIError.create('share_expired');
|
||||
}
|
||||
|
||||
share.data = this.db.case({
|
||||
mysql: () => share.data,
|
||||
otherwise: () =>
|
||||
JSON.parse(share.data ?? '{}'),
|
||||
})();
|
||||
|
||||
if ( ! share ) {
|
||||
throw APIError.create('share_expired');
|
||||
}
|
||||
|
||||
const actor = Actor.adapt(req.actor ?? req.user);
|
||||
if ( ! actor ) {
|
||||
// this shouldn't happen; auth should catch it
|
||||
@ -137,6 +138,74 @@ class ShareService extends BaseService {
|
||||
});
|
||||
}
|
||||
}).attach(router);
|
||||
|
||||
Endpoint({
|
||||
route: '/request',
|
||||
methods: ['POST'],
|
||||
mw: [configurable_auth()],
|
||||
handler: async (req, res) => {
|
||||
const share_uid = req.body.uid;
|
||||
|
||||
const share = await svc_share.get_share({
|
||||
uid: share_uid,
|
||||
});
|
||||
|
||||
// track: null check before processing
|
||||
if ( ! share ) {
|
||||
throw APIError.create('share_expired');
|
||||
}
|
||||
|
||||
share.data = this.db.case({
|
||||
mysql: () => share.data,
|
||||
otherwise: () =>
|
||||
JSON.parse(share.data ?? '{}'),
|
||||
})();
|
||||
|
||||
const actor = Actor.adapt(req.actor ?? req.user);
|
||||
if ( ! actor ) {
|
||||
// this shouldn't happen; auth should catch it
|
||||
throw new Error('actor missing');
|
||||
}
|
||||
|
||||
// track: opposite condition of sibling
|
||||
// :: sibling: /apply endpoint
|
||||
if (
|
||||
actor.type.user.email_confirmed &&
|
||||
actor.type.user.email === share.recipient_email
|
||||
) {
|
||||
throw APIError.create('no_need_to_request');
|
||||
}
|
||||
|
||||
const issuer_user = await get_user({
|
||||
id: share.issuer_user_id,
|
||||
});
|
||||
|
||||
if ( ! issuer_user ) {
|
||||
throw APIError.create('share_expired');
|
||||
}
|
||||
|
||||
const svc_notification = this.services.get('notification');
|
||||
svc_notification.notify(
|
||||
UsernameNotifSelector(issuer_user.username),
|
||||
{
|
||||
source: 'sharing',
|
||||
title: `User ${actor.type.user.username} is ` +
|
||||
`trying to open a share you sent to ` +
|
||||
share.recipient_email,
|
||||
template: 'user-requesting-share',
|
||||
fields: {
|
||||
username: actor.type.user.username,
|
||||
intended_recipient: share.recipient_email,
|
||||
permissions: share.data.permissions,
|
||||
},
|
||||
}
|
||||
);
|
||||
res.json({
|
||||
$: 'api:status-report',
|
||||
status: 'success',
|
||||
});
|
||||
}
|
||||
}).attach(router);
|
||||
}
|
||||
|
||||
async get_share ({ uid }) {
|
||||
|
@ -34,6 +34,11 @@ class DriverService extends BaseService {
|
||||
this.interfaces = require('./interfaces');
|
||||
this.interface_to_implementation = {};
|
||||
}
|
||||
|
||||
_init () {
|
||||
const svc_registry = this.services.get('registry');
|
||||
svc_registry.register_collection('');
|
||||
}
|
||||
|
||||
register_driver (interface_name, implementation) {
|
||||
this.interface_to_implementation[interface_name] = implementation;
|
||||
|
Loading…
Reference in New Issue
Block a user