Remove need for WebServer in a lot of areas, oputil ap condition functional

* Getting domain, URLs, etc. for local web server do not need a web server instance themselves
* fix up oputil
This commit is contained in:
Bryan Ashby 2023-03-18 14:30:37 -06:00
parent e915527427
commit fb02fc599a
No known key found for this signature in database
GPG Key ID: C2C1B501E4EFD994
19 changed files with 187 additions and 191 deletions

View File

@ -115,14 +115,14 @@ module.exports = class Actor extends ActivityPubObject {
? user.getSanitizedName('real')
: user.username,
endpoints: {
sharedInbox: Endpoints.sharedInbox(webServer),
sharedInbox: Endpoints.sharedInbox(),
},
inbox: Endpoints.inbox(webServer, user),
outbox: Endpoints.outbox(webServer, user),
followers: Endpoints.followers(webServer, user),
following: Endpoints.following(webServer, user),
inbox: Endpoints.inbox(user),
outbox: Endpoints.outbox(user),
followers: Endpoints.followers(user),
following: Endpoints.following(user),
summary: user.getProperty(UserProps.AutoSignature) || '',
url: Endpoints.profile(webServer, user),
url: Endpoints.profile(user),
manuallyApprovesFollowers: userSettings.manuallyApprovesFollowers,
discoverable: userSettings.discoverable,
// :TODO: we can start to define BBS related stuff with the community perhaps

View File

@ -84,7 +84,7 @@ module.exports = class Collection extends ActivityPubObject {
}
static addFollower(owningUser, followingActor, webServer, ignoreDupes, cb) {
const collectionId = Endpoints.followers(webServer, owningUser);
const collectionId = Endpoints.followers(owningUser);
return Collection.addToCollection(
Collections.Followers,
owningUser,
@ -98,8 +98,7 @@ module.exports = class Collection extends ActivityPubObject {
}
static addFollowRequest(owningUser, requestingActor, webServer, ignoreDupes, cb) {
const collectionId =
Endpoints.makeUserUrl(webServer, owningUser) + 'follow-requests';
const collectionId = Endpoints.makeUserUrl(owningUser) + 'follow-requests';
return Collection.addToCollection(
Collections.FollowRequests,
owningUser,
@ -113,7 +112,7 @@ module.exports = class Collection extends ActivityPubObject {
}
static addFollowing(owningUser, followingActor, webServer, ignoreDupes, cb) {
const collectionId = Endpoints.following(webServer, owningUser);
const collectionId = Endpoints.following(owningUser);
return Collection.addToCollection(
Collections.Following,
owningUser,
@ -127,7 +126,7 @@ module.exports = class Collection extends ActivityPubObject {
}
static addOutboxItem(owningUser, outboxItem, isPrivate, webServer, ignoreDupes, cb) {
const collectionId = Endpoints.outbox(webServer, owningUser);
const collectionId = Endpoints.outbox(owningUser);
return Collection.addToCollection(
Collections.Outbox,
owningUser,
@ -141,7 +140,7 @@ module.exports = class Collection extends ActivityPubObject {
}
static addInboxItem(inboxItem, owningUser, webServer, ignoreDupes, cb) {
const collectionId = Endpoints.inbox(webServer, owningUser);
const collectionId = Endpoints.inbox(owningUser);
return Collection.addToCollection(
Collections.Inbox,
owningUser,
@ -498,8 +497,7 @@ module.exports = class Collection extends ActivityPubObject {
}
// e.g. http://somewhere.com/_enig/ap/users/NuSkooler/followers
const collectionId =
Endpoints.makeUserUrl(webServer, owningUser) + `/${collectionName}`;
const collectionId = Endpoints.makeUserUrl(owningUser) + `/${collectionName}`;
if (!page) {
return apDb.get(

View File

@ -1,4 +1,5 @@
const { WellKnownLocations } = require('../servers/content/web');
const { buildUrl } = require('../web_util');
// deps
const { v4: UUIDv4 } = require('uuid');
@ -16,46 +17,42 @@ exports.objectId = objectId;
const ActivityPubUsersPrefix = '/ap/users/';
function makeUserUrl(webServer, user, relPrefix = ActivityPubUsersPrefix) {
return webServer.buildUrl(
WellKnownLocations.Internal + `${relPrefix}${user.username}`
);
function makeUserUrl(user, relPrefix = ActivityPubUsersPrefix) {
return buildUrl(WellKnownLocations.Internal + `${relPrefix}${user.username}`);
}
function inbox(webServer, user) {
return makeUserUrl(webServer, user, ActivityPubUsersPrefix) + '/inbox';
function inbox(user) {
return makeUserUrl(user, ActivityPubUsersPrefix) + '/inbox';
}
function outbox(webServer, user) {
return makeUserUrl(webServer, user, ActivityPubUsersPrefix) + '/outbox';
function outbox(user) {
return makeUserUrl(user, ActivityPubUsersPrefix) + '/outbox';
}
function followers(webServer, user) {
return makeUserUrl(webServer, user, ActivityPubUsersPrefix) + '/followers';
function followers(user) {
return makeUserUrl(user, ActivityPubUsersPrefix) + '/followers';
}
function following(webServer, user) {
return makeUserUrl(webServer, user, ActivityPubUsersPrefix) + '/following';
function following(user) {
return makeUserUrl(user, ActivityPubUsersPrefix) + '/following';
}
function actorId(webServer, user) {
return makeUserUrl(webServer, user, ActivityPubUsersPrefix);
function actorId(user) {
return makeUserUrl(user, ActivityPubUsersPrefix);
}
function profile(webServer, user) {
return webServer.buildUrl(WellKnownLocations.Internal + `/wf/@${user.username}`);
function profile(user) {
return buildUrl(WellKnownLocations.Internal + `/wf/@${user.username}`);
}
function avatar(webServer, user, filename) {
return makeUserUrl(webServer, user, '/users/') + `/avatar/${filename}`;
function avatar(user, filename) {
return makeUserUrl(user, '/users/') + `/avatar/${filename}`;
}
function sharedInbox(webServer) {
return webServer.buildUrl(WellKnownLocations.Internal + '/ap/shared-inbox');
function sharedInbox() {
return buildUrl(WellKnownLocations.Internal + '/ap/shared-inbox');
}
function objectId(webServer, objectType) {
return webServer.buildUrl(
WellKnownLocations.Internal + `/ap/${UUIDv4()}/${objectType}`
);
function objectId(objectType) {
return buildUrl(WellKnownLocations.Internal + `/ap/${UUIDv4()}/${objectType}`);
}

View File

@ -84,7 +84,7 @@ module.exports = class ActivityPubObject {
}
static makeObjectId(webServer, objectType) {
return Endpoints.objectId(webServer, objectType);
return Endpoints.objectId(objectType);
}
sendTo(inboxEndpoint, fromUser, webServer, cb) {
@ -103,7 +103,7 @@ module.exports = class ActivityPubObject {
},
sign: {
key: privateKey,
keyId: Endpoints.actorId(webServer, fromUser) + '#main-key',
keyId: Endpoints.actorId(fromUser) + '#main-key',
authorizationHeaderName: 'Signature',
headers: HttpSignatureSignHeaders,
},

View File

@ -6,6 +6,7 @@ const { stripAnsiControlCodes } = require('../string_util');
const { WellKnownRecipientFields } = require('./const');
const Log = require('../logger').log;
const { getWebDomain } = require('../web_util');
const Endpoints = require('./endpoint');
// deps
const _ = require('lodash');
@ -30,6 +31,7 @@ exports.userNameFromSubject = userNameFromSubject;
exports.userNameToSubject = userNameToSubject;
exports.extractMessageMetadata = extractMessageMetadata;
exports.recipientIdsFromObject = recipientIdsFromObject;
exports.prepareLocalUserAsActor = prepareLocalUserAsActor;
// :TODO: more info in default
// this profile template is the *default* for both WebFinger
@ -262,3 +264,43 @@ function recipientIdsFromObject(obj) {
return Array.from(new Set(ids));
}
function prepareLocalUserAsActor(user, options = { force: false }, cb) {
const hasProps =
user.getProperty(UserProps.ActivityPubActorId) &&
user.getProperty(UserProps.PrivateActivityPubSigningKey) &&
user.getProperty(UserProps.PublicActivityPubSigningKey);
if (hasProps && !options.force) {
return cb(null);
}
const actorId = Endpoints.actorId(user);
user.setProperty(UserProps.ActivityPubActorId, actorId);
user.updateActivityPubKeyPairProperties(err => {
if (err) {
return cb(err);
}
user.generateNewRandomAvatar((err, outPath) => {
if (err) {
return err;
}
// :TODO: fetch over +op default overrides here, e.g. 'enabled'
const apSettings = ActivityPubSettings.fromUser(user);
const filename = paths.basename(outPath);
const avatarUrl = Endpoints.avatar(user, filename);
apSettings.image = avatarUrl;
apSettings.icon = avatarUrl;
user.setProperty(UserProps.AvatarImageUrl, avatarUrl);
user.setProperty(UserProps.ActivityPubSettings, JSON.stringify(apSettings));
return cb(null);
});
});
}

View File

@ -17,6 +17,7 @@ const webServerPackageName = require('./servers/content/web.js').moduleInfo.pack
const Events = require('./events.js');
const UserProps = require('./user_property.js');
const SysProps = require('./system_menu_method.js');
const { buildUrl } = require('./web_util');
// deps
const hashids = require('hashids/cjs');
@ -202,11 +203,11 @@ class FileAreaWebAccess {
buildSingleFileTempDownloadLink(client, fileEntry, hashId) {
hashId = hashId || this.getSingleFileHashId(client, fileEntry);
return this.webServer.instance.buildUrl(`${Config().fileBase.web.path}${hashId}`);
return buildUrl(`${Config().fileBase.web.path}${hashId}`);
}
buildBatchArchiveTempDownloadLink(client, hashId) {
return this.webServer.instance.buildUrl(`${Config().fileBase.web.path}${hashId}`);
return buildUrl(`${Config().fileBase.web.path}${hashId}`);
}
getExistingTempDownloadServeItem(client, fileEntry, cb) {

View File

@ -5,7 +5,6 @@ const {
initConfigAndDatabases,
} = require('./oputil_common');
const getHelpFor = require('./oputil_help.js').getHelpFor;
const UserProps = require('../user_property');
const { Errors } = require('../enig_error');
// deps
@ -48,24 +47,30 @@ function applyAction(username, actionFunc, cb) {
});
}
function conditionSingleUser(User, username, userId, settings, cb) {
const { userNameToSubject } = require('../activitypub/util');
const subject = userNameToSubject(username);
function conditionSingleUser(user, cb) {
const { userNameToSubject, prepareLocalUserAsActor } = require('../activitypub/util');
const subject = userNameToSubject(user.username);
if (!subject) {
return cb(Errors.General(`Failed to get subject for ${username}`));
return cb(Errors.General(`Failed to get subject for ${user.username}`));
}
console.info(`Conditioning ${username} (${userId}) -> ${subject}...`);
console.info(`Conditioning ${user.username} (${user.userId}) -> ${subject}...`);
prepareLocalUserAsActor(user, { force: argv.force }, err => {
if (err) {
return cb(err);
}
User.persistPropertyByUserId(userId, UserProps.ActivityPubSettings, settings, err => {
return cb(err);
user.persistProperties(user.properties, err => {
if (err) {
return cb(err);
}
});
});
}
function actionConditionAllUsers(_, cb) {
const User = require('../../core/user.js');
const ActivityPubSettings = require('../activitypub/settings');
const defaultSettings = JSON.stringify(new ActivityPubSettings());
User.getUserList({}, (err, userList) => {
if (err) {
@ -75,13 +80,12 @@ function actionConditionAllUsers(_, cb) {
async.each(
userList,
(entry, next) => {
conditionSingleUser(
User,
entry.userName,
entry.userId,
defaultSettings,
next
);
User.getUser(entry.userId, (err, user) => {
if (err) {
return next(err);
}
return conditionSingleUser(user, next);
});
},
err => {
return cb(err);
@ -90,13 +94,6 @@ function actionConditionAllUsers(_, cb) {
});
}
function actionConditionUser(user, cb) {
const User = require('../../core/user.js');
const ActivityPubSettings = require('../activitypub/settings');
const defaultSettings = JSON.stringify(new ActivityPubSettings());
return conditionSingleUser(User, user.username, user.userId, defaultSettings, cb);
}
function validateActivityPub() {
//
// Web Server, and ActivityPub both must be enabled
@ -116,7 +113,7 @@ function validateActivityPub() {
function conditionUser(action, username) {
return applyAction(
username,
'*' === username ? actionConditionAllUsers : actionConditionUser,
'*' === username ? actionConditionAllUsers : conditionSingleUser,
err => {
if (err) {
console.error(err.message);

View File

@ -10,6 +10,7 @@ const async = require('async');
const inq = require('inquirer');
const fs = require('fs');
const hjson = require('hjson');
const log = require('../../core/logger');
const packageJson = require('../../package.json');
@ -81,6 +82,7 @@ function initConfigAndDatabases(cb) {
initConfig(callback);
},
function initDb(callback) {
log.init();
db.initializeDatabases(callback);
},
function initArchiveUtil(callback) {

View File

@ -215,6 +215,9 @@ Actions:
condition USERNAME Condition user with system ActivityPub defaults
Instead of an actual USERNAME, the '*' character may be substituted.
condition arguments:
--force Force condition; overrides any existing settings
`,
});

View File

@ -299,7 +299,7 @@ exports.getModule = class ActivityPubScannerTosser extends MessageScanTossModule
}
_collectFollowersSharedInboxEndpoints(localUser, cb) {
const localFollowersEndpoint = Endpoints.followers(this._webServer(), localUser);
const localFollowersEndpoint = Endpoints.followers(localUser);
Collection.followers(localFollowersEndpoint, 'all', (err, collection) => {
if (err) {

View File

@ -5,7 +5,6 @@ const Config = require('../../config.js').get;
const { Errors } = require('../../enig_error.js');
const { loadModulesForCategory, moduleCategories } = require('../../module_util');
const WebHandlerModule = require('../../web_handler_module');
const { getWebDomain } = require('../../web_util');
// deps
const http = require('http');
@ -90,53 +89,6 @@ exports.getModule = class WebServerModule extends ServerModule {
return this.log;
}
getDomain() {
return getWebDomain();
}
baseUrl() {
const config = Config();
const overridePrefix = _.get(config, 'contentServers.web.overrideUrlPrefix');
if (overridePrefix) {
return overridePrefix;
}
let schema;
let port;
if (config.contentServers.web.https.enabled) {
schema = 'https://';
port =
443 === config.contentServers.web.https.port
? ''
: `:${config.contentServers.web.https.port}`;
} else {
schema = 'http://';
port =
80 === config.contentServers.web.http.port
? ''
: `:${config.contentServers.web.http.port}`;
}
return `${schema}${config.contentServers.web.domain}${port}`;
}
fullUrl(req) {
const base = this.baseUrl();
return new URL(`${base}${req.url}`);
}
buildUrl(pathAndQuery) {
//
// Create a URL such as
// https://l33t.codes:44512/ + |pathAndQuery|
//
// Prefer HTTPS over HTTP. Be explicit about the port
// only if non-standard. Allow users to override full prefix in config.
//
const base = this.baseUrl();
return `${base}${pathAndQuery}`;
}
isEnabled() {
return this.enableHttp || this.enableHttps;
}

View File

@ -4,8 +4,8 @@ const {
getUserProfileTemplatedBody,
DefaultProfileTemplate,
getActorId,
prepareLocalUserAsActor,
} = require('../../../activitypub/util');
const Endpoints = require('../../../activitypub/endpoint');
const {
ActivityStreamMediaType,
WellKnownActivity,
@ -21,15 +21,14 @@ const Note = require('../../../activitypub/note');
const EnigAssert = require('../../../enigma_assert');
const Message = require('../../../message');
const Events = require('../../../events');
const UserProps = require('../../../user_property');
const { Errors } = require('../../../enig_error');
const { getFullUrl } = require('../../../web_util');
// deps
const _ = require('lodash');
const enigma_assert = require('../../../enigma_assert');
const httpSignature = require('http-signature');
const async = require('async');
const paths = require('path');
exports.moduleInfo = {
name: 'ActivityPub',
@ -175,7 +174,7 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
_selfUrlRequestHandler(req, resp) {
this.log.trace({ url: req.url }, 'Request for "self"');
let actorId = this.webServer.fullUrl(req).toString();
let actorId = getFullUrl(req).toString();
let sendActor = false;
if (actorId.endsWith('.json')) {
sendActor = true;
@ -783,7 +782,7 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
_localUserFromCollectionEndpoint(req, collectionName, cb) {
// turn a collection URL to a Actor ID
let actorId = this.webServer.fullUrl(req).toString();
let actorId = getFullUrl(req).toString();
const suffix = `/${collectionName}`;
if (actorId.endsWith(suffix)) {
actorId = actorId.slice(0, -suffix.length);
@ -986,7 +985,7 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
return this.webServer.resourceNotFound(resp);
}
const url = this.webServer.fullUrl(req);
const url = getFullUrl(req);
const page = url.searchParams.get('page');
const collectionId = url.toString();
@ -1037,7 +1036,7 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
_singlePublicNoteGetHandler(req, resp) {
this.log.debug({ url: req.url }, 'Request for "Note"');
const noteId = this.webServer.fullUrl(req).toString();
const noteId = getFullUrl(req).toString();
Note.fromPublicNoteId(noteId, (err, note) => {
if (err) {
return this.webServer.internalServerError(resp, err);
@ -1180,42 +1179,6 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
`Preparing ActivityPub settings for "${user.username}"`
);
const actorId = Endpoints.actorId(this.webServer, user);
user.setProperty(UserProps.ActivityPubActorId, actorId);
user.updateActivityPubKeyPairProperties(err => {
if (err) {
return cb(err);
}
user.generateNewRandomAvatar((err, outPath) => {
if (err) {
this.log.warn(
{
username: user.username,
userId: user.userId,
error: err.message,
},
`Failed to generate random avatar for "${user.username}"`
);
}
// :TODO: fetch over +op default overrides here, e.g. 'enabled'
const apSettings = ActivityPubSettings.fromUser(user);
const filename = paths.basename(outPath);
const avatarUrl = Endpoints.avatar(this.webServer, user, filename);
apSettings.image = avatarUrl;
apSettings.icon = avatarUrl;
user.setProperty(
UserProps.ActivityPubSettings,
JSON.stringify(apSettings)
);
return cb(null);
});
});
return prepareLocalUserAsActor(user, cb);
}
};

View File

@ -6,6 +6,7 @@ const packageJson = require('../../../../package.json');
const StatLog = require('../../../stat_log');
const SysProps = require('../../../system_property');
const SysLogKeys = require('../../../system_log');
const { getBaseUrl, getWebDomain } = require('../../../web_util');
// deps
const moment = require('moment');
@ -30,7 +31,7 @@ exports.getModule = class NodeInfo2WebHandler extends WebHandlerModule {
this.log = webServer.logger().child({ webHandler: 'NodeInfo2' });
const domain = this.webServer.getDomain();
const domain = getWebDomain();
if (!domain) {
return cb(Errors.UnexpectedState('Web server does not have "domain" set'));
}
@ -65,7 +66,7 @@ exports.getModule = class NodeInfo2WebHandler extends WebHandlerModule {
const nodeInfo = {
version: '1.0',
server: {
baseUrl: this.webServer.baseUrl(),
baseUrl: getBaseUrl(),
name: config.general.boardName,
software: 'ENiGMA½ Bulletin Board Software',
version: packageJson.version,

View File

@ -2,6 +2,7 @@ const WebHandlerModule = require('../../../web_handler_module');
const { Errors } = require('../../../enig_error');
const EngiAssert = require('../../../enigma_assert');
const Config = require('../../../config').get;
const { getFullUrl, getWebDomain } = require('../../../web_util');
// deps
const paths = require('path');
@ -28,7 +29,7 @@ exports.getModule = class SystemGeneralWebHandler extends WebHandlerModule {
this.log = webServer.logger().child({ webHandler: 'SysGeneral' });
const domain = this.webServer.getDomain();
const domain = getWebDomain();
if (!domain) {
return cb(Errors.UnexpectedState('Web server does not have "domain" set'));
}
@ -44,7 +45,7 @@ exports.getModule = class SystemGeneralWebHandler extends WebHandlerModule {
}
_avatarGetHandler(req, resp) {
const url = this.webServer.fullUrl(req);
const url = getFullUrl(req);
const filename = paths.basename(url.pathname);
if (!filename) {
return this.webServer.fileNotFound(resp);

View File

@ -11,6 +11,7 @@ const EngiAssert = require('../../../enigma_assert');
const User = require('../../../user');
const UserProps = require('../../../user_property');
const ActivityPubSettings = require('../../../activitypub/settings');
const { getFullUrl, buildUrl, getWebDomain } = require('../../../web_util');
// deps
const _ = require('lodash');
@ -38,7 +39,7 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
this.log = webServer.logger().child({ webHandler: 'WebFinger' });
const domain = this.webServer.getDomain();
const domain = getWebDomain();
if (!domain) {
return cb(Errors.UnexpectedState('Web server does not have "domain" set'));
}
@ -49,15 +50,9 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
new RegExp(`^acct:(.+)@${domain}$`),
// profile page
// https://webfinger.net/rel/profile-page/
new RegExp(
`^${this.webServer.buildUrl(WellKnownLocations.Internal + '/wf/@')}(.+)$`
),
new RegExp(`^${buildUrl(WellKnownLocations.Internal + '/wf/@')}(.+)$`),
// self URL
new RegExp(
`^${this.webServer.buildUrl(
WellKnownLocations.Internal + '/ap/users/'
)}(.+)$`
),
new RegExp(`^${buildUrl(WellKnownLocations.Internal + '/ap/users/')}(.+)$`),
];
this.webServer.addRoute({
@ -78,7 +73,7 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
_profileRequestHandler(req, resp) {
// Profile requests do not have an Actor ID available
const profileQuery = this.webServer.fullUrl(req).toString();
const profileQuery = getFullUrl(req).toString();
const accountName = this._getAccountName(profileQuery);
if (!accountName) {
this.log.warn(
@ -135,7 +130,7 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
}
_webFingerRequestHandler(req, resp) {
const url = this.webServer.fullUrl(req);
const url = getFullUrl(req);
const resource = url.searchParams.get('resource');
if (!resource) {
return this.webServer.respondWithError(
@ -161,11 +156,10 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
return this.webServer.resourceNotFound(resp);
}
const domain = this.webServer.getDomain();
const domain = getWebDomain();
const body = JSON.stringify({
subject: `acct:${localUser.username}@${domain}`,
aliases: [this._profileUrl(localUser), this._userActorId(localUser)],
aliases: [Endpoints.profile(localUser), Endpoints.actorId(localUser)],
links: [
this._profilePageLink(localUser),
this._selfLink(localUser),
@ -218,12 +212,8 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
});
}
_profileUrl(user) {
return Endpoints.profile(this.webServer, user);
}
_profilePageLink(user) {
const href = this._profileUrl(user);
const href = Endpoints.profile(user);
return {
rel: 'http://webfinger.net/rel/profile-page',
type: 'text/plain',
@ -232,12 +222,12 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
}
_userActorId(user) {
return Endpoints.actorId(this.webServer, user);
return Endpoints.actorId(user);
}
// :TODO: only if ActivityPub is enabled
_selfLink(user) {
const href = this._userActorId(user);
const href = Endpoints.actorId(user);
return {
rel: 'self',
type: 'application/activity+json',
@ -249,7 +239,7 @@ exports.getModule = class WebFingerWebHandler extends WebHandlerModule {
_subscribeLink() {
return {
rel: 'http://ostatus.org/schema/1.0/subscribe',
template: this.webServer.buildUrl(
template: buildUrl(
WellKnownLocations.Internal + '/ap/authorize_interaction?uri={uri}'
),
};

View File

@ -17,6 +17,7 @@ const { sendMail } = require('./email.js');
const UserProps = require('./user_property.js');
const Log = require('./logger.js').log;
const { getConnectionByUserId } = require('./client_connections.js');
const { buildUrl } = require('./web_util');
// deps
const async = require('async');
@ -75,8 +76,7 @@ module.exports = class User2FA_OTPWebRegister {
});
},
(token, textTemplate, htmlTemplate, callback) => {
const webServer = getWebServer();
const registerUrl = webServer.instance.buildUrl(
const registerUrl = buildUrl(
WellKnownLocations.Internal +
`/2fa/enable_2fa_otp?token=${token}&otpType=${otpType}`
);
@ -172,7 +172,7 @@ module.exports = class User2FA_OTPWebRegister {
return User2FA_OTPWebRegister.accessDenied(webServer, resp);
}
const postUrl = webServer.instance.buildUrl(
const postUrl = buildUrl(
WellKnownLocations.Internal + '/2fa/enable_2fa_otp'
);
const config = Config();

View File

@ -70,6 +70,8 @@ module.exports = {
PublicActivityPubSigningKey: 'public_key_activitypub_sign_rsa_pem', // RSA public key for ActivityPub signing
PrivateActivityPubSigningKey: 'private_key_activitypub_sign_rsa_pem', // RSA private key (corresponding to PublicActivityPubSigningKey)
AvatarImageUrl: 'user_avatar_image',
ActivityPubSettings: 'activitypub_settings', // JSON object (above); see ActivityPubSettings in activitypub/settings.js
ActivityPubActorId: 'activitypub_actor_id', // Actor ID representing this users
};

View File

@ -12,6 +12,7 @@ const userDb = require('./database.js').dbs.user;
const getISOTimestampString = require('./database.js').getISOTimestampString;
const Log = require('./logger.js').log;
const UserProps = require('./user_property.js');
const { buildUrl } = require('./web_util');
// deps
const async = require('async');
@ -121,7 +122,7 @@ class WebPasswordReset {
function buildAndSendEmail(user, textTemplate, htmlTemplate, callback) {
const sendMail = require('./email.js').sendMail;
const resetUrl = webServer.instance.buildUrl(
const resetUrl = buildUrl(
WellKnownLocations.Internal +
`/sec/reset_password?token=${
user.properties[UserProps.EmailPwResetToken]
@ -271,7 +272,7 @@ class WebPasswordReset {
);
}
const postResetUrl = webServer.instance.buildUrl(
const postResetUrl = buildUrl(
WellKnownLocations.Internal + '/sec/reset_password'
);

View File

@ -4,6 +4,9 @@ const Config = require('./config').get;
const { get, isString } = require('lodash');
exports.getWebDomain = getWebDomain;
exports.getBaseUrl = getBaseUrl;
exports.getFullUrl = getFullUrl;
exports.buildUrl = buildUrl;
function getWebDomain() {
const config = Config();
@ -15,3 +18,46 @@ function getWebDomain() {
return config.contentServers.web.domain;
}
function getBaseUrl() {
const config = Config();
const overridePrefix = get(config, 'contentServers.web.overrideUrlPrefix');
if (overridePrefix) {
return overridePrefix;
}
let schema;
let port;
if (config.contentServers.web.https.enabled) {
schema = 'https://';
port =
443 === config.contentServers.web.https.port
? ''
: `:${config.contentServers.web.https.port}`;
} else {
schema = 'http://';
port =
80 === config.contentServers.web.http.port
? ''
: `:${config.contentServers.web.http.port}`;
}
return `${schema}${config.contentServers.web.domain}${port}`;
}
function getFullUrl(req) {
const base = getBaseUrl();
return new URL(`${base}${req.url}`);
}
function buildUrl(pathAndQuery) {
//
// Create a URL such as
// https://l33t.codes:44512/ + |pathAndQuery|
//
// Prefer HTTPS over HTTP. Be explicit about the port
// only if non-standard. Allow users to override full prefix in config.
//
const base = getBaseUrl();
return `${base}${pathAndQuery}`;
}