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 { 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(
|
return webServer.buildUrl(
|
||||||
WellKnownLocations.Internal + `${relPrefix}${user.username}`
|
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);
|
return nextModule(err);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.log.error(e, 'Exception caught web handler!');
|
Log.error(e, 'Exception caught web handler!');
|
||||||
return nextModule(e);
|
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 Config = require('../../../config').get;
|
||||||
const { Errors, ErrorReasons } = require('../../../enig_error');
|
const { Errors, ErrorReasons } = require('../../../enig_error');
|
||||||
const { WellKnownLocations } = require('../web');
|
const { WellKnownLocations } = require('../web');
|
||||||
const { buildSelfUrl } = require('../../../activitypub_util');
|
const {
|
||||||
|
selfUrl,
|
||||||
|
webFingerProfileUrl,
|
||||||
|
userFromAccount,
|
||||||
|
} = require('../../../activitypub_util');
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const User = require('../../../user');
|
const User = require('../../../user');
|
||||||
|
@ -44,7 +48,7 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
||||||
|
|
||||||
// we rely on the web server
|
// we rely on the web server
|
||||||
this.webServer = WebHandlerModule.getWebServer();
|
this.webServer = WebHandlerModule.getWebServer();
|
||||||
if (!this.webServer || !this.webServer.isEnabled()) {
|
if (!this.webServer) {
|
||||||
return cb(Errors.UnexpectedState('Cannot access web server!'));
|
return cb(Errors.UnexpectedState('Cannot access web server!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,13 +111,10 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
||||||
|
|
||||||
const accountName = resource.substring(userPosition + 1);
|
const accountName = resource.substring(userPosition + 1);
|
||||||
|
|
||||||
this._getUser(accountName, resp, (err, user) => {
|
userFromAccount(accountName, (err, user) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
// |resp| already written to
|
Log.warn({ error: err.message }, `Profile request failed: ${req.url}`);
|
||||||
return Log.warn(
|
return this._notFound(resp);
|
||||||
{ error: err.message },
|
|
||||||
`Profile request failed: ${req.url}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._getProfileTemplate((template, mimeType) => {
|
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) {
|
if (err) {
|
||||||
// |resp| already written to
|
Log.warn({ error: err.message }, `WebFinger failed: ${req.url}`);
|
||||||
return Log.warn({ error: err.message }, `WebFinger failed: ${req.url}`);
|
return this._notFound(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
const domain = this.webServer.getDomain();
|
const domain = this.webServer.getDomain();
|
||||||
|
@ -233,9 +234,7 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
_profileUrl(user) {
|
_profileUrl(user) {
|
||||||
return this.webServer.buildUrl(
|
return webFingerProfileUrl(this.webServer, user);
|
||||||
WellKnownLocations.Internal + `/wf/@${user.username}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_profilePageLink(user) {
|
_profilePageLink(user) {
|
||||||
|
@ -248,7 +247,7 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
_selfUrl(user) {
|
_selfUrl(user) {
|
||||||
return buildSelfUrl(this.webServer, user, '/ap/users/');
|
return selfUrl(this.webServer, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
// :TODO: only if ActivityPub is enabled
|
// :TODO: only if ActivityPub is enabled
|
||||||
|
@ -288,33 +287,4 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
|
||||||
'Resource Not Found'
|
'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