Refactored profile to be part of webfinger

This commit is contained in:
Nathan Byrd 2023-01-01 10:47:59 -06:00
parent 38098b46f1
commit e1b4c3e510
2 changed files with 72 additions and 143 deletions

View File

@ -1,122 +0,0 @@
const { ServerModule } = require('../../../server_module');
const Config = require('../../../config').get;
const { Errors } = require('../../../enig_error');
const WebServerPackageName = require('../web').moduleInfo.packageName;
const _ = require('lodash');
const User = require('../../../user');
const Log = require('../../../logger').log;
exports.moduleInfo = {
name: 'Profile',
desc: 'Displays a user profile',
author: 'CognitiveGears',
packageName: 'codes.l33t.enigma.web.handler.profile',
};
exports.getModule = class ProfileServerModule extends ServerModule {
constructor() {
super();
}
init(cb) {
if (!_.get(Config(), 'contentServers.web.handlers.profile.enabled')) {
return cb(null);
}
const { getServer } = require('../../../listening_server');
// we rely on the web server
this.webServer = getServer(WebServerPackageName);
if (!this.webServer || !this.webServer.instance.isEnabled()) {
return cb(Errors.UnexpectedState('Cannot access web server!'));
}
this.webServer.instance.addRoute({
method: 'GET',
path: /^\/profile\//,
handler: this._profileRequestHandler.bind(this),
});
return cb(null);
}
_profileRequestHandler(req, resp) {
const url = new URL(req.url, `https://${req.headers.host}`);
const resource = url.pathname;
if (!resource) {
return this.webServer.instance.respondWithError(
resp,
400,
'pathname is required',
'Missing "resource"'
);
}
this._getUser(resource, resp, (err, user, accountName) => {
if (err) {
// |resp| already written to
return Log.warn(
{ error: err.message },
`Profile request failed: ${req.url}`
);
}
// TODO: More user information here
const body = `
User name: ${accountName},
`;
const headers = {
'Content-Type': 'text/plain',
'Content-Length': body.length,
};
resp.writeHead(200, headers);
return resp.end(body);
});
}
_getUser(resource, resp, cb) {
const notFound = () => {
this.webServer.instance.respondWithError(
resp,
404,
'Resource not found',
'Resource Not Found'
);
};
// TODO: Handle URL escaped @ sign as well
const userPosition = resource.indexOf('@');
if (-1 == userPosition) {
notFound();
return cb(Errors.DoesNotExist('"@username" missing from path'));
}
const searchQuery = resource.substring(userPosition + 1);
if (_.isEmpty(searchQuery)) {
notFound();
return cb(Errors.DoesNotExist('Empty username in path'));
}
User.getUserIdAndName(searchQuery, (err, userId) => {
if (err) {
notFound();
return cb(err);
}
User.getUser(userId, (err, user) => {
if (err) {
notFound();
return cb(err);
}
return cb(null, user, searchQuery);
});
});
}
};

View File

@ -65,6 +65,12 @@ exports.getModule = class WebFingerServerModule extends WebHandlerModule {
handler: this._webFingerRequestHandler.bind(this), handler: this._webFingerRequestHandler.bind(this),
}); });
ws.addRoute({
method: 'GET',
path: /^\/_enig\/profile\//,
handler: this._profileRequestHandler.bind(this),
});
return cb(null); return cb(null);
} }
@ -72,6 +78,52 @@ exports.getModule = class WebFingerServerModule extends WebHandlerModule {
return this.webServer.instance; return this.webServer.instance;
} }
_profileRequestHandler(req, resp) {
const url = new URL(req.url, `https://${req.headers.host}`);
const resource = url.pathname;
if (_.isEmpty(resource)) {
return this.webServer.instance.respondWithError(
resp,
400,
'pathname is required',
'Missing "resource"'
);
}
// TODO: Handle URL escaped @ sign as well
const userPosition = resource.indexOf('@');
if (-1 == userPosition || userPosition == resource.length - 1) {
this._notFound(resp);
return Errors.DoesNotExist('"@username" missing from path');
}
const accountName = resource.substring(userPosition + 1);
this._getUser(accountName, resp, (err, user) => {
if (err) {
// |resp| already written to
return Log.warn(
{ error: err.message },
`Profile request failed: ${req.url}`
);
}
// TODO: More user information here
const body = `
User name: ${user.username},
`;
const headers = {
'Content-Type': 'text/plain',
'Content-Length': body.length,
};
resp.writeHead(200, headers);
return resp.end(body);
});
}
_webFingerRequestHandler(req, resp) { _webFingerRequestHandler(req, resp) {
const url = new URL(req.url, `https://${req.headers.host}`); const url = new URL(req.url, `https://${req.headers.host}`);
@ -85,7 +137,15 @@ exports.getModule = class WebFingerServerModule extends WebHandlerModule {
); );
} }
this._getUser(resource, resp, (err, user) => { const accountName = this._getAccountName(resource);
if (!accountName || accountName.length < 1) {
this._notFound(resp);
return Errors.DoesNotExist(
`Failed to parse "account name" for resource: ${resource}`
);
}
this._getUser(accountName, resp, (err, user) => {
if (err) { if (err) {
// |resp| already written to // |resp| already written to
return Log.warn({ error: err.message }, `WebFinger failed: ${req.url}`); return Log.warn({ error: err.message }, `WebFinger failed: ${req.url}`);
@ -163,35 +223,26 @@ exports.getModule = class WebFingerServerModule extends WebHandlerModule {
} }
} }
_getUser(resource, resp, cb) { _notFound(resp) {
const notFound = () => { this._webServer().respondWithError(
this._webServer().respondWithError( resp,
resp, 404,
404, 'Resource not found',
'Resource not found', 'Resource Not Found'
'Resource Not Found' );
); }
};
const accountName = this._getAccountName(resource);
if (!accountName || accountName.length < 1) {
notFound();
return cb(
Errors.DoesNotExist(
`Failed to parse "account name" for resource: ${resource}`
)
);
}
_getUser(accountName, resp, cb) {
User.getUserIdAndName(accountName, (err, userId) => { User.getUserIdAndName(accountName, (err, userId) => {
if (err) { if (err) {
notFound(); this._notFound(resp);
return cb(err); return cb(err);
} }
User.getUser(userId, (err, user) => { User.getUser(userId, (err, user) => {
if (err) { if (err) {
notFound(); this._notFound(resp);
return cb(err); return cb(err);
} }