-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathtrait-wp-codebox-abilities-permissions.php
More file actions
171 lines (138 loc) · 5.52 KB
/
Copy pathtrait-wp-codebox-abilities-permissions.php
File metadata and controls
171 lines (138 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php
/**
* WP_Codebox_Abilities_Permissions implementation.
*
* @package WPCodebox
*/
defined( 'ABSPATH' ) || exit;
trait WP_Codebox_Abilities_Permissions {
public static function can_run_agent_task(): bool {
$allowed = current_user_can( 'manage_options' );
return (bool) apply_filters( 'wp_codebox_can_run_agent_task', $allowed );
}
/** @param mixed $input Ability input or request-like object. */
public static function can_create_browser_playground_session( mixed $input = null ): bool {
$allowed = current_user_can( 'manage_options' );
$filtered_allowed = (bool) apply_filters( 'wp_codebox_can_run_agent_task', $allowed );
if ( $filtered_allowed ) {
return true;
}
if ( $allowed ) {
return false;
}
$input = self::permission_input_array( $input );
if ( empty( $input ) ) {
return false;
}
$authorization = self::trusted_orchestrator_authorization( $input, self::BROWSER_SESSION_CREATE_SCOPE );
return true === ( $authorization['authorized'] ?? false );
}
/** @param mixed $input Ability input or request-like object. */
public static function can_persist_browser_artifact( mixed $input = null ): bool {
if ( current_user_can( 'manage_options' ) ) {
return true;
}
$input = self::permission_input_array( $input );
if ( empty( $input ) ) {
return false;
}
$authorization = self::trusted_orchestrator_authorization( $input, self::BROWSER_ARTIFACT_WRITE_SCOPE );
return true === ( $authorization['authorized'] ?? false );
}
/** @param mixed $input Ability input or request-like object. */
public static function can_import_artifact_bundle( mixed $input = null ): bool {
return self::can_persist_browser_artifact( $input );
}
/** @param mixed $input Ability input or request-like object. */
public static function can_request_browser_connector( mixed $input = null ): bool {
if ( current_user_can( 'manage_options' ) ) {
return true;
}
$input = self::permission_input_array( $input );
if ( empty( $input ) ) {
return false;
}
$authorization = self::trusted_orchestrator_authorization( $input, self::BROWSER_CONNECTOR_REQUEST_SCOPE );
return true === ( $authorization['authorized'] ?? false );
}
/** @param mixed $input Ability input or request-like object. @return array<string,mixed> */
private static function permission_input_array( mixed $input ): array {
if ( is_array( $input ) ) {
return $input;
}
if ( is_object( $input ) && is_callable( array( $input, 'get_json_params' ) ) ) {
$params = $input->get_json_params();
return is_array( $params ) ? $params : array();
}
if ( is_object( $input ) && is_callable( array( $input, 'get_params' ) ) ) {
$params = $input->get_params();
return is_array( $params ) ? $params : array();
}
return array();
}
/** @param array<string,mixed> $input Ability input. @return array<string,mixed> */
private static function browser_session_authorization( array $input ): array {
return self::trusted_orchestrator_authorization( $input, self::BROWSER_SESSION_CREATE_SCOPE );
}
/** @param array<string,mixed> $input Ability input. @return array<string,mixed> */
private static function trusted_orchestrator_authorization( array $input, string $required_scope ): array {
$authorization = is_array( $input['authorization'] ?? null ) ? $input['authorization'] : array();
$caller = trim( (string) ( $authorization['caller'] ?? '' ) );
$scope = trim( (string) ( $authorization['scope'] ?? '' ) );
$result = array_filter(
array(
'schema' => 'wp-codebox/trusted-orchestrator-authorization/v1',
'caller' => $caller,
'scope' => $scope,
'authorized' => false,
'method' => 'trusted-orchestrator',
'reason' => 'missing-authorization',
),
static fn( mixed $value ): bool => '' !== $value
);
if ( '' === $caller ) {
return $result;
}
if ( $required_scope !== $scope ) {
$result['reason'] = 'missing-scope';
return $result;
}
/**
* Filters trusted browser-session callers.
*
* Return either a map of caller ids to scopes, or a list of grant arrays:
* [ 'browser-client' => [ 'browser-session:create' ] ]
* [ [ 'caller' => 'browser-client', 'scopes' => [ 'browser-session:create' ] ] ]
*
* @param array<int|string,mixed> $trusted_callers Trusted caller grants.
* @param array<string,mixed> $authorization Explicit caller authorization payload.
* @param array<string,mixed> $input Ability input.
*/
$trusted_callers = apply_filters( 'wp_codebox_trusted_browser_session_callers', array(), $authorization, $input );
$trusted_callers = is_array( $trusted_callers ) ? $trusted_callers : array();
if ( self::trusted_browser_session_caller_has_scope( $trusted_callers, $caller, $scope ) ) {
$result['authorized'] = true;
$result['reason'] = 'trusted-caller-grant';
return $result;
}
$result['reason'] = 'caller-not-trusted';
return $result;
}
/** @param array<int|string,mixed> $trusted_callers Trusted caller grants. */
private static function trusted_browser_session_caller_has_scope( array $trusted_callers, string $caller, string $scope ): bool {
foreach ( $trusted_callers as $key => $grant ) {
if ( is_string( $key ) && $caller === $key ) {
$scopes = is_array( $grant ) ? $grant : array( $grant );
return in_array( $scope, array_map( 'strval', $scopes ), true );
}
if ( ! is_array( $grant ) || $caller !== (string) ( $grant['caller'] ?? '' ) ) {
continue;
}
$scopes = is_array( $grant['scopes'] ?? null ) ? $grant['scopes'] : array( $grant['scope'] ?? '' );
if ( in_array( $scope, array_map( 'strval', $scopes ), true ) ) {
return true;
}
}
return false;
}
}