Actor.fromLocalUser()
This commit is contained in:
parent
2370185bcc
commit
e5b2beffcf
|
@ -4,9 +4,15 @@
|
||||||
// ENiGMA½
|
// ENiGMA½
|
||||||
const actorDb = require('./database.js').dbs.actor;
|
const actorDb = require('./database.js').dbs.actor;
|
||||||
const { Errors } = require('./enig_error.js');
|
const { Errors } = require('./enig_error.js');
|
||||||
const Events = require('./events.js');
|
|
||||||
const { ActorProps } = require('./activitypub_actor_property');
|
const { ActorProps } = require('./activitypub_actor_property');
|
||||||
const { isValidLink } = require('./activitypub_util');
|
const UserProps = require('./user_property');
|
||||||
|
const {
|
||||||
|
webFingerProfileUrl,
|
||||||
|
makeUserUrl,
|
||||||
|
selfUrl,
|
||||||
|
isValidLink,
|
||||||
|
} = require('./activitypub_util');
|
||||||
|
const Log = require('./logger').log;
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
@ -54,8 +60,55 @@ module.exports = class Actor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// :TODO: create an Actor object from a local user
|
// :TODO: from a User object
|
||||||
static fromLocalUser(userId, cb) {}
|
static fromLocalUser(user, webServer, cb) {
|
||||||
|
const userSelfUrl = selfUrl(webServer, user);
|
||||||
|
|
||||||
|
const obj = {
|
||||||
|
'@context': [
|
||||||
|
'https://www.w3.org/ns/activitystreams',
|
||||||
|
'https://w3id.org/security/v1', // :TODO: add support
|
||||||
|
],
|
||||||
|
id: userSelfUrl,
|
||||||
|
type: 'Person',
|
||||||
|
preferredUsername: user.username,
|
||||||
|
name: user.getSanitizedName('real'),
|
||||||
|
endpoints: {
|
||||||
|
sharedInbox: 'TODO',
|
||||||
|
},
|
||||||
|
inbox: makeUserUrl(webServer, user, '/ap/users/') + '/inbox',
|
||||||
|
outbox: makeUserUrl(webServer, user, '/ap/users/') + '/outbox',
|
||||||
|
followers: makeUserUrl(webServer, user, '/ap/users/') + '/followers',
|
||||||
|
following: makeUserUrl(webServer, user, '/ap/users/') + '/following',
|
||||||
|
summary: user.getProperty(UserProps.AutoSignature) || '',
|
||||||
|
url: webFingerProfileUrl(webServer, user),
|
||||||
|
|
||||||
|
// :TODO: we can start to define BBS related stuff with the community perhaps
|
||||||
|
// attachment: [
|
||||||
|
// {
|
||||||
|
// name: 'SomeNetwork Address',
|
||||||
|
// type: 'PropertyValue',
|
||||||
|
// value: 'Mateo@21:1/121',
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
};
|
||||||
|
|
||||||
|
const publicKeyPem = user.getProperty(UserProps.PublicKeyMain);
|
||||||
|
if (!_.isEmpty(publicKeyPem)) {
|
||||||
|
obj.publicKey = {
|
||||||
|
id: userSelfUrl + '#main-key',
|
||||||
|
owner: userSelfUrl,
|
||||||
|
publicKeyPem,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
Log.warn(
|
||||||
|
{ username: user.username },
|
||||||
|
`No public key (${UserProps.PublicKeyMain}) for user "${user.username}"`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb(null, new Actor(obj));
|
||||||
|
}
|
||||||
|
|
||||||
static fromRemoteUrl(url, cb) {
|
static fromRemoteUrl(url, cb) {
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
@ -214,54 +214,6 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// :TODO: replace me with a fetch-and-cache in Actor, wrapped in e.g. Actor.fetch(url, options, cb)
|
|
||||||
_fetchActor(actorUrl, cb) {
|
|
||||||
const headers = {
|
|
||||||
Accept: 'application/activity+json',
|
|
||||||
};
|
|
||||||
https
|
|
||||||
.get(actorUrl, { headers }, res => {
|
|
||||||
if (res.statusCode !== 200) {
|
|
||||||
return cb(Errors.Invalid(`Bad HTTP status code: ${req.statusCode}`));
|
|
||||||
}
|
|
||||||
|
|
||||||
const contentType = res.headers['content-type'];
|
|
||||||
if (
|
|
||||||
!_.isString(contentType) ||
|
|
||||||
!contentType.startsWith('application/activity+json')
|
|
||||||
) {
|
|
||||||
return cb(Errors.Invalid(`Invalid Content-Type: ${contentType}`));
|
|
||||||
}
|
|
||||||
|
|
||||||
res.setEncoding('utf8');
|
|
||||||
let body = '';
|
|
||||||
res.on('data', data => {
|
|
||||||
body += data;
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on('end', () => {
|
|
||||||
try {
|
|
||||||
const actor = JSON.parse(body);
|
|
||||||
if (
|
|
||||||
!Array.isArray(actor['@context']) ||
|
|
||||||
actor['@context'][0] !==
|
|
||||||
'https://www.w3.org/ns/activitystreams'
|
|
||||||
) {
|
|
||||||
return cb(
|
|
||||||
Errors.Invalid('Invalid or missing Actor "@context"')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return cb(null, actor);
|
|
||||||
} catch (e) {
|
|
||||||
return cb(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.on('error', err => {
|
|
||||||
return cb(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_validateKeyId(keyId) {
|
_validateKeyId(keyId) {
|
||||||
if (!keyId) {
|
if (!keyId) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -275,82 +227,28 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
|
||||||
console.log(req);
|
console.log(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
// _populateKeyIdInfo(keyId, info) {
|
|
||||||
// if (!_.isString(keyId)) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const m = /^https?:\/\/.+\/(.+)#(main-key)$/.exec(keyId);
|
|
||||||
// if (!m || !m.length === 3) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// info.accountName = m[1];
|
|
||||||
// info.keyType = m[2];
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
_selfAsActorHandler(user, req, resp) {
|
_selfAsActorHandler(user, req, resp) {
|
||||||
this.log.trace(
|
this.log.trace(
|
||||||
{ username: user.username },
|
{ username: user.username },
|
||||||
`Serving ActivityPub Actor for "${user.username}"`
|
`Serving ActivityPub Actor for "${user.username}"`
|
||||||
);
|
);
|
||||||
|
|
||||||
const userSelfUrl = selfUrl(this.webServer, user);
|
Actor.fromLocalUser(user, this.webServer, (err, actor) => {
|
||||||
|
if (err) {
|
||||||
|
// :TODO: Log me
|
||||||
|
return this.webServer.internalServerError(resp);
|
||||||
|
}
|
||||||
|
|
||||||
// :TODO: something like: Actor.makeActor(...)
|
const body = JSON.stringify(actor);
|
||||||
const bodyJson = {
|
|
||||||
'@context': [
|
|
||||||
'https://www.w3.org/ns/activitystreams',
|
|
||||||
'https://w3id.org/security/v1',
|
|
||||||
],
|
|
||||||
id: userSelfUrl,
|
|
||||||
type: 'Person',
|
|
||||||
preferredUsername: user.username,
|
|
||||||
name: user.getSanitizedName('real'),
|
|
||||||
endpoints: {
|
|
||||||
sharedInbox: 'TODO',
|
|
||||||
},
|
|
||||||
inbox: makeUserUrl(this.webServer, user, '/ap/users/') + '/inbox',
|
|
||||||
outbox: makeUserUrl(this.webServer, user, '/ap/users/') + '/outbox',
|
|
||||||
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),
|
|
||||||
|
|
||||||
// :TODO: we can start to define BBS related stuff with the community perhaps
|
const headers = {
|
||||||
// attachment: [
|
'Content-Type': 'application/activity+json',
|
||||||
// {
|
'Content-Length': body.length,
|
||||||
// name: 'SomeNetwork Address',
|
|
||||||
// type: 'PropertyValue',
|
|
||||||
// value: 'Mateo@21:1/121',
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
};
|
|
||||||
|
|
||||||
const publicKeyPem = user.getProperty(UserProps.PublicKeyMain);
|
|
||||||
if (!_.isEmpty(publicKeyPem)) {
|
|
||||||
bodyJson['publicKey'] = {
|
|
||||||
id: userSelfUrl + '#main-key',
|
|
||||||
owner: userSelfUrl,
|
|
||||||
publicKeyPem,
|
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
this.log.warn(
|
|
||||||
{ username: user.username },
|
|
||||||
`No public key (${UserProps.PublicKeyMain}) for user "${user.username}"`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = JSON.stringify(bodyJson);
|
resp.writeHead(200, headers);
|
||||||
|
return resp.end(body);
|
||||||
const headers = {
|
});
|
||||||
'Content-Type': 'application/activity+json',
|
|
||||||
'Content-Length': body.length,
|
|
||||||
};
|
|
||||||
|
|
||||||
resp.writeHead(200, headers);
|
|
||||||
return resp.end(body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_standardSelfHandler(user, req, resp) {
|
_standardSelfHandler(user, req, resp) {
|
||||||
|
|
Loading…
Reference in New Issue