mirror of
https://github.com/HeyPuter/puter.git
synced 2026-09-23 21:56:57 +00:00
dev: hook extensions into service event bus
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
const { AdvancedBase } = require("@heyputer/putility");
|
||||
const EmitterFeature = require("@heyputer/putility/src/features/EmitterFeature");
|
||||
const { Context } = require("./util/context");
|
||||
const { ExtensionService, ExtensionServiceState } = require("./ExtensionService");
|
||||
const { ExtensionServiceState } = require("./ExtensionService");
|
||||
|
||||
class Extension extends AdvancedBase {
|
||||
static FEATURES = [
|
||||
@@ -56,7 +56,9 @@ class Extension extends AdvancedBase {
|
||||
return;
|
||||
}
|
||||
|
||||
this.service = new ExtensionServiceState();
|
||||
this.service = new ExtensionServiceState({
|
||||
extension: this,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ class ExtensionServiceState extends AdvancedBase {
|
||||
constructor (...a) {
|
||||
super(...a);
|
||||
|
||||
this.extension = a[0].extension;
|
||||
|
||||
this.endpoints_ = [];
|
||||
}
|
||||
register_route_handler_ (path, handler, options = {}) {
|
||||
@@ -44,11 +46,23 @@ class ExtensionServiceState extends AdvancedBase {
|
||||
*/
|
||||
class ExtensionService extends BaseService {
|
||||
_construct () {
|
||||
this.extension = null;
|
||||
this.endpoints_ = [];
|
||||
}
|
||||
async _init (args) {
|
||||
this.state = args.state;
|
||||
|
||||
// Propagate all events not from extensions to `core.`
|
||||
const svc_event = this.services.get('event');
|
||||
svc_event.on_all((key, data, meta = {}) => {
|
||||
meta.from_outside_of_extension = true;
|
||||
this.state.extension.emit(`core.${key}`, data, meta);
|
||||
});
|
||||
|
||||
this.state.extension.on_all((key, data, meta) => {
|
||||
if ( meta.from_outside_of_extension ) return;
|
||||
|
||||
svc_event.emit(key, data, meta);
|
||||
});
|
||||
}
|
||||
|
||||
['__on_install.routes'] (_, { app }) {
|
||||
|
||||
@@ -74,7 +74,7 @@ router.post('/save_account', auth, express.json(), async (req, res, next)=>{
|
||||
const svc_cleanEmail = req.services.get('clean-email')
|
||||
const clean_email = svc_cleanEmail.clean(req.body.email);
|
||||
|
||||
if ( ! svc_cleanEmail.validate(clean_email) ) {
|
||||
if ( ! await svc_cleanEmail.validate(clean_email) ) {
|
||||
return res.status(400).send('This email domain is not allowed.');
|
||||
}
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ module.exports = eggspress(['/signup'], {
|
||||
const svc_cleanEmail = req.services.get('clean-email');
|
||||
const clean_email = svc_cleanEmail.clean(req.body.email);
|
||||
|
||||
if ( ! svc_cleanEmail.validate(clean_email) ) {
|
||||
if ( ! await svc_cleanEmail.validate(clean_email) ) {
|
||||
return res.status(400).send('This email domain is not allowed');
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ module.exports = {
|
||||
const svc_cleanEmail = req.services.get('clean-email');
|
||||
const clean_email = svc_cleanEmail.clean(new_email);
|
||||
|
||||
if ( ! svc_cleanEmail.validate(clean_email) ) {
|
||||
if ( ! await svc_cleanEmail.validate(clean_email) ) {
|
||||
throw APIError.create('email_not_allowed', undefined, {
|
||||
email: clean_email,
|
||||
});
|
||||
|
||||
@@ -101,7 +101,7 @@ class CleanEmailService extends BaseService {
|
||||
return eml.local + '@' + eml.domain;
|
||||
}
|
||||
|
||||
validate (email) {
|
||||
async validate (email) {
|
||||
email = this.clean(email);
|
||||
const config = this.global_config;
|
||||
|
||||
@@ -112,6 +112,12 @@ class CleanEmailService extends BaseService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const svc_event = this.services.get('event');
|
||||
const event = { allow: true, email };
|
||||
await svc_event.emit('email.validate', event);
|
||||
|
||||
if ( ! event.allow ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ module.exports = ({ decorators }) => ({
|
||||
// install the internal state
|
||||
const state = instance._.emitterFeature = {};
|
||||
state.listeners_ = {};
|
||||
state.global_listeners_ = [];
|
||||
state.callbackDecorators = decorators || [];
|
||||
|
||||
instance.emit = async (key, data, meta) => {
|
||||
@@ -22,6 +23,17 @@ module.exports = ({ decorators }) => ({
|
||||
const parts = key.split('.');
|
||||
|
||||
const promises = [];
|
||||
|
||||
for ( let i = 0 ; i < state.global_listeners_.length ; i++ ) {
|
||||
let callback = state.global_listeners_[i];
|
||||
for ( const decorator of state.callbackDecorators ) {
|
||||
callback = decorator(callback);
|
||||
}
|
||||
|
||||
promises.push(callback(key, data,
|
||||
{ ...meta, key }));
|
||||
}
|
||||
|
||||
for ( let i = 0; i < parts.length; i++ ) {
|
||||
const part = i === parts.length - 1
|
||||
? parts.join('.')
|
||||
@@ -42,7 +54,7 @@ module.exports = ({ decorators }) => ({
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return await Promise.all(promises);
|
||||
}
|
||||
|
||||
@@ -63,6 +75,10 @@ module.exports = ({ decorators }) => ({
|
||||
|
||||
return det;
|
||||
}
|
||||
|
||||
instance.on_all = (callback) => {
|
||||
state.global_listeners_.push(callback);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user