2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  accesscontrol  
						 
					
						
							
								
									
										
										
										
											2021-03-22 20:22:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2022-08-24 19:29:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"bytes" 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-13 05:00:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-14 00:05:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"io" 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-22 20:22:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"net/http" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"net/url" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"regexp" 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 00:55:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"strconv" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-24 19:29:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"text/template" 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-13 05:00:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-17 21:53:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/infra/tracing" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/middleware/cookies" 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-18 16:56:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/models/usertoken" 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 18:42:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/auth/identity" 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-23 21:39:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/authn" 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 15:50:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									contextmodel  "github.com/grafana/grafana/pkg/services/contexthandler/model" 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-04 23:20:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/org" 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-04 16:59:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/setting" 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-24 17:36:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/util" 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-11 20:30:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/web" 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-22 20:22:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-24 16:49:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  Middleware ( ac  AccessControl )  func ( Evaluator )  web . Handler  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  func ( evaluator  Evaluator )  web . Handler  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 15:50:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  func ( c  * contextmodel . ReqContext )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  c . AllowAnonymous  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												forceLogin ,  _  :=  strconv . ParseBool ( c . Req . URL . Query ( ) . Get ( "forceLogin" ) )  // ignoring error, assuming false for non-true values is ok.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												orgID ,  err  :=  strconv . ParseInt ( c . Req . URL . Query ( ) . Get ( "orgId" ) ,  10 ,  64 ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 18:42:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  err  ==  nil  &&  orgID  >  0  &&  orgID  !=  c . SignedInUser . GetOrgID ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													forceLogin  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ! c . IsSignedIn  &&  forceLogin  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-01 19:08:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													unauthorized ( c ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-23 21:39:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													return 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-03-23 21:39:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  c . LookupTokenErr  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												var  revokedErr  * usertoken . TokenRevokedError 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  errors . As ( c . LookupTokenErr ,  & revokedErr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													tokenRevoked ( c ,  revokedErr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-01 19:08:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												unauthorized ( c ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											authorize ( c ,  ac ,  c . SignedInUser ,  evaluator ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 18:42:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  authorize ( c  * contextmodel . ReqContext ,  ac  AccessControl ,  user  identity . Requester ,  evaluator  Evaluator )  {  
						 
					
						
							
								
									
										
										
										
											2022-08-24 19:29:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									injected ,  err  :=  evaluator . MutateScopes ( c . Req . Context ( ) ,  scopeInjector ( scopeParams { 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 18:42:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										OrgID :      user . GetOrgID ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										URLParams :  web . Params ( c . Req ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-17 17:12:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . JsonApiErr ( http . StatusInternalServerError ,  "Internal server error" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hasAccess ,  err  :=  ac . Evaluate ( c . Req . Context ( ) ,  user ,  injected ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! hasAccess  ||  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										deny ( c ,  injected ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-17 17:12:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 15:50:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  deny ( c  * contextmodel . ReqContext ,  evaluator  Evaluator ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2021-05-13 05:00:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									id  :=  newID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . Logger . Error ( "Error from access control system" ,  "error" ,  err ,  "accessErrorID" ,  id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 18:42:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										namespace ,  identifier  :=  c . SignedInUser . GetNamespacedID ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-24 17:36:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										c . Logger . Info ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"Access denied" , 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 18:42:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											"namespace" ,  namespace , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"userID" ,  identifier , 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-24 17:36:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											"accessErrorID" ,  id , 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-28 19:17:24 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											"permissions" ,  evaluator . GoString ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-24 17:36:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-13 05:00:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-04 16:59:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ! c . IsApiRequest ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// TODO(emil): I'd like to show a message after this redirect, not sure how that can be done?
 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-21 22:53:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeRedirectCookie ( c ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-04 16:59:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										c . Redirect ( setting . AppSubUrl  +  "/" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									message  :=  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  evaluator  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										message  =  evaluator . String ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-13 05:00:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// If the user triggers an error in the access control system, we
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// don't want the user to be aware of that, so the user gets the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// same information from the system regardless of if it's an
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// internal server error or access denied.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . JSON ( http . StatusForbidden ,  map [ string ] string { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										"title" :          "Access denied" ,  // the component needs to pick this up
 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										"message" :        fmt . Sprintf ( "You'll need additional permissions to perform this action. Permissions needed: %s" ,  message ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-13 05:00:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										"accessErrorId" :  id , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-01 19:08:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  unauthorized ( c  * contextmodel . ReqContext )  {  
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  c . IsApiRequest ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-23 21:39:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										c . WriteErrOrFallback ( http . StatusUnauthorized ,  http . StatusText ( http . StatusUnauthorized ) ,  c . LookupTokenErr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-03-23 21:39:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									writeRedirectCookie ( c ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  errors . Is ( c . LookupTokenErr ,  authn . ErrTokenNeedsRotation )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . Redirect ( setting . AppSubUrl  +  "/user/auth-tokens/rotate" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . Redirect ( setting . AppSubUrl  +  "/login" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-03-23 21:39:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  tokenRevoked ( c  * contextmodel . ReqContext ,  err  * usertoken . TokenRevokedError )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  c . IsApiRequest ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-30 23:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										c . JSON ( http . StatusUnauthorized ,  map [ string ] any { 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-23 21:39:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											"message" :  "Token revoked" , 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-30 23:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											"error" :  map [ string ] any { 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-23 21:39:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												"id" :                     "ERR_TOKEN_REVOKED" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												"maxConcurrentSessions" :  err . MaxConcurrentSessions , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeRedirectCookie ( c ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c . Redirect ( setting . AppSubUrl  +  "/login" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 15:50:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  writeRedirectCookie ( c  * contextmodel . ReqContext )  {  
						 
					
						
							
								
									
										
										
										
											2022-10-07 14:18:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									redirectTo  :=  c . Req . RequestURI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  setting . AppSubUrl  !=  ""  &&  ! strings . HasPrefix ( redirectTo ,  setting . AppSubUrl )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										redirectTo  =  setting . AppSubUrl  +  c . Req . RequestURI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// remove any forceLogin=true params
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									redirectTo  =  removeForceLoginParams ( redirectTo ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cookies . WriteCookie ( c . Resp ,  "redirect_to" ,  url . QueryEscape ( redirectTo ) ,  0 ,  nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  forceLoginParamsRegexp  =  regexp . MustCompile ( ` &?forceLogin=true ` )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  removeForceLoginParams ( str  string )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  forceLoginParamsRegexp . ReplaceAllString ( str ,  "" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-13 05:00:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  newID ( )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Less ambiguity than alphanumerical.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									numerical  :=  [ ] byte ( "0123456789" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									id ,  err  :=  util . GetRandomString ( 10 ,  numerical ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// this should not happen, but if it does, a timestamp is as
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// useful as anything.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										id  =  fmt . Sprintf ( "%d" ,  time . Now ( ) . UnixNano ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  "ACE"  +  id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2021-10-06 19:15:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 15:50:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type  OrgIDGetter  func ( c  * contextmodel . ReqContext )  ( int64 ,  error )  
						 
					
						
							
								
									
										
										
										
											2022-10-04 18:17:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-10 18:42:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  AuthorizeInOrgMiddleware ( ac  AccessControl ,  authnService  authn . Service )  func ( OrgIDGetter ,  Evaluator )  web . Handler  {  
						 
					
						
							
								
									
										
										
										
											2023-05-24 16:49:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  func ( getTargetOrg  OrgIDGetter ,  evaluator  Evaluator )  web . Handler  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 15:50:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  func ( c  * contextmodel . ReqContext )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-12 18:28:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											targetOrgID ,  err  :=  getTargetOrg ( c ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-17 17:12:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-17 21:53:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  errors . Is ( err ,  ErrInvalidRequestBody )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													c . JSON ( http . StatusBadRequest ,  map [ string ] string { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														"message" :  err . Error ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														"traceID" :  tracing . TraceIDFromContext ( c . Req . Context ( ) ,  false ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												deny ( c ,  nil ,  fmt . Errorf ( "failed to get target org: %w" ,  err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-17 17:12:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-12 18:28:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-10 18:42:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											var  orgUser  identity . Requester  =  c . SignedInUser 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  targetOrgID  !=  c . SignedInUser . GetOrgID ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												orgUser ,  err  =  authnService . ResolveIdentity ( c . Req . Context ( ) ,  targetOrgID ,  c . SignedInUser . GetID ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													deny ( c ,  nil ,  fmt . Errorf ( "failed to authenticate user in target org: %w" ,  err ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-09 15:07:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-10 18:42:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											authorize ( c ,  ac ,  orgUser ,  evaluator ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-24 15:58:10 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-12 18:28:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// guard against nil map
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  c . SignedInUser . Permissions  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												c . SignedInUser . Permissions  =  make ( map [ int64 ] map [ string ] [ ] string ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-10 18:42:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											c . SignedInUser . Permissions [ orgUser . GetOrgID ( ) ]  =  orgUser . GetPermissions ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 21:20:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-17 17:12:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 15:50:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  UseOrgFromContextParams ( c  * contextmodel . ReqContext )  ( int64 ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2022-01-15 00:55:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									orgID ,  err  :=  strconv . ParseInt ( web . Params ( c . Req ) [ ":orgId" ] ,  10 ,  64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-17 17:12:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Special case of macaron handling invalid params
 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-06 15:57:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ,  org . ErrOrgNotFound . Errorf ( "failed to get organization from context: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  orgID  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ,  org . ErrOrgNotFound . Errorf ( "empty org ID" ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-17 17:12:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  orgID ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 15:50:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  UseGlobalOrg ( c  * contextmodel . ReqContext )  ( int64 ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  GlobalOrgID ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 16:52:24 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-21 22:09:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// UseGlobalOrSingleOrg returns the global organization or the current organization in a single organization setup
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  UseGlobalOrSingleOrg ( cfg  * setting . Cfg )  OrgIDGetter  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  func ( c  * contextmodel . ReqContext )  ( int64 ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  cfg . RBACSingleOrganization  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  c . GetOrgID ( ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  GlobalOrgID ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-14 00:05:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// UseOrgFromRequestData returns the organization from the request data.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If no org is specified, then the org where user is logged in is returned.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  UseOrgFromRequestData ( c  * contextmodel . ReqContext )  ( int64 ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									query ,  err  :=  getOrgQueryFromRequest ( c ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Special case of macaron handling invalid params
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NoOrgID ,  org . ErrOrgNotFound . Errorf ( "failed to get organization from context: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  query . OrgId  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  c . SignedInUser . GetOrgID ( ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  * query . OrgId ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// UseGlobalOrgFromRequestData returns global org if `global` flag is set or the org where user is logged in.
  
						 
					
						
							
								
									
										
										
										
											2024-04-03 18:44:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// If RBACSingleOrganization is set, the org where user is logged in is returned - this is intended only for cloud workflows, where instances are limited to a single organization.
  
						 
					
						
							
								
									
										
										
										
											2024-04-10 18:42:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  UseGlobalOrgFromRequestData ( cfg  * setting . Cfg )  OrgIDGetter  {  
						 
					
						
							
								
									
										
										
										
											2024-04-03 18:44:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  func ( c  * contextmodel . ReqContext )  ( int64 ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										query ,  err  :=  getOrgQueryFromRequest ( c ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-17 21:53:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  errors . Is ( err ,  ErrInvalidRequestBody )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  NoOrgID ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 18:44:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// Special case of macaron handling invalid params
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NoOrgID ,  org . ErrOrgNotFound . Errorf ( "failed to get organization from context: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-14 00:05:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 18:44:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// We only check permissions in the global organization if we are not running a SingleOrganization setup
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// That allows Organization Admins to modify global roles and make global assignments.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  query . Global  &&  ! cfg . RBACSingleOrganization  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  GlobalOrgID ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-14 00:05:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 18:44:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  c . SignedInUser . GetOrgID ( ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-14 00:05:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-14 23:17:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// UseGlobalOrgFromRequestParams returns global org if `global` flag is set or the org where user is logged in.
  
						 
					
						
							
								
									
										
										
										
											2024-04-12 01:50:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  UseGlobalOrgFromRequestParams ( cfg  * setting . Cfg )  OrgIDGetter  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  func ( c  * contextmodel . ReqContext )  ( int64 ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// We only check permissions in the global organization if we are not running a SingleOrganization setup
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// That allows Organization Admins to modify global roles and make global assignments, and is intended for use in hosted Grafana.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  c . QueryBool ( "global" )  &&  ! cfg . RBACSingleOrganization  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  GlobalOrgID ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-14 23:17:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-12 01:50:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  c . SignedInUser . GetOrgID ( ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-14 23:17:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-14 00:05:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  getOrgQueryFromRequest ( c  * contextmodel . ReqContext )  ( * QueryWithOrg ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									query  :=  & QueryWithOrg { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									req ,  err  :=  CloneRequest ( c . Req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  web . Bind ( req ,  query ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-17 21:53:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err . Error ( )  ==  "unexpected EOF"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  fmt . Errorf ( "%w: unexpected end of JSON input" ,  ErrInvalidRequestBody ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-14 00:05:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  query ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// CloneRequest creates request copy including request body
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  CloneRequest ( req  * http . Request )  ( * http . Request ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Get copy of body to prevent error when reading closed body in request handler
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bodyCopy ,  err  :=  CopyRequestBody ( req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									reqCopy  :=  req . Clone ( req . Context ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									reqCopy . Body  =  bodyCopy 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  reqCopy ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// CopyRequestBody returns copy of request body and keeps the original one to prevent error when reading closed body
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  CopyRequestBody ( req  * http . Request )  ( io . ReadCloser ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  req . Body  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									body  :=  req . Body 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  buf  bytes . Buffer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  _ ,  err  :=  buf . ReadFrom ( body ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  body . Close ( ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									req . Body  =  io . NopCloser ( & buf ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  io . NopCloser ( bytes . NewReader ( buf . Bytes ( ) ) ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-24 19:29:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// scopeParams holds the parameters used to fill in scope templates
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  scopeParams  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									OrgID      int64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									URLParams  map [ string ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// scopeInjector inject request params into the templated scopes. e.g. "settings:" + eval.Parameters(":id")
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  scopeInjector ( params  scopeParams )  ScopeAttributeMutator  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  func ( _  context . Context ,  scope  string )  ( [ ] string ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tmpl ,  err  :=  template . New ( "scope" ) . Parse ( scope ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  buf  bytes . Buffer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  =  tmpl . Execute ( & buf ,  params ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  [ ] string { buf . String ( ) } ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}