set( 'settings', static function () { return new Settings(); } ); $c->set( 'limiter', static function ( Container $c ) { return new Security\RateLimiter( $c->get( 'settings' ) ); } ); $c->set( 'tokens', static function () { return new Auth\TokenRepository(); } ); $c->set( 'auth', static function ( Container $c ) { return new Authenticator( $c->get( 'settings' ), $c->get( 'tokens' ), $c->get( 'limiter' ) ); } ); $c->set( 'oauth', static function ( Container $c ) { return new Auth\OAuthServer( $c->get( 'settings' ), $c->get( 'tokens' ), $c->get( 'limiter' ), $c->get( 'auth' ) ); } ); $c->set( 'log', static function () { return new Tools\Log(); } ); $c->set( 'registry', static function ( Container $c ) { return new Tools\Registry( $c->get( 'settings' ), $c->get( 'limiter' ), $c->get( 'log' ) ); } ); $c->set( 'server', static function ( Container $c ) { return new Mcp\Server( $c ); } ); $this->container = $c; } /** * Services. */ public function container(): Container { return $this->container; } /** * Settings shortcut. */ public function settings(): Settings { return $this->container->get( 'settings' ); } /** * Hook everything up. */ public function boot(): void { Installer::maybe_migrate(); Authenticator::register_hooks(); Auth\AppPasswordPolicy::register( $this->container->get( 'settings' ) ); $this->container->get( 'server' )->register(); $this->container->get( 'oauth' )->register(); add_action( 'handymcp_daily_maintenance', function () { Installer::maintenance( $this->container->get( 'settings' ) ); } ); add_action( 'init', array( Integrations\WordPress::class, 'preview_hooks' ) ); // Sign every AI app out when the account they act for changes hands or loses access. $tokens = $this->container->get( 'tokens' ); $kill = static function ( $user_id, string $why ) use ( $tokens ) { $tokens->revoke_user( (int) $user_id, $why ); global $wpdb; $wpdb->delete( Database\Installer::table( 'sessions' ), array( 'user_id' => (int) $user_id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table of this plugin. }; add_action( 'after_password_reset', static function ( $user ) use ( $kill ) { $kill( $user->ID, 'password_reset' ); } ); add_action( 'profile_update', static function ( $user_id, $old ) use ( $kill ) { $new = get_userdata( $user_id ); if ( $new && $old && $new->user_pass !== $old->user_pass ) { $kill( $user_id, 'password_changed' ); } }, 10, 2 ); add_action( 'delete_user', static function ( $user_id ) use ( $kill ) { $kill( $user_id, 'user_deleted' ); } ); // Any role change re-checks the user against the allowed roles. $role_check = function ( $user_id ) use ( $kill ) { $user = get_userdata( (int) $user_id ); if ( $user && ! $this->container->get( 'auth' )->user_allowed( $user ) ) { $kill( (int) $user_id, 'role_changed' ); } }; foreach ( array( 'set_user_role', 'add_user_role', 'remove_user_role' ) as $role_hook ) { add_action( $role_hook, $role_check, 20, 1 ); } Admin\Diagnostics::boot(); Admin\ErrorReports::boot(); Support\Crash::boot(); Integrations\Media::boot(); if ( is_admin() ) { ( new Admin\Admin( $this->container ) )->register(); } } }