More utils, tidy, and activitypub.js added
This commit is contained in:
parent
127e9794ee
commit
6cea4269b2
|
@ -1,9 +1,47 @@
|
|||
const { WellKnownLocations } = require('./servers/content/web');
|
||||
const User = require('./user');
|
||||
const { Errors } = require('./enig_error');
|
||||
const UserProps = require('./user_property');
|
||||
|
||||
exports.buildSelfUrl = buildSelfUrl;
|
||||
exports.makeUserUrl = makeUserUrl;
|
||||
exports.webFingerProfileUrl = webFingerProfileUrl;
|
||||
exports.selfUrl = selfUrl;
|
||||
exports.userFromAccount = userFromAccount;
|
||||
|
||||
function buildSelfUrl(webServer, user, relPrefix) {
|
||||
function makeUserUrl(webServer, user, relPrefix) {
|
||||
return webServer.buildUrl(
|
||||
WellKnownLocations.Internal + `${relPrefix}${user.username}`
|
||||
);
|
||||
}
|
||||
|
||||
function webFingerProfileUrl(webServer, user) {
|
||||
return webServer.buildUrl(WellKnownLocations.Internal + `/wf/@${user.username}`);
|
||||
}
|
||||
|
||||
function selfUrl(webServer, user) {
|
||||
return makeUserUrl(webServer, user, '/ap/users/');
|
||||
}
|
||||
|
||||
function userFromAccount(accountName, cb) {
|
||||
User.getUserIdAndName(accountName, (err, userId) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
User.getUser(userId, (err, user) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
const accountStatus = user.getPropertyAsNumber(UserProps.AccountStatus);
|
||||
if (
|
||||
User.AccountStatus.disabled == accountStatus ||
|
||||
User.AccountStatus.inactive == accountStatus
|
||||
) {
|
||||
return cb(Errors.AccessDenied('Account disabled', ErrorReasons.Disabled));
|
||||
}
|
||||
|
||||
return cb(null, user);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -175,7 +175,7 @@ exports.getModule = class WebServerModule extends ServerModule {
|
|||
return nextModule(err);
|
||||
});
|
||||
} catch (e) {
|
||||
logger.log.error(e, 'Exception caught web handler!');
|
||||
Log.error(e, 'Exception caught web handler!');
|
||||
return nextModule(e);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
const WebHandlerModule = require('../../../web_handler_module');
|
||||
const {
|
||||
makeUserUrl,
|
||||
webFingerProfileUrl,
|
||||
selfUrl,
|
||||
userFromAccount,
|
||||
} = require('../../../activitypub_util');
|
||||
const UserProps = require('../../../user_property');
|
||||
const { Errors } = require('../../../enig_error');
|
||||
|
||||
exports.moduleInfo = {
|
||||
name: 'ActivityPub',
|
||||
desc: 'Provides ActivityPub support',
|
||||
author: 'NuSkooler, CognitiveGears',
|
||||
packageName: 'codes.l33t.enigma.web.handler.activitypub',
|
||||
};
|
||||
|
||||
exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
init(cb) {
|
||||
this.webServer = WebHandlerModule.getWebServer();
|
||||
if (!this.webServer) {
|
||||
return cb(Errors.UnexpectedState('Cannot access web server!'));
|
||||
}
|
||||
|
||||
this.webServer.addRoute({
|
||||
method: 'GET',
|
||||
path: /^\/_enig\/ap\/users\/.+$/,
|
||||
handler: this._selfUrlRequestHandler.bind(this),
|
||||
});
|
||||
|
||||
return cb(null);
|
||||
}
|
||||
|
||||
_selfUrlRequestHandler(req, resp) {
|
||||
const accept = req.headers['accept'] || '*/*';
|
||||
if (accept === 'application/activity+json') {
|
||||
return this._selfActorHandler(req, resp);
|
||||
}
|
||||
}
|
||||
|
||||
_selfActorHandler(req, resp) {
|
||||
const url = new URL(req.url, `https://${req.headers.host}`);
|
||||
const accountName = url.pathname.substring(url.pathname.lastIndexOf('/') + 1);
|
||||
|
||||
userFromAccount(accountName, (err, user) => {
|
||||
if (err) {
|
||||
return this._notFound(resp);
|
||||
}
|
||||
|
||||
const body = JSON.stringify({
|
||||
'@context': [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1',
|
||||
],
|
||||
id: selfUrl(this.webServer, user),
|
||||
type: 'Person',
|
||||
preferredUsername: user.username,
|
||||
name: user.getSanitizedName('real'),
|
||||
endpoints: {
|
||||
sharedInbox: 'TODO',
|
||||
},
|
||||
inbox: makeUserUrl(this.webServer, user, '/ap/users') + '/outbox',
|
||||
outbox: makeUserUrl(this.webServer, user, '/ap/users') + '/inbox',
|
||||
followers: makeUserUrl(this.webServer, user, '/ap/users') + '/followers',
|
||||
following: makeUserUrl(this.webServer, user, '/ap/users') + '/following',
|
||||
summary: user.getProperty(UserProps.AutoSignature) || '',
|
||||
url: webFingerProfileUrl(this.webServer, user),
|
||||
publicKey: {},
|
||||
|
||||
// :TODO: we can start to define BBS related stuff with the community perhaps
|
||||
});
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/activity+json',
|
||||
'Content-Length': body.length,
|
||||
};
|
||||
|
||||
resp.writeHead(200, headers);
|
||||
return resp.end(body);
|
||||
});
|
||||
}
|
||||
|
||||
_notFound(resp) {
|
||||
this.webServer.respondWithError(
|
||||
resp,
|
||||
404,
|
||||
'Resource not found',
|
||||
'Resource Not Found'
|
||||
);
|
||||
}
|
||||
};
|
|
@ -2,7 +2,11 @@ const WebHandlerModule = require('../../../web_handler_module');
|
|||
const Config = require('../../../config').get;
|
||||
const { Errors, ErrorReasons } = require('../../../enig_error');
|
||||
const { WellKnownLocations } = require('../web');
|
||||
const { buildSelfUrl } = require('../../../activitypub_util');
|
||||
const {
|
||||
selfUrl,
|
||||
webFingerProfileUrl,
|
||||
userFromAccount,
|
||||
} = require('../../../activitypub_util');
|
||||
|
||||
const _ = require('lodash');
|
||||
const User = require('../../../user');
|
||||
|
@ -44,7 +48,7 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
|||
|
||||
// we rely on the web server
|
||||
this.webServer = WebHandlerModule.getWebServer();
|
||||
if (!this.webServer || !this.webServer.isEnabled()) {
|
||||
if (!this.webServer) {
|
||||
return cb(Errors.UnexpectedState('Cannot access web server!'));
|
||||
}
|
||||
|
||||
|
@ -107,13 +111,10 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
|||
|
||||
const accountName = resource.substring(userPosition + 1);
|
||||
|
||||
this._getUser(accountName, resp, (err, user) => {
|
||||
userFromAccount(accountName, (err, user) => {
|
||||
if (err) {
|
||||
// |resp| already written to
|
||||
return Log.warn(
|
||||
{ error: err.message },
|
||||
`Profile request failed: ${req.url}`
|
||||
);
|
||||
Log.warn({ error: err.message }, `Profile request failed: ${req.url}`);
|
||||
return this._notFound(resp);
|
||||
}
|
||||
|
||||
this._getProfileTemplate((template, mimeType) => {
|
||||
|
@ -204,10 +205,10 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
|||
);
|
||||
}
|
||||
|
||||
this._getUser(accountName, resp, (err, user) => {
|
||||
userFromAccount(accountName, (err, user) => {
|
||||
if (err) {
|
||||
// |resp| already written to
|
||||
return Log.warn({ error: err.message }, `WebFinger failed: ${req.url}`);
|
||||
Log.warn({ error: err.message }, `WebFinger failed: ${req.url}`);
|
||||
return this._notFound(resp);
|
||||
}
|
||||
|
||||
const domain = this.webServer.getDomain();
|
||||
|
@ -233,9 +234,7 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
|||
}
|
||||
|
||||
_profileUrl(user) {
|
||||
return this.webServer.buildUrl(
|
||||
WellKnownLocations.Internal + `/wf/@${user.username}`
|
||||
);
|
||||
return webFingerProfileUrl(this.webServer, user);
|
||||
}
|
||||
|
||||
_profilePageLink(user) {
|
||||
|
@ -248,7 +247,7 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
|||
}
|
||||
|
||||
_selfUrl(user) {
|
||||
return buildSelfUrl(this.webServer, user, '/ap/users/');
|
||||
return selfUrl(this.webServer, user);
|
||||
}
|
||||
|
||||
// :TODO: only if ActivityPub is enabled
|
||||
|
@ -288,33 +287,4 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
|||
'Resource Not Found'
|
||||
);
|
||||
}
|
||||
|
||||
_getUser(accountName, resp, cb) {
|
||||
User.getUserIdAndName(accountName, (err, userId) => {
|
||||
if (err) {
|
||||
this._notFound(resp);
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
User.getUser(userId, (err, user) => {
|
||||
if (err) {
|
||||
this._notFound(resp);
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
const accountStatus = user.getPropertyAsNumber(UserProps.AccountStatus);
|
||||
if (
|
||||
User.AccountStatus.disabled == accountStatus ||
|
||||
User.AccountStatus.inactive == accountStatus
|
||||
) {
|
||||
this._notFound(resp);
|
||||
return cb(
|
||||
Errors.AccessDenied('Account disabled', ErrorReasons.Disabled)
|
||||
);
|
||||
}
|
||||
|
||||
return cb(null, user);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue