@@ -9,6 +9,7 @@ export type CommandAuthorization = {
99 providerId ?: ChannelId ;
1010 ownerList : string [ ] ;
1111 senderId ?: string ;
12+ senderIsOwner : boolean ;
1213 isAuthorizedSender : boolean ;
1314 from ?: string ;
1415 to ?: string ;
@@ -83,6 +84,47 @@ function normalizeAllowFromEntry(params: {
8384 return normalized . filter ( ( entry ) => entry . trim ( ) . length > 0 ) ;
8485}
8586
87+ function resolveOwnerAllowFromList ( params : {
88+ dock ?: ChannelDock ;
89+ cfg : OpenClawConfig ;
90+ accountId ?: string | null ;
91+ providerId ?: ChannelId ;
92+ } ) : string [ ] {
93+ const raw = params . cfg . commands ?. ownerAllowFrom ;
94+ if ( ! Array . isArray ( raw ) || raw . length === 0 ) {
95+ return [ ] ;
96+ }
97+ const filtered : string [ ] = [ ] ;
98+ for ( const entry of raw ) {
99+ const trimmed = String ( entry ?? "" ) . trim ( ) ;
100+ if ( ! trimmed ) {
101+ continue ;
102+ }
103+ const separatorIndex = trimmed . indexOf ( ":" ) ;
104+ if ( separatorIndex > 0 ) {
105+ const prefix = trimmed . slice ( 0 , separatorIndex ) ;
106+ const channel = normalizeAnyChannelId ( prefix ) ;
107+ if ( channel ) {
108+ if ( params . providerId && channel !== params . providerId ) {
109+ continue ;
110+ }
111+ const remainder = trimmed . slice ( separatorIndex + 1 ) . trim ( ) ;
112+ if ( remainder ) {
113+ filtered . push ( remainder ) ;
114+ }
115+ continue ;
116+ }
117+ }
118+ filtered . push ( trimmed ) ;
119+ }
120+ return formatAllowFromList ( {
121+ dock : params . dock ,
122+ cfg : params . cfg ,
123+ accountId : params . accountId ,
124+ allowFrom : filtered ,
125+ } ) ;
126+ }
127+
86128function resolveSenderCandidates ( params : {
87129 dock ?: ChannelDock ;
88130 providerId ?: ChannelId ;
@@ -141,22 +183,31 @@ export function resolveCommandAuthorization(params: {
141183 accountId : ctx . AccountId ,
142184 allowFrom : Array . isArray ( allowFromRaw ) ? allowFromRaw : [ ] ,
143185 } ) ;
186+ const ownerAllowFromList = resolveOwnerAllowFromList ( {
187+ dock,
188+ cfg,
189+ accountId : ctx . AccountId ,
190+ providerId,
191+ } ) ;
144192 const allowAll =
145193 allowFromList . length === 0 || allowFromList . some ( ( entry ) => entry . trim ( ) === "*" ) ;
146194
147- const ownerCandidates = allowAll ? [ ] : allowFromList . filter ( ( entry ) => entry !== "*" ) ;
148- if ( ! allowAll && ownerCandidates . length === 0 && to ) {
195+ const ownerCandidatesForCommands = allowAll ? [ ] : allowFromList . filter ( ( entry ) => entry !== "*" ) ;
196+ if ( ! allowAll && ownerCandidatesForCommands . length === 0 && to ) {
149197 const normalizedTo = normalizeAllowFromEntry ( {
150198 dock,
151199 cfg,
152200 accountId : ctx . AccountId ,
153201 value : to ,
154202 } ) ;
155203 if ( normalizedTo . length > 0 ) {
156- ownerCandidates . push ( ...normalizedTo ) ;
204+ ownerCandidatesForCommands . push ( ...normalizedTo ) ;
157205 }
158206 }
159- const ownerList = Array . from ( new Set ( ownerCandidates ) ) ;
207+ const explicitOwners = ownerAllowFromList . filter ( ( entry ) => entry !== "*" ) ;
208+ const ownerList = Array . from (
209+ new Set ( explicitOwners . length > 0 ? explicitOwners : ownerCandidatesForCommands ) ,
210+ ) ;
160211
161212 const senderCandidates = resolveSenderCandidates ( {
162213 dock,
@@ -170,16 +221,25 @@ export function resolveCommandAuthorization(params: {
170221 const matchedSender = ownerList . length
171222 ? senderCandidates . find ( ( candidate ) => ownerList . includes ( candidate ) )
172223 : undefined ;
224+ const matchedCommandOwner = ownerCandidatesForCommands . length
225+ ? senderCandidates . find ( ( candidate ) => ownerCandidatesForCommands . includes ( candidate ) )
226+ : undefined ;
173227 const senderId = matchedSender ?? senderCandidates [ 0 ] ;
174228
175229 const enforceOwner = Boolean ( dock ?. commands ?. enforceOwnerForCommands ) ;
176- const isOwner = ! enforceOwner || allowAll || ownerList . length === 0 || Boolean ( matchedSender ) ;
177- const isAuthorizedSender = commandAuthorized && isOwner ;
230+ const senderIsOwner = Boolean ( matchedSender ) ;
231+ const isOwnerForCommands =
232+ ! enforceOwner ||
233+ allowAll ||
234+ ownerCandidatesForCommands . length === 0 ||
235+ Boolean ( matchedCommandOwner ) ;
236+ const isAuthorizedSender = commandAuthorized && isOwnerForCommands ;
178237
179238 return {
180239 providerId,
181240 ownerList,
182241 senderId : senderId || undefined ,
242+ senderIsOwner,
183243 isAuthorizedSender,
184244 from : from || undefined ,
185245 to : to || undefined ,
0 commit comments