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" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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" 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 21:20:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/team" 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-10 17:56:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/user" 
							 
						 
					
						
							
								
									
										
										
										
											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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								type  userCache  interface  {  
						 
					
						
							
								
									
										
										
										
											2022-08-16 22:08:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									GetSignedInUserWithCacheCtx ( ctx  context . Context ,  query  * user . GetSignedInUserQuery )  ( * user . SignedInUser ,  error ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-28 16:46:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2021-11-17 17:12:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 21:20:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type  teamService  interface  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									GetTeamIDsByUser ( ctx  context . Context ,  query  * team . GetTeamIDsByUserQuery )  ( [ ] int64 ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  AuthorizeInOrgMiddleware ( ac  AccessControl ,  service  Service ,  userService  userCache ,  teamService  teamService )  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  { 
							 
						 
					
						
							
								
									
										
										
										
											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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 21:20:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											tmpUser ,  err  :=  makeTmpUser ( c . Req . Context ( ) ,  service ,  userService ,  teamService ,  c . SignedInUser ,  targetOrgID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 21:20:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											authorize ( c ,  ac ,  tmpUser ,  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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 21:20:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											c . SignedInUser . Permissions [ tmpUser . GetOrgID ( ) ]  =  tmpUser . GetPermissions ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// makeTmpUser creates a temporary user that can be used to evaluate access across orgs.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  makeTmpUser ( ctx  context . Context ,  service  Service ,  cache  userCache ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									teamService  teamService ,  reqUser  identity . Requester ,  targetOrgID  int64 )  ( identity . Requester ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tmpUser  :=  & user . SignedInUser { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										OrgID :           reqUser . GetOrgID ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										OrgName :         reqUser . GetOrgName ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										OrgRole :         reqUser . GetOrgRole ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IsGrafanaAdmin :  reqUser . GetIsGrafanaAdmin ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Login :           reqUser . GetLogin ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Teams :           reqUser . GetTeams ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Permissions :  map [ int64 ] map [ string ] [ ] string { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reqUser . GetOrgID ( ) :  reqUser . GetPermissions ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									namespace ,  identifier  :=  reqUser . GetNamespacedID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									id ,  _  :=  identity . IntIdentifier ( namespace ,  identifier ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  namespace  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  identity . NamespaceUser : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tmpUser . UserID  =  id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  identity . NamespaceAPIKey : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tmpUser . ApiKeyID  =  id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  tmpUser . OrgID  !=  targetOrgID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  errors . New ( "API key does not belong to target org" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  identity . NamespaceServiceAccount : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tmpUser . UserID  =  id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tmpUser . IsServiceAccount  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  tmpUser . OrgID  !=  targetOrgID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  targetOrgID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  GlobalOrgID : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tmpUser . OrgID  =  GlobalOrgID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tmpUser . OrgRole  =  org . RoleNone 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tmpUser . OrgName  =  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tmpUser . Teams  =  [ ] int64 { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  cache  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil ,  errors . New ( "user cache is nil" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											query  :=  user . GetSignedInUserQuery { UserID :  tmpUser . UserID ,  OrgID :  targetOrgID } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											queryResult ,  err  :=  cache . GetSignedInUserWithCacheCtx ( ctx ,  & query ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tmpUser . OrgID  =  queryResult . OrgID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tmpUser . OrgName  =  queryResult . OrgName 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tmpUser . OrgRole  =  queryResult . OrgRole 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-01 19:37:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// Only fetch the team membership is the user is a member of the organization
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  queryResult . OrgID  ==  targetOrgID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  teamService  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													teamIDs ,  err  :=  teamService . GetTeamIDsByUser ( ctx ,  & team . GetTeamIDsByUserQuery { OrgID :  targetOrgID ,  UserID :  tmpUser . UserID } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													tmpUser . Teams  =  teamIDs 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 21:20:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-01 19:37:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// If the user is not a member of the organization
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// evaluation must happen based on global permissions.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									evaluationOrg  :=  targetOrgID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  tmpUser . OrgID  ==  NoOrgID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										evaluationOrg  =  GlobalOrgID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  tmpUser . Permissions [ evaluationOrg ]  ==  nil  ||  len ( tmpUser . Permissions [ evaluationOrg ] )  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 21:20:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										permissions ,  err  :=  service . GetUserPermissions ( ctx ,  tmpUser ,  Options { } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-17 17:12:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 21:20:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-01 19:37:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										tmpUser . Permissions [ evaluationOrg ]  =  GroupScopesByAction ( permissions ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-17 17:12:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 21:20:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  tmpUser ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											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.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  UseGlobalOrgFromRequestData ( cfg  * setting . Cfg )  func ( * contextmodel . ReqContext )  ( int64 ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  func ( 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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											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.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  UseGlobalOrgFromRequestParams ( c  * contextmodel . ReqContext )  ( int64 ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  c . QueryBool ( "global" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  GlobalOrgID ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  c . SignedInUser . GetOrgID ( ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Special case of macaron handling invalid params
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}