This commit is contained in:
Bryan Ashby 2023-01-08 13:26:52 -07:00
parent f86d9338a1
commit 2370185bcc
No known key found for this signature in database
GPG Key ID: C2C1B501E4EFD994
2 changed files with 319 additions and 321 deletions

View File

@ -29,13 +29,7 @@ module.exports = class Actor {
this.outbox = '';
this.following = '';
this.followers = '';
this.liked = '';
}
this.actorId = 0;
this.actorUrl = '';
this.properties = {}; // name:value
this.groups = []; // group membership(s)
}
isValid() {
@ -60,7 +54,10 @@ module.exports = class Actor {
return true;
}
static getRemoteActor(url, cb) {
// :TODO: create an Actor object from a local user
static fromLocalUser(userId, cb) {}
static fromRemoteUrl(url, cb) {
const headers = {
Accept: 'application/activity+json',
};
@ -106,360 +103,361 @@ module.exports = class Actor {
return new Actor(parsed);
}
create(cb) {
assert(0 === this.actorId);
// :TODO: persist()?
// create(cb) {
// assert(0 === this.actorId);
if (_.isEmpty(this.actorUrl)) {
return cb(Errors.Invalid('Blank actor url'));
}
// if (_.isEmpty(this.actorUrl)) {
// return cb(Errors.Invalid('Blank actor url'));
// }
const self = this;
// const self = this;
async.waterfall(
[
function beginTransaction(callback) {
return actorDb.beginTransaction(callback);
},
function createActorRec(trans, callback) {
trans.run(
`INSERT INTO actor (actor_url)
VALUES (?);`,
[self.actorUrl],
function inserted(err) {
// use classic function for |this|
if (err) {
return callback(err);
}
// async.waterfall(
// [
// function beginTransaction(callback) {
// return actorDb.beginTransaction(callback);
// },
// function createActorRec(trans, callback) {
// trans.run(
// `INSERT INTO actor (actor_url)
// VALUES (?);`,
// [self.actorUrl],
// function inserted(err) {
// // use classic function for |this|
// if (err) {
// return callback(err);
// }
self.actorId = this.lastID;
// self.actorId = this.lastID;
return callback(null, trans);
}
);
},
function saveAll(trans, callback) {
self.persistWithTransaction(trans, err => {
return callback(err, trans);
});
},
function sendEvent(trans, callback) {
Events.emit(Events.getSystemEvents().NewActor, {
actor: Object.assign({}, self, {}),
});
return callback(null, trans);
},
],
(err, trans) => {
if (trans) {
trans[err ? 'rollback' : 'commit'](transErr => {
return cb(err ? err : transErr);
});
} else {
return cb(err);
}
}
);
}
// return callback(null, trans);
// }
// );
// },
// function saveAll(trans, callback) {
// self.persistWithTransaction(trans, err => {
// return callback(err, trans);
// });
// },
// function sendEvent(trans, callback) {
// Events.emit(Events.getSystemEvents().NewActor, {
// actor: Object.assign({}, self, {}),
// });
// return callback(null, trans);
// },
// ],
// (err, trans) => {
// if (trans) {
// trans[err ? 'rollback' : 'commit'](transErr => {
// return cb(err ? err : transErr);
// });
// } else {
// return cb(err);
// }
// }
// );
// }
persistWithTransaction(trans, cb) {
assert(this.actorId > 0);
// persistWithTransaction(trans, cb) {
// assert(this.actorId > 0);
const self = this;
// const self = this;
async.series(
[
function saveProps(callback) {
self.persistProperties(self.properties, trans, err => {
return callback(err);
});
},
],
err => {
return cb(err);
}
);
}
// async.series(
// [
// function saveProps(callback) {
// self.persistProperties(self.properties, trans, err => {
// return callback(err);
// });
// },
// ],
// err => {
// return cb(err);
// }
// );
// }
static persistPropertyByActorId(actorId, propName, propValue, cb) {
actorDb.run(
`REPLACE INTO activitypub_actor_property (actor_id, prop_name, prop_value)
VALUES (?, ?, ?);`,
[actorId, propName, propValue],
err => {
if (cb) {
return cb(err, propValue);
}
}
);
}
// static persistPropertyByActorId(actorId, propName, propValue, cb) {
// actorDb.run(
// `REPLACE INTO activitypub_actor_property (actor_id, prop_name, prop_value)
// VALUES (?, ?, ?);`,
// [actorId, propName, propValue],
// err => {
// if (cb) {
// return cb(err, propValue);
// }
// }
// );
// }
setProperty(propName, propValue) {
this.properties[propName] = propValue;
}
// setProperty(propName, propValue) {
// this.properties[propName] = propValue;
// }
incrementProperty(propName, incrementBy) {
incrementBy = incrementBy || 1;
let newValue = parseInt(this.getProperty(propName));
if (newValue) {
newValue += incrementBy;
} else {
newValue = incrementBy;
}
this.setProperty(propName, newValue);
return newValue;
}
// incrementProperty(propName, incrementBy) {
// incrementBy = incrementBy || 1;
// let newValue = parseInt(this.getProperty(propName));
// if (newValue) {
// newValue += incrementBy;
// } else {
// newValue = incrementBy;
// }
// this.setProperty(propName, newValue);
// return newValue;
// }
getProperty(propName) {
return this.properties[propName];
}
// getProperty(propName) {
// return this.properties[propName];
// }
getPropertyAsNumber(propName) {
return parseInt(this.getProperty(propName), 10);
}
// getPropertyAsNumber(propName) {
// return parseInt(this.getProperty(propName), 10);
// }
persistProperty(propName, propValue, cb) {
// update live props
this.properties[propName] = propValue;
// persistProperty(propName, propValue, cb) {
// // update live props
// this.properties[propName] = propValue;
return Actor.persistPropertyByActorId(this.actorId, propName, propValue, cb);
}
// return Actor.persistPropertyByActorId(this.actorId, propName, propValue, cb);
// }
removeProperty(propName, cb) {
// update live
delete this.properties[propName];
// removeProperty(propName, cb) {
// // update live
// delete this.properties[propName];
actorDb.run(
`DELETE FROM activitypub_actor_property
WHERE activity_id = ? AND prop_name = ?;`,
[this.actorId, propName],
err => {
if (cb) {
return cb(err);
}
}
);
}
// actorDb.run(
// `DELETE FROM activitypub_actor_property
// WHERE activity_id = ? AND prop_name = ?;`,
// [this.actorId, propName],
// err => {
// if (cb) {
// return cb(err);
// }
// }
// );
// }
removeProperties(propNames, cb) {
async.each(
propNames,
(name, next) => {
return this.removeProperty(name, next);
},
err => {
if (cb) {
return cb(err);
}
}
);
}
// removeProperties(propNames, cb) {
// async.each(
// propNames,
// (name, next) => {
// return this.removeProperty(name, next);
// },
// err => {
// if (cb) {
// return cb(err);
// }
// }
// );
// }
persistProperties(properties, transOrDb, cb) {
if (!_.isFunction(cb) && _.isFunction(transOrDb)) {
cb = transOrDb;
transOrDb = actorDb;
}
// persistProperties(properties, transOrDb, cb) {
// if (!_.isFunction(cb) && _.isFunction(transOrDb)) {
// cb = transOrDb;
// transOrDb = actorDb;
// }
const self = this;
// const self = this;
// update live props
_.merge(this.properties, properties);
// // update live props
// _.merge(this.properties, properties);
const stmt = transOrDb.prepare(
`REPLACE INTO activitypub_actor_property (actor_id, prop_name, prop_value)
VALUES (?, ?, ?);`
);
// const stmt = transOrDb.prepare(
// `REPLACE INTO activitypub_actor_property (actor_id, prop_name, prop_value)
// VALUES (?, ?, ?);`
// );
async.each(
Object.keys(properties),
(propName, nextProp) => {
stmt.run(self.actorId, propName, properties[propName], err => {
return nextProp(err);
});
},
err => {
if (err) {
return cb(err);
}
// async.each(
// Object.keys(properties),
// (propName, nextProp) => {
// stmt.run(self.actorId, propName, properties[propName], err => {
// return nextProp(err);
// });
// },
// err => {
// if (err) {
// return cb(err);
// }
stmt.finalize(() => {
return cb(null);
});
}
);
}
// stmt.finalize(() => {
// return cb(null);
// });
// }
// );
// }
static getActor(actorId, cb) {
async.waterfall(
[
function fetchActorId(callback) {
Actor.getActorUrl(actorId, (err, actorUrl) => {
return callback(null, actorUrl);
});
},
function initProps(actorUrl, callback) {
Actor.loadProperties(actorId, (err, properties) => {
return callback(err, actorUrl, properties);
});
},
],
(err, actorUrl, properties) => {
const actor = new Actor();
actor.actorId = actorId;
actor.actorUrl = actorUrl;
actor.properties = properties;
// static getActor(actorId, cb) {
// async.waterfall(
// [
// function fetchActorId(callback) {
// Actor.getActorUrl(actorId, (err, actorUrl) => {
// return callback(null, actorUrl);
// });
// },
// function initProps(actorUrl, callback) {
// Actor.loadProperties(actorId, (err, properties) => {
// return callback(err, actorUrl, properties);
// });
// },
// ],
// (err, actorUrl, properties) => {
// const actor = new Actor();
// actor.actorId = actorId;
// actor.actorUrl = actorUrl;
// actor.properties = properties;
return cb(err, actor);
}
);
}
// return cb(err, actor);
// }
// );
// }
// FIXME
static getActorInfo(actorId, propsList, cb) {
if (!cb && _.isFunction(propsList)) {
cb = propsList;
propsList = [
ActorProps.Type,
ActorProps.PreferredUsername,
ActorProps.Name,
ActorProps.Summary,
ActorProps.IconUrl,
ActorProps.BannerUrl,
ActorProps.PublicKeyMain,
];
}
// // FIXME
// static getActorInfo(actorId, propsList, cb) {
// if (!cb && _.isFunction(propsList)) {
// cb = propsList;
// propsList = [
// ActorProps.Type,
// ActorProps.PreferredUsername,
// ActorProps.Name,
// ActorProps.Summary,
// ActorProps.IconUrl,
// ActorProps.BannerUrl,
// ActorProps.PublicKeyMain,
// ];
// }
async.waterfall(
[
callback => {
return Actor.getActorUrl(actorId, callback);
},
(actorUrl, callback) => {
Actor.loadProperties(actorId, { names: propsList }, (err, props) => {
return callback(
err,
Object.assign({}, props, { actor_url: actorUrl })
);
});
},
],
(err, actorProps) => {
if (err) {
return cb(err);
}
// async.waterfall(
// [
// callback => {
// return Actor.getActorUrl(actorId, callback);
// },
// (actorUrl, callback) => {
// Actor.loadProperties(actorId, { names: propsList }, (err, props) => {
// return callback(
// err,
// Object.assign({}, props, { actor_url: actorUrl })
// );
// });
// },
// ],
// (err, actorProps) => {
// if (err) {
// return cb(err);
// }
const actorInfo = {};
Object.keys(actorProps).forEach(key => {
actorInfo[_.camelCase(key)] = actorProps[key] || 'N/A';
});
// const actorInfo = {};
// Object.keys(actorProps).forEach(key => {
// actorInfo[_.camelCase(key)] = actorProps[key] || 'N/A';
// });
return cb(null, actorInfo);
}
);
}
// return cb(null, actorInfo);
// }
// );
// }
static getActorIdAndUrl(actorUrl, cb) {
actorDb.get(
`SELECT id, actor_url
FROM activitypub_actor
WHERE actor_url LIKE ?;`,
[actorUrl],
(err, row) => {
if (err) {
return cb(err);
}
// static getActorIdAndUrl(actorUrl, cb) {
// actorDb.get(
// `SELECT id, actor_url
// FROM activitypub_actor
// WHERE actor_url LIKE ?;`,
// [actorUrl],
// (err, row) => {
// if (err) {
// return cb(err);
// }
if (row) {
return cb(null, row.id, row.actor_url);
}
// if (row) {
// return cb(null, row.id, row.actor_url);
// }
return cb(Errors.DoesNotExist('No matching actorUrl'));
}
);
}
// return cb(Errors.DoesNotExist('No matching actorUrl'));
// }
// );
// }
static getActorUrl(actorId, cb) {
actorDb.get(
`SELECT actor_url
FROM activitypub_actor
WHERE id = ?;`,
[actorId],
(err, row) => {
if (err) {
return cb(err);
}
// static getActorUrl(actorId, cb) {
// actorDb.get(
// `SELECT actor_url
// FROM activitypub_actor
// WHERE id = ?;`,
// [actorId],
// (err, row) => {
// if (err) {
// return cb(err);
// }
if (row) {
return cb(null, row.actor_url);
}
// if (row) {
// return cb(null, row.actor_url);
// }
return cb(Errors.DoesNotExist('No matching actor ID'));
}
);
}
// return cb(Errors.DoesNotExist('No matching actor ID'));
// }
// );
// }
static loadProperties(actorId, options, cb) {
if (!cb && _.isFunction(options)) {
cb = options;
options = {};
}
// static loadProperties(actorId, options, cb) {
// if (!cb && _.isFunction(options)) {
// cb = options;
// options = {};
// }
let sql = `SELECT prop_name, prop_value
FROM activitypub_actor_property
WHERE actor_id = ?`;
// let sql = `SELECT prop_name, prop_value
// FROM activitypub_actor_property
// WHERE actor_id = ?`;
if (options.names) {
sql += ` AND prop_name IN("${options.names.join('","')}");`;
} else {
sql += ';';
}
// if (options.names) {
// sql += ` AND prop_name IN("${options.names.join('","')}");`;
// } else {
// sql += ';';
// }
let properties = {};
actorDb.each(
sql,
[actorId],
(err, row) => {
if (err) {
return cb(err);
}
properties[row.prop_name] = row.prop_value;
},
err => {
return cb(err, err ? null : properties);
}
);
}
// let properties = {};
// actorDb.each(
// sql,
// [actorId],
// (err, row) => {
// if (err) {
// return cb(err);
// }
// properties[row.prop_name] = row.prop_value;
// },
// err => {
// return cb(err, err ? null : properties);
// }
// );
// }
// :TODO: make this much more flexible - propValue should allow for case-insensitive compare, etc.
static getActorIdsWithProperty(propName, propValue, cb) {
let actorIds = [];
// // :TODO: make this much more flexible - propValue should allow for case-insensitive compare, etc.
// static getActorIdsWithProperty(propName, propValue, cb) {
// let actorIds = [];
actorDb.each(
`SELECT actor_id
FROM activitypub_actor_property
WHERE prop_name = ? AND prop_value = ?;`,
[propName, propValue],
(err, row) => {
if (row) {
actorIds.push(row.actor_id);
}
},
() => {
return cb(null, actorIds);
}
);
}
// actorDb.each(
// `SELECT actor_id
// FROM activitypub_actor_property
// WHERE prop_name = ? AND prop_value = ?;`,
// [propName, propValue],
// (err, row) => {
// if (row) {
// actorIds.push(row.actor_id);
// }
// },
// () => {
// return cb(null, actorIds);
// }
// );
// }
static getActorCount(cb) {
actorDb.get(
`SELECT count() AS actor_count
FROM activitypub_actor;`,
(err, row) => {
if (err) {
return cb(err);
}
return cb(null, row.actor_count);
}
);
}
// static getActorCount(cb) {
// actorDb.get(
// `SELECT count() AS actor_count
// FROM activitypub_actor;`,
// (err, row) => {
// if (err) {
// return cb(err);
// }
// return cb(null, row.actor_count);
// }
// );
// }
};

View File

@ -177,7 +177,7 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
return this.webServer.resourceNotFound(resp);
}
Actor.getRemoteActor(activity.actor, (err, actor) => {
Actor.fromRemoteUrl(activity.actor, (err, actor) => {
if (err) {
// :TODO: log, and probably should be inspecting |err|
return this.webServer.internalServerError(resp);