コード例 #1
0
        public bool TryAuthorize(RavenBaseApiController controller, out HttpResponseMessage msg)
        {
            var requestUrl = controller.GetRequestUrl();

            if (NeverSecret.IsNeverSecretUrl(requestUrl))
            {
                msg = controller.GetEmptyMessage();
                return(true);
            }

            //CORS pre-flight (ignore creds if using cors).
            if (Settings.AccessControlAllowOrigin.Count > 0 && controller.InnerRequest.Method.Method == "OPTIONS")
            {
                msg = controller.GetEmptyMessage();
                return(true);
            }

            var oneTimeToken = controller.GetHeader("Single-Use-Auth-Token");

            if (string.IsNullOrEmpty(oneTimeToken) == false)
            {
                return(TryAuthorizeSingleUseAuthToken(controller, oneTimeToken, out msg));
            }

            var authHeader            = controller.GetHeader("Authorization");
            var hasApiKey             = "True".Equals(controller.GetHeader("Has-Api-Key"), StringComparison.CurrentCultureIgnoreCase);
            var hasOAuthTokenInCookie = controller.HasCookie("OAuth-Token");

            if (hasApiKey || hasOAuthTokenInCookie ||
                string.IsNullOrEmpty(authHeader) == false && authHeader.StartsWith("Bearer "))
            {
                return(oAuthRequestAuthorizer.TryAuthorize(controller, hasApiKey, IgnoreDb.Urls.Contains(requestUrl), out msg));
            }
            return(windowsRequestAuthorizer.TryAuthorize(controller, IgnoreDb.Urls.Contains(requestUrl), out msg));
        }
コード例 #2
0
        private PrincipalWithDatabaseAccess UpdateUserPrincipal(RavenBaseApiController controller, List <ResourceAccess> databaseAccessLists)
        {
            var access = controller.User as PrincipalWithDatabaseAccess;

            if (access != null)
            {
                return(access);
            }

            var user = new PrincipalWithDatabaseAccess((WindowsPrincipal)controller.User);

            foreach (var databaseAccess in databaseAccessLists)
            {
                if (databaseAccess.Admin)
                {
                    user.AdminDatabases.Add(databaseAccess.TenantId);
                }
                else if (databaseAccess.ReadOnly)
                {
                    user.ReadOnlyDatabases.Add(databaseAccess.TenantId);
                }
                else
                {
                    user.ReadWriteDatabases.Add(databaseAccess.TenantId);
                }
            }

            controller.User         = user;
            Thread.CurrentPrincipal = user;

            return(user);
        }
コード例 #3
0
        HttpResponseMessage WriteAuthorizationChallenge(RavenBaseApiController controller, int statusCode, string error, string errorDescription)
        {
            var msg = controller.GetEmptyMessage();
            var systemConfiguration = controller.SystemConfiguration;

            if (string.IsNullOrEmpty(systemConfiguration.OAuthTokenServer) == false)
            {
                if (systemConfiguration.UseDefaultOAuthTokenServer == false)
                {
                    controller.AddHeader("OAuth-Source", systemConfiguration.OAuthTokenServer, msg);
                }
                else
                {
                    controller.AddHeader("OAuth-Source", new UriBuilder(systemConfiguration.OAuthTokenServer)
                    {
                        Scheme = controller.InnerRequest.RequestUri.Scheme,
                        Host   = controller.InnerRequest.RequestUri.Host,
                        Port   = controller.InnerRequest.RequestUri.Port,
                    }.Uri.ToString(), msg);
                }
            }
            msg.StatusCode = (HttpStatusCode)statusCode;

            msg.Headers.Add("WWW-Authenticate", string.Format("Bearer realm=\"Raven\", error=\"{0}\",error_description=\"{1}\"", error, errorDescription));
            msg.Headers.Add("Access-Control-Expose-Headers", "WWW-Authenticate, OAuth-Source");
            return(msg);
        }
コード例 #4
0
        public bool TryAuthorize(RavenBaseApiController controller, out HttpResponseMessage msg)
		{
			var requestUrl = controller.GetRequestUrl();
			if (NeverSecret.IsNeverSecretUrl(requestUrl))
			{
				msg = controller.GetEmptyMessage();
				return true;
			}

			//CORS pre-flight (ignore creds if using cors).
			if (!String.IsNullOrEmpty(Settings.AccessControlAllowOrigin) && controller.InnerRequest.Method.Method == "OPTIONS")
			{
				msg = controller.GetEmptyMessage();
				return true;
			}

			var oneTimeToken = controller.GetHeader("Single-Use-Auth-Token");
			if (string.IsNullOrEmpty(oneTimeToken) == false)
			{
				return TryAuthorizeSingleUseAuthToken(controller, oneTimeToken, out msg);
			}

			var authHeader = controller.GetHeader("Authorization");
			var hasApiKey = "True".Equals(controller.GetHeader("Has-Api-Key"), StringComparison.CurrentCultureIgnoreCase);
			var hasOAuthTokenInCookie = controller.HasCookie("OAuth-Token");
			if (hasApiKey || hasOAuthTokenInCookie ||
				string.IsNullOrEmpty(authHeader) == false && authHeader.StartsWith("Bearer "))
			{
				return oAuthRequestAuthorizer.TryAuthorize(controller, hasApiKey, IgnoreDb.Urls.Contains(requestUrl), out msg);
			}
			return windowsRequestAuthorizer.TryAuthorize(controller, IgnoreDb.Urls.Contains(requestUrl), out msg);
		}
コード例 #5
0
ファイル: RequestManager.cs プロジェクト: mow/ravendb
        private void LogHttpRequestStats(RavenBaseApiController controller, LogHttpRequestStatsParams logHttpRequestStatsParams, string databaseName, long curReq)
        {
            if (Logger.IsDebugEnabled == false)
            {
                return;
            }

            if (controller is StudioController || controller is HardRouteController || controller is SilverlightController)
            {
                return;
            }

            var message = string.Format(CultureInfo.InvariantCulture, "Request #{0,4:#,0}: {1,-7} - {2,5:#,0} ms - {5,-10} - {3} - {4}",
                                        curReq,
                                        logHttpRequestStatsParams.HttpMethod,
                                        logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds,
                                        logHttpRequestStatsParams.ResponseStatusCode,
                                        logHttpRequestStatsParams.RequestUri,
                                        databaseName);

            Logger.Debug(message);
            if (string.IsNullOrWhiteSpace(logHttpRequestStatsParams.CustomInfo) == false)
            {
                Logger.Debug(logHttpRequestStatsParams.CustomInfo);
            }
        }
コード例 #6
0
        private bool TryAuthorizeSingleUseAuthToken(RavenBaseApiController controller, string token, out HttpResponseMessage msg)
        {
            if (controller.WasAlreadyAuthorizedUsingSingleAuthToken)
            {
                msg = controller.GetEmptyMessage();
                return(true);
            }

            object         result;
            HttpStatusCode statusCode;
            IPrincipal     user;
            var            success = TryAuthorizeSingleUseAuthToken(token, controller.TenantName, out result, out statusCode, out user);

            controller.User = user;
            if (success == false)
            {
                msg = controller.GetMessageWithObject(result, statusCode);
            }
            else
            {
                msg = controller.GetEmptyMessage();
            }

            controller.WasAlreadyAuthorizedUsingSingleAuthToken = success;
            return(success);
        }
コード例 #7
0
        private void LogHttpRequestStats(RavenBaseApiController controller, LogHttpRequestStatsParams logHttpRequestStatsParams, string databaseName, long curReq)
        {
            if (Logger.IsDebugEnabled == false)
            {
                return;
            }

            if (controller is StudioController || controller is HardRouteController || controller is SilverlightController)
            {
                return;
            }

            // we filter out requests for the UI because they fill the log with information
            // we probably don't care about them anyway. That said, we do output them if they take too
            // long.
            if (logHttpRequestStatsParams.Headers["Raven-Timer-Request"] == "true" &&
                logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds <= 25)
            {
                return;
            }

            var message = string.Format(CultureInfo.InvariantCulture, "Request #{0,4:#,0}: {1,-7} - {2,5:#,0} ms - {5,-10} - {3} - {4}",
                                        curReq,
                                        logHttpRequestStatsParams.HttpMethod,
                                        logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds,
                                        logHttpRequestStatsParams.ResponseStatusCode,
                                        logHttpRequestStatsParams.RequestUri,
                                        databaseName);

            Logger.Debug(message);
            if (string.IsNullOrWhiteSpace(logHttpRequestStatsParams.CustomInfo) == false)
            {
                Logger.Debug(logHttpRequestStatsParams.CustomInfo);
            }
        }
コード例 #8
0
ファイル: LogPushContent.cs プロジェクト: GorelH/ravendb
        public LogsPushContent(RavenBaseApiController controller)
		{
			Connected = true;
			Id = controller.GetQueryStringValue("id");
            
			if (string.IsNullOrEmpty(Id))
				throw new ArgumentException("Id is mandatory");
		}
コード例 #9
0
        private bool TryCreateUser(RavenBaseApiController controller, string databaseName, out Func <HttpResponseMessage> onRejectingRequest)
        {
            var invalidUser = (controller.User == null || controller.User.Identity.IsAuthenticated == false);

            if (invalidUser)
            {
                onRejectingRequest = () =>
                {
                    var msg = ProvideDebugAuthInfo(controller, new
                    {
                        Reason = "User is null or not authenticated"
                    });
                    controller.AddHeader("Raven-Required-Auth", "Windows", msg);
                    if (string.IsNullOrEmpty(controller.SystemConfiguration.OAuthTokenServer) == false)
                    {
                        controller.AddHeader("OAuth-Source", controller.SystemConfiguration.OAuthTokenServer, msg);
                    }
                    msg.StatusCode = HttpStatusCode.Unauthorized;

                    return(msg);
                };
                return(false);
            }

            var dbUsersIsAllowedAccessTo = requiredUsers
                                           .Where(data => controller.User.Identity.Name.Equals(data.Name, StringComparison.InvariantCultureIgnoreCase))
                                           .SelectMany(source => source.Databases)
                                           .Concat(requiredGroups.Where(data => controller.User.IsInRole(data.Name)).SelectMany(x => x.Databases))
                                           .ToList();

            var fsUsersIsAllowedAccessTo = requiredUsers
                                           .Where(data => controller.User.Identity.Name.Equals(data.Name, StringComparison.InvariantCultureIgnoreCase))
                                           .SelectMany(source => source.FileSystems)
                                           .Concat(requiredGroups.Where(data => controller.User.IsInRole(data.Name)).SelectMany(x => x.FileSystems))
                                           .ToList();

            var user = UpdateUserPrincipal(controller, dbUsersIsAllowedAccessTo, fsUsersIsAllowedAccessTo);

            onRejectingRequest = () =>
            {
                var msg = ProvideDebugAuthInfo(controller, new
                {
                    user.Identity.Name,
                    user.AdminDatabases,
                    user.ReadOnlyDatabases,
                    user.ReadWriteDatabases,
                    user.ReadOnlyFileSystems,
                    user.ReadWriteFileSystems,
                    DatabaseName = databaseName
                });

                msg.StatusCode = HttpStatusCode.Forbidden;

                throw new HttpResponseException(msg);
            };
            return(true);
        }
コード例 #10
0
        public async Task <HttpResponseMessage> HandleActualRequest(RavenBaseApiController controller,
                                                                    HttpControllerContext controllerContext,
                                                                    Func <Task <HttpResponseMessage> > action,
                                                                    Func <HttpException, HttpResponseMessage> onHttpException)
        {
            HttpResponseMessage response = null;

            cancellationToken.ThrowIfCancellationRequested();

            Stopwatch sw = Stopwatch.StartNew();

            try
            {
                Interlocked.Increment(ref concurrentRequests);

                if (controller.SetupRequestToProperDatabase(this))
                {
                    if (controller.ResourceConfiguration.RejectClientsMode && controllerContext.Request.Headers.Contains(Constants.RavenClientVersion))
                    {
                        response = new HttpResponseMessage(HttpStatusCode.ServiceUnavailable)
                        {
                            Content = new MultiGetSafeStringContent("This service is not accepting clients calls")
                        };
                    }
                    else
                    {
                        response = await action();
                    }
                }
            }
            catch (HttpException httpException)
            {
                response = onHttpException(httpException);
            }

            finally
            {
                Interlocked.Decrement(ref concurrentRequests);
                try
                {
                    FinalizeRequestProcessing(controller, response, sw);
                }

                catch (Exception e)
                {
                    var aggregateException = e as AggregateException;
                    if (aggregateException != null)
                    {
                        e = aggregateException.ExtractSingleInnerException();
                    }

                    Logger.ErrorException("Could not finalize request properly", e);
                }
            }
            return(response);
        }
コード例 #11
0
ファイル: LogPushContent.cs プロジェクト: xinix00/ravendb
        public LogsPushContent(RavenBaseApiController controller)
        {
            Connected = true;
            Id        = controller.GetQueryStringValue("id");

            if (string.IsNullOrEmpty(Id))
            {
                throw new ArgumentException("Id is mandatory");
            }
        }
コード例 #12
0
        public IPrincipal GetUser(RavenBaseApiController controller)
        {
            Func <HttpResponseMessage> onRejectingRequest;
            var databaseName = controller.ResourceName ?? Constants.SystemDatabase;
            var userCreated  = TryCreateUser(controller, databaseName, out onRejectingRequest);

            if (userCreated == false)
            {
                onRejectingRequest();
            }
            return(userCreated ? controller.User : null);
        }
コード例 #13
0
        public async Task <HttpResponseMessage> HandleActualRequest(RavenBaseApiController controller,
                                                                    Func <Task <HttpResponseMessage> > action,
                                                                    Func <HttpException, HttpResponseMessage> onHttpException)
        {
            HttpResponseMessage response = null;

            cancellationToken.ThrowIfCancellationRequested();

            Stopwatch sw = Stopwatch.StartNew();

            try
            {
                Interlocked.Increment(ref concurrentRequests);
                if (IsWriteRequest(controller.InnerRequest))
                {
                    lastWriteRequest = SystemTime.UtcNow;
                }


                if (controller.SetupRequestToProperDatabase(this))
                {
                    response = await action();
                }
            }


            catch (HttpException httpException)
            {
                response = onHttpException(httpException);
            }

            finally
            {
                Interlocked.Decrement(ref concurrentRequests);
                try
                {
                    FinalizeRequestProcessing(controller, response, sw);
                }

                catch (Exception e)
                {
                    var aggregateException = e as AggregateException;
                    if (aggregateException != null)
                    {
                        e = aggregateException.ExtractSingleInnerException();
                    }

                    Logger.ErrorException("Could not finalize request properly", e);
                }
            }
            return(response);
        }
コード例 #14
0
ファイル: ChangesPushContent.cs プロジェクト: cocytus/ravendb
        public ChangesPushContent(RavenBaseApiController controller)
		{
			Connected = true;
            ResourceName = controller.TenantName;
			Id = controller.GetQueryStringValue("id");
            
			if (string.IsNullOrEmpty(Id))
				throw new ArgumentException("Id is mandatory");

            long coolDownWithDataLossInMiliseconds = 0;
			long.TryParse(controller.GetQueryStringValue("coolDownWithDataLoss"), out coolDownWithDataLossInMiliseconds);
            CoolDownWithDataLossInMiliseconds = coolDownWithDataLossInMiliseconds;
		}
コード例 #15
0
ファイル: RequestManager.cs プロジェクト: stvoidmain/ravendb
        private void FinalizeRequestProcessing(RavenBaseApiController controller, HttpResponseMessage response, Stopwatch sw)
        {
            LogHttpRequestStatsParams logHttpRequestStatsParam = null;

            try
            {
                StringBuilder sb = null;
                if (controller.CustomRequestTraceInfo != null)
                {
                    sb = new StringBuilder();
                    foreach (var action in controller.CustomRequestTraceInfo)
                    {
                        action(sb);
                        sb.AppendLine();
                    }
                    while (sb.Length > 0)
                    {
                        if (!char.IsWhiteSpace(sb[sb.Length - 1]))
                        {
                            break;
                        }
                        sb.Length--;
                    }
                }
                logHttpRequestStatsParam = new LogHttpRequestStatsParams(
                    sw,
                    GetHeaders(controller.InnerHeaders),
                    controller.InnerRequest.Method.Method,
                    response != null ? (int)response.StatusCode : 500,
                    controller.InnerRequest.RequestUri.ToString(),
                    sb != null ? sb.ToString() : null
                    );
            }
            catch (Exception e)
            {
                Logger.WarnException("Could not gather information to log request stats", e);
            }

            if (logHttpRequestStatsParam == null || sw == null)
            {
                return;
            }

            sw.Stop();

            controller.MarkRequestDuration(sw.ElapsedMilliseconds);

            LogHttpRequestStats(controller, logHttpRequestStatsParam, controller.TenantName);

            TraceRequest(logHttpRequestStatsParam, controller.TenantName);
        }
コード例 #16
0
ファイル: TransportState.cs プロジェクト: tryadiadi/ravendb
        public ConnectionState For(string id, RavenBaseApiController controller = null)
        {
            return(connections.GetOrAdd(id, _ =>
            {
                IEventsTransport eventsTransport = null;
                if (controller != null)
                {
                    eventsTransport = new ChangesPushContent(controller);
                }

                var connectionState = new ConnectionState(eventsTransport);
                TimeSensitiveStore.Missing(id);
                return connectionState;
            }));
        }
コード例 #17
0
        public ChangesPushContent(RavenBaseApiController controller)
        {
            Connected = true;
            Id        = controller.GetQueryStringValue("id");

            if (string.IsNullOrEmpty(Id))
            {
                throw new ArgumentException("Id is mandatory");
            }

            long coolDownWithDataLossInMilisecods = 0;

            long.TryParse(controller.GetQueryStringValue("coolDownWithDataLoss"), out coolDownWithDataLossInMilisecods);
            CoolDownWithDataLossInMilisecods = coolDownWithDataLossInMilisecods;
        }
コード例 #18
0
		public static bool IsGetRequest(RavenBaseApiController controller)
		{
            switch (controller.InnerRequest.Method.Method)
		    {
                case "GET":
                case "HEAD":
		            return true;
                case "POST":
		            var absolutePath = controller.InnerRequest.RequestUri.AbsolutePath;
				    return absolutePath.EndsWith("/queries", StringComparison.Ordinal) ||
				           absolutePath.EndsWith("/multi_get", StringComparison.Ordinal) ||
				           absolutePath.EndsWith("/multi_get/", StringComparison.Ordinal);
                default:
		            return false;
		    }
		}
コード例 #19
0
        public ChangesPushContent(RavenBaseApiController controller)
        {
            Connected    = true;
            ResourceName = controller.TenantName;
            Id           = controller.GetQueryStringValue("id");

            if (string.IsNullOrEmpty(Id))
            {
                throw new ArgumentException("Id is mandatory");
            }
            cancellationTokenSource = WebSocketTransportFactory.RavenGcCancellation;
            long coolDownWithDataLossInMiliseconds = 0;

            long.TryParse(controller.GetQueryStringValue("coolDownWithDataLoss"), out coolDownWithDataLossInMiliseconds);
            CoolDownWithDataLossInMiliseconds = coolDownWithDataLossInMiliseconds;
        }
コード例 #20
0
ファイル: RequestManager.cs プロジェクト: stvoidmain/ravendb
        // Cross-Origin Resource Sharing (CORS) is documented here: http://www.w3.org/TR/cors/
        public void AddAccessControlHeaders(RavenBaseApiController controller, HttpResponseMessage msg)
        {
            var accessControlAllowOrigin = landlord.SystemConfiguration.AccessControlAllowOrigin;

            if (accessControlAllowOrigin.Count == 0)
            {
                return;
            }

            var originHeader = controller.GetHeader("Origin");

            if (originHeader == null || originHeader.Contains(controller.InnerRequest.Headers.Host))
            {
                return;         // no need
            }
            bool originAllowed = accessControlAllowOrigin.Contains("*") ||
                                 accessControlAllowOrigin.Contains(originHeader);

            if (originAllowed)
            {
                controller.AddHeader("Access-Control-Allow-Origin", originHeader, msg);
            }


            if (controller.InnerRequest.Method.Method != "OPTIONS")
            {
                return;
            }

            controller.AddHeader("Access-Control-Allow-Credentials", "true", msg);
            controller.AddHeader("Access-Control-Max-Age", landlord.SystemConfiguration.AccessControlMaxAge, msg);
            controller.AddHeader("Access-Control-Allow-Methods", landlord.SystemConfiguration.AccessControlAllowMethods, msg);
            if (string.IsNullOrEmpty(landlord.SystemConfiguration.AccessControlRequestHeaders))
            {
                // allow whatever headers are being requested
                var hdr = controller.GetHeader("Access-Control-Request-Headers");                 // typically: "x-requested-with"
                if (hdr != null)
                {
                    controller.AddHeader("Access-Control-Allow-Headers", hdr, msg);
                }
            }
            else
            {
                controller.AddHeader("Access-Control-Request-Headers", landlord.SystemConfiguration.AccessControlRequestHeaders, msg);
            }
        }
コード例 #21
0
        public IPrincipal GetUser(RavenBaseApiController controller)
        {
            if (controller.WasAlreadyAuthorizedUsingSingleAuthToken)
            {
                return(controller.User);
            }

            var hasApiKey             = "True".Equals(controller.GetQueryStringValue("Has-Api-Key"), StringComparison.CurrentCultureIgnoreCase);
            var authHeader            = controller.GetHeader("Authorization");
            var hasOAuthTokenInCookie = controller.HasCookie("OAuth-Token");

            if (hasApiKey || hasOAuthTokenInCookie ||
                string.IsNullOrEmpty(authHeader) == false && authHeader.StartsWith("Bearer "))
            {
                return(oAuthRequestAuthorizer.GetUser(controller, hasApiKey));
            }
            return(windowsRequestAuthorizer.GetUser(controller));
        }
コード例 #22
0
        public static bool IsGetRequest(RavenBaseApiController controller)
        {
            switch (controller.InnerRequest.Method.Method)
            {
            case "GET":
            case "HEAD":
                return(true);

            case "POST":
                var absolutePath = controller.InnerRequest.RequestUri.AbsolutePath;
                return(absolutePath.EndsWith("/queries", StringComparison.Ordinal) ||
                       absolutePath.EndsWith("/multi_get", StringComparison.Ordinal) ||
                       absolutePath.EndsWith("/multi_get/", StringComparison.Ordinal));

            default:
                return(false);
            }
        }
コード例 #23
0
        private static HttpResponseMessage ProvideDebugAuthInfo(RavenBaseApiController controller, object msg)
        {
            string debugAuth = controller.GetQueryStringValue("debug-auth");

            if (debugAuth == null)
            {
                return(controller.GetEmptyMessage());
            }

            bool shouldProvideDebugAuthInformation;

            if (bool.TryParse(debugAuth, out shouldProvideDebugAuthInformation) && shouldProvideDebugAuthInformation)
            {
                return(controller.GetMessageWithObject(msg));
            }

            return(controller.GetEmptyMessage());
        }
コード例 #24
0
        private bool TryAuthorizeSingleUseAuthToken(RavenBaseApiController controller, string token, out HttpResponseMessage msg)
        {
            OneTimeToken value;

            if (singleUseAuthTokens.TryRemove(token, out value) == false)
            {
                msg = controller.GetMessageWithObject(
                    new
                {
                    Error = "Unknown single use token, maybe it was already used?"
                }, HttpStatusCode.Forbidden);
                return(false);
            }

            if (string.Equals(value.DatabaseName, controller.TenantName, StringComparison.InvariantCultureIgnoreCase) == false &&
                (value.DatabaseName == "<system>" && controller.TenantName == null) == false)
            {
                msg = controller.GetMessageWithObject(
                    new
                {
                    Error = "This single use token cannot be used for this database"
                }, HttpStatusCode.Forbidden);
                return(false);
            }
            if ((SystemTime.UtcNow - value.GeneratedAt).TotalMinutes > 2.5)
            {
                msg = controller.GetMessageWithObject(
                    new
                {
                    Error = "This single use token has expired"
                }, HttpStatusCode.Forbidden);
                return(false);
            }

            if (value.User != null)
            {
                CurrentOperationContext.Headers.Value[Constants.RavenAuthenticatedUser] = value.User.Identity.Name;
            }

            CurrentOperationContext.User.Value = value.User;
            controller.User = value.User;
            msg             = controller.GetEmptyMessage();
            return(true);
        }
コード例 #25
0
        public AdminLogsConnectionState For(string id, RavenBaseApiController controller = null)
        {
            var connection = connections.GetOrAdd(
                id,
                _ =>
            {
                IEventsTransport logsTransport = null;
                if (controller != null)
                {
                    logsTransport = new LogsPushContent(controller);
                }

                var connectionState = new AdminLogsConnectionState(logsTransport);
                TimeSensitiveStore.Missing(id);
                return(connectionState);
            });

            AlterEnabled();
            return(connection);
        }
コード例 #26
0
        private bool TryAuthorizeSingleUseAuthToken(RavenBaseApiController controller, string token, out HttpResponseMessage msg)
        {
            if (controller.WasAlreadyAuthorizedUsingSingleAuthToken)
            {
                msg = controller.GetEmptyMessage();
                return(true);
            }

            object         result;
            HttpStatusCode statusCode;
            IPrincipal     user;
            var            resourceName = controller.ResourceName == null ? null : controller.ResourcePrefix + controller.ResourceName;
            var            success      = TryAuthorizeSingleUseAuthToken(token, resourceName, out result, out statusCode, out user);

            controller.User = user;
            msg             = success == false?controller.GetMessageWithObject(result, statusCode) : controller.GetEmptyMessage();

            controller.WasAlreadyAuthorizedUsingSingleAuthToken = success;
            return(success);
        }
コード例 #27
0
ファイル: RequestManager.cs プロジェクト: mow/ravendb
        private void TraceTraffic(RavenBaseApiController controller, LogHttpRequestStatsParams logHttpRequestStatsParams, string resourceName)
        {
            if (HasAnyHttpTraceEventTransport() == false)
            {
                return;
            }

            NotifyTrafficWatch(string.IsNullOrEmpty(resourceName) == false ? resourceName : Constants.SystemDatabase,
                               new TrafficWatchNotification()
            {
                RequestUri          = logHttpRequestStatsParams.RequestUri,
                ElapsedMilliseconds = logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds,
                CustomInfo          = logHttpRequestStatsParams.CustomInfo,
                HttpMethod          = logHttpRequestStatsParams.HttpMethod,
                ResponseStatusCode  = logHttpRequestStatsParams.ResponseStatusCode,
                TenantName          = NormalizeTennantName(resourceName),
                TimeStamp           = SystemTime.UtcNow,
                InnerRequestsCount  = logHttpRequestStatsParams.InnerRequestsCount
            }
                               );
        }
コード例 #28
0
        private void TraceTraffic(RavenBaseApiController controller, LogHttpRequestStatsParams logHttpRequestStatsParams, string databaseName)
        {
            if (HasAnyHttpTraceEventTransport() == false)
            {
                return;
            }



            NotifyTrafficWatch(
                new TrafficWatchNotification()
            {
                RequestUri          = logHttpRequestStatsParams.RequestUri,
                ElapsedMilliseconds = logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds,
                CustomInfo          = logHttpRequestStatsParams.CustomInfo,
                HttpMethod          = logHttpRequestStatsParams.HttpMethod,
                ResponseStatusCode  = logHttpRequestStatsParams.ResponseStatusCode,
                TenantName          = NormalizeTennantName(databaseName),
                TimeStamp           = SystemTime.UtcNow
            }
                );
        }
コード例 #29
0
        public IPrincipal GetUser(RavenBaseApiController controller, bool hasApiKey)
        {
            var token = GetToken(controller);

            if (token == null)
            {
                WriteAuthorizationChallenge(controller, hasApiKey ? 412 : 401, "invalid_request", "The access token is required");

                return(null);
            }

            AccessTokenBody tokenBody;

            if (!AccessToken.TryParseBody(controller.DatabasesLandlord.SystemConfiguration.OAuthTokenKey, token, out tokenBody))
            {
                WriteAuthorizationChallenge(controller, 401, "invalid_token", "The access token is invalid");

                return(null);
            }

            return(new OAuthPrincipal(tokenBody, null));
        }
コード例 #30
0
        static string GetToken(RavenBaseApiController controller)
        {
            const string bearerPrefix = "Bearer ";

            var auth = controller.GetHeader("Authorization");

            if (auth == null)
            {
                auth = controller.GetCookie("OAuth-Token");
                if (auth != null)
                {
                    auth = Uri.UnescapeDataString(auth);
                }
            }
            if (auth == null || auth.Length <= bearerPrefix.Length ||
                !auth.StartsWith(bearerPrefix, StringComparison.OrdinalIgnoreCase))
            {
                return(null);
            }

            var token = auth.Substring(bearerPrefix.Length, auth.Length - bearerPrefix.Length);

            return(token);
        }
コード例 #31
0
        private bool TryAuthorizeSingleUseAuthToken(RavenBaseApiController controller, string token, out HttpResponseMessage msg)
		{
			OneTimeToken value;
			if (singleUseAuthTokens.TryRemove(token, out value) == false)
			{
				msg = controller.GetMessageWithObject(
					new
					{
						Error = "Unknown single use token, maybe it was already used?"
					}, HttpStatusCode.Forbidden);
				return false;
			}

			if (string.Equals(value.DatabaseName, controller.TenantName, StringComparison.InvariantCultureIgnoreCase) == false &&
                (value.DatabaseName == "<system>" && controller.TenantName == null) == false)
			{
				msg = controller.GetMessageWithObject(
					new
					{
						Error = "This single use token cannot be used for this database"
					}, HttpStatusCode.Forbidden);
				return false;
			}
			if ((SystemTime.UtcNow - value.GeneratedAt).TotalMinutes > 2.5)
			{
				msg = controller.GetMessageWithObject(
					new
					{
						Error = "This single use token has expired"
					}, HttpStatusCode.Forbidden);
				return false;
			}

			if (value.User != null)
			{
				CurrentOperationContext.Headers.Value[Constants.RavenAuthenticatedUser] = value.User.Identity.Name;
			}

			CurrentOperationContext.User.Value = value.User;
			controller.User = value.User;
			msg = controller.GetEmptyMessage();
			return true;
		}
コード例 #32
0
        public async Task<HttpResponseMessage> HandleActualRequest(RavenBaseApiController controller,
		                                                           Func<Task<HttpResponseMessage>> action,
		                                                           Func<HttpException, HttpResponseMessage> onHttpException)
	    {
	        HttpResponseMessage response = null;
            cancellationToken.ThrowIfCancellationRequested();

	        Stopwatch sw = Stopwatch.StartNew();
	        try
	        {
	            Interlocked.Increment(ref concurrentRequests);
	            if (IsWriteRequest(controller.InnerRequest))
	            {
	                lastWriteRequest = SystemTime.UtcNow;
	            }

                if (controller.SetupRequestToProperDatabase(this))
	            {
	                response = await action();
	            }
	        }
	        catch (HttpException httpException)
	        {
	            response = onHttpException(httpException);
	        }
	        finally
	        {
	            Interlocked.Decrement(ref concurrentRequests);
	            try
	            {
	                FinalizeRequestProcessing(controller, response, sw);
	            }
	            catch (Exception e)
	            {
		            var aggregateException = e as AggregateException;
		            if (aggregateException != null)
		            {
			            e = aggregateException.ExtractSingleInnerException();
		            }
		            Logger.ErrorException("Could not finalize request properly", e);
	            }
	        }

	        return response;
	    }
コード例 #33
0
ファイル: RequestManager.cs プロジェクト: mow/ravendb
        private void FinalizeRequestProcessing(RavenBaseApiController controller, HttpResponseMessage response, Stopwatch sw)
        {
            LogHttpRequestStatsParams logHttpRequestStatsParam = null;

            try
            {
                StringBuilder sb = null;
                if (controller.CustomRequestTraceInfo != null && controller.CustomRequestTraceInfo.Count > 0)
                {
                    sb = new StringBuilder();
                    foreach (var action in controller.CustomRequestTraceInfo)
                    {
                        try
                        {
                            action(sb);
                        }
                        catch (Exception e)
                        {
                            Logger.WarnException("Could not gather information to log request stats custom info, so far got " + sb, e);
                        }
                        sb.AppendLine();
                    }
                    while (sb.Length > 0)
                    {
                        if (!char.IsWhiteSpace(sb[sb.Length - 1]))
                        {
                            break;
                        }
                        sb.Length--;
                    }
                }
                var innerRequest       = controller.InnerRequest;
                var httpRequestHeaders = innerRequest.Headers;
                var httpContentHeaders = innerRequest.Content == null ? null : innerRequest.Content.Headers;
                logHttpRequestStatsParam = new LogHttpRequestStatsParams(
                    sw,
                    new Lazy <HttpHeaders>(() => RavenBaseApiController.CloneRequestHttpHeaders(httpRequestHeaders, httpContentHeaders)),
                    controller.InnerRequest.Method.Method,
                    response != null ? (int)response.StatusCode : 500,
                    controller.InnerRequest.RequestUri.ToString(),
                    sb != null ? sb.ToString() : null,
                    controller.InnerRequestsCount
                    );
            }
            catch (Exception e)
            {
                Logger.WarnException("Could not gather information to log request stats", e);
            }

            if (logHttpRequestStatsParam == null || sw == null)
            {
                return;
            }

            sw.Stop();

            if (landlord.IsDatabaseLoaded(controller.TenantName ?? Constants.SystemDatabase))
            {
                controller.MarkRequestDuration(sw.ElapsedMilliseconds);
            }

            var curReq = Interlocked.Increment(ref reqNum);

            LogHttpRequestStats(controller, logHttpRequestStatsParam, controller.TenantName, curReq);

            if (controller.IsInternalRequest == false)
            {
                TraceTraffic(controller, logHttpRequestStatsParam, controller.TenantName);
            }

            RememberRecentRequests(logHttpRequestStatsParam, controller.TenantName);
        }
コード例 #34
0
        public bool TryAuthorize(RavenBaseApiController controller, bool ignoreDb, out HttpResponseMessage msg)
        {
            Func <HttpResponseMessage> onRejectingRequest;
            var tenantId    = controller.TenantName ?? Constants.SystemDatabase;
            var userCreated = TryCreateUser(controller, tenantId, out onRejectingRequest);

            if (server.SystemConfiguration.AnonymousUserAccessMode == AnonymousUserAccessMode.None && userCreated == false)
            {
                msg = onRejectingRequest();
                return(false);
            }

            PrincipalWithDatabaseAccess user = null;

            if (userCreated)
            {
                user = (PrincipalWithDatabaseAccess)controller.User;
                CurrentOperationContext.Headers.Value[Constants.RavenAuthenticatedUser] = controller.User.Identity.Name;
                CurrentOperationContext.User.Value = controller.User;

                // admins always go through
                if (user.Principal.IsAdministrator(server.SystemConfiguration.AnonymousUserAccessMode))
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                // backup operators can go through
                if (user.Principal.IsBackupOperator(server.SystemConfiguration.AnonymousUserAccessMode))
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }
            }

            bool isGetRequest = IsGetRequest(controller.InnerRequest.Method.Method, controller.InnerRequest.RequestUri.AbsolutePath);

            switch (server.SystemConfiguration.AnonymousUserAccessMode)
            {
            case AnonymousUserAccessMode.Admin:
            case AnonymousUserAccessMode.All:
                msg = controller.GetEmptyMessage();
                return(true);                        // if we have, doesn't matter if we have / don't have the user

            case AnonymousUserAccessMode.Get:
                if (isGetRequest)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }
                goto case AnonymousUserAccessMode.None;

            case AnonymousUserAccessMode.None:
                if (userCreated)
                {
                    if (string.IsNullOrEmpty(tenantId) || tenantId.StartsWith("fs/") == false)
                    {
                        if (user.AdminDatabases.Contains(tenantId) ||
                            user.AdminDatabases.Contains("*") || ignoreDb)
                        {
                            msg = controller.GetEmptyMessage();
                            return(true);
                        }
                        if (user.ReadWriteDatabases.Contains(tenantId) ||
                            user.ReadWriteDatabases.Contains("*"))
                        {
                            msg = controller.GetEmptyMessage();
                            return(true);
                        }
                        if (isGetRequest && (user.ReadOnlyDatabases.Contains(tenantId) ||
                                             user.ReadOnlyDatabases.Contains("*")))
                        {
                            msg = controller.GetEmptyMessage();
                            return(true);
                        }
                    }
                    else if (tenantId.StartsWith("fs/"))
                    {
                        tenantId = tenantId.Substring(3, tenantId.Length - "fs/".Length);

                        if (user.ReadWriteFileSystems.Contains(tenantId) ||
                            user.ReadWriteFileSystems.Contains("*"))
                        {
                            msg = controller.GetEmptyMessage();
                            return(true);
                        }
                        if (isGetRequest && (user.ReadOnlyFileSystems.Contains(tenantId) ||
                                             user.ReadOnlyFileSystems.Contains("*")))
                        {
                            msg = controller.GetEmptyMessage();
                            return(true);
                        }
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException("tenantId", "We don't know how to authorize unknown tenant id: " + tenantId);
                    }
                }

                msg = onRejectingRequest();
                return(false);

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
コード例 #35
0
        private PrincipalWithDatabaseAccess UpdateUserPrincipal(RavenBaseApiController controller, List<ResourceAccess> databaseAccessLists)
        {
            var access = controller.User as PrincipalWithDatabaseAccess;
            if (access != null)
                return access;

            var user = new PrincipalWithDatabaseAccess((WindowsPrincipal)controller.User);

            foreach (var databaseAccess in databaseAccessLists)
            {
                if (databaseAccess.Admin)
                    user.AdminDatabases.Add(databaseAccess.TenantId);
                else if (databaseAccess.ReadOnly)
                    user.ReadOnlyDatabases.Add(databaseAccess.TenantId);
                else
                    user.ReadWriteDatabases.Add(databaseAccess.TenantId);
            }

            controller.User = user;
            Thread.CurrentPrincipal = user;

            return user;
        }
コード例 #36
0
        public bool TryAuthorize(RavenBaseApiController controller, bool ignoreDb, out HttpResponseMessage msg)
		{
			Func<HttpResponseMessage> onRejectingRequest;
			var tenantId = controller.TenantName ?? Constants.SystemDatabase;
			var userCreated = TryCreateUser(controller, tenantId, out onRejectingRequest);
			if (server.SystemConfiguration.AnonymousUserAccessMode == AnonymousUserAccessMode.None && userCreated == false)
			{
				msg = onRejectingRequest();
				return false;
			}

			PrincipalWithDatabaseAccess user = null;
			if (userCreated)
			{
				user = (PrincipalWithDatabaseAccess)controller.User;
				CurrentOperationContext.Headers.Value[Constants.RavenAuthenticatedUser] = controller.User.Identity.Name;
				CurrentOperationContext.User.Value = controller.User;

				// admins always go through
				if (user.Principal.IsAdministrator(server.SystemConfiguration.AnonymousUserAccessMode))
				{
					msg = controller.GetEmptyMessage();
					return true;
				}

				// backup operators can go through
				if (user.Principal.IsBackupOperator(server.SystemConfiguration.AnonymousUserAccessMode))
				{
					msg = controller.GetEmptyMessage();
					return true;
				}
			}

			bool isGetRequest = IsGetRequest(controller.InnerRequest.Method.Method, controller.InnerRequest.RequestUri.AbsolutePath);
			switch (server.SystemConfiguration.AnonymousUserAccessMode)
			{
				case AnonymousUserAccessMode.Admin:
				case AnonymousUserAccessMode.All:
					msg = controller.GetEmptyMessage();
					return true; // if we have, doesn't matter if we have / don't have the user
				case AnonymousUserAccessMode.Get:
					if (isGetRequest)
					{
						msg = controller.GetEmptyMessage();
						return true;
					}
					goto case AnonymousUserAccessMode.None;
				case AnonymousUserAccessMode.None:
					if (userCreated)
					{
						if (string.IsNullOrEmpty(tenantId) == false && tenantId.StartsWith("fs/"))
							tenantId = tenantId.Substring(3);

						if (string.IsNullOrEmpty(tenantId) == false && tenantId.StartsWith("counters/"))
							tenantId = tenantId.Substring(9);

					    if (user.AdminDatabases.Contains(tenantId) ||
					        user.AdminDatabases.Contains("*") || ignoreDb)
					    {
					        msg = controller.GetEmptyMessage();
					        return true;
					    }
					    if (user.ReadWriteDatabases.Contains(tenantId) ||
					        user.ReadWriteDatabases.Contains("*"))
					    {
					        msg = controller.GetEmptyMessage();
					        return true;
					    }
					    if (isGetRequest && (user.ReadOnlyDatabases.Contains(tenantId) ||
					                            user.ReadOnlyDatabases.Contains("*")))
					    {
					        msg = controller.GetEmptyMessage();
					        return true;
					    }
					}

					msg = onRejectingRequest();
					return false;
				default:
					throw new ArgumentOutOfRangeException();
			}
		}
コード例 #37
0
		private void TraceTraffic(RavenBaseApiController controller, LogHttpRequestStatsParams logHttpRequestStatsParams, string databaseName)
		{
			if (HasAnyHttpTraceEventTransport() == false)
				return;

			NotifyTrafficWatch(
			new TrafficWatchNotification()
			{
				RequestUri = logHttpRequestStatsParams.RequestUri,
				ElapsedMilliseconds = logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds,
				CustomInfo = logHttpRequestStatsParams.CustomInfo,
				HttpMethod = logHttpRequestStatsParams.HttpMethod,
				ResponseStatusCode = logHttpRequestStatsParams.ResponseStatusCode,
				TenantName = NormalizeTennantName(databaseName),
				TimeStamp = SystemTime.UtcNow,
                InnerRequestsCount = logHttpRequestStatsParams.InnerRequestsCount
			}
			);
		}
コード例 #38
0
ファイル: RequestManager.cs プロジェクト: jrusbatch/ravendb
		private void LogHttpRequestStats(RavenBaseApiController controller, LogHttpRequestStatsParams logHttpRequestStatsParams, string databaseName, long curReq)
		{
			if (Logger.IsDebugEnabled == false)
				return;

			if (controller is StudioController || controller is HardRouteController || controller is SilverlightController)
				return;

			var message = string.Format(CultureInfo.InvariantCulture, "Request #{0,4:#,0}: {1,-7} - {2,5:#,0} ms - {5,-10} - {3} - {4}",
				curReq,
				logHttpRequestStatsParams.HttpMethod,
				logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds,
				logHttpRequestStatsParams.ResponseStatusCode,
				logHttpRequestStatsParams.RequestUri,
				databaseName);
			Logger.Debug(message);
			if (string.IsNullOrWhiteSpace(logHttpRequestStatsParams.CustomInfo) == false)
			{
				Logger.Debug(logHttpRequestStatsParams.CustomInfo);
			}
		}
コード例 #39
0
        HttpResponseMessage WriteAuthorizationChallenge(RavenBaseApiController controller, int statusCode, string error, string errorDescription)
		{
			var msg = controller.GetEmptyMessage();
			var systemConfiguration = controller.SystemConfiguration;
			if (string.IsNullOrEmpty(systemConfiguration.OAuthTokenServer) == false)
			{
				if (systemConfiguration.UseDefaultOAuthTokenServer == false)
				{
					controller.AddHeader("OAuth-Source", systemConfiguration.OAuthTokenServer, msg);
				}
				else
				{
					controller.AddHeader("OAuth-Source", new UriBuilder(systemConfiguration.OAuthTokenServer)
					{
						Host = controller.InnerRequest.RequestUri.Host,
						Port = controller.InnerRequest.RequestUri.Port
					}.Uri.ToString(), msg);

				}
			}
			msg.StatusCode = (HttpStatusCode)statusCode;
 
			msg.Headers.Add("WWW-Authenticate", string.Format("Bearer realm=\"Raven\", error=\"{0}\",error_description=\"{1}\"", error, errorDescription));

			return msg;
		}
コード例 #40
0
		// Cross-Origin Resource Sharing (CORS) is documented here: http://www.w3.org/TR/cors/
		public void AddAccessControlHeaders(RavenBaseApiController controller, HttpResponseMessage msg)
		{

			var accessControlAllowOrigin = landlord.SystemConfiguration.AccessControlAllowOrigin;
			if (accessControlAllowOrigin.Count == 0)
				return;

			var originHeader = controller.GetHeader("Origin");
			if (originHeader == null || originHeader.Contains(controller.InnerRequest.Headers.Host))
				return; // no need

			bool originAllowed = accessControlAllowOrigin.Contains("*") ||
								 accessControlAllowOrigin.Contains(originHeader);
			if (originAllowed)
			{
				controller.AddHeader("Access-Control-Allow-Origin", originHeader, msg);
			}
			if (controller.InnerRequest.Method.Method != "OPTIONS")
				return;

			controller.AddHeader("Access-Control-Allow-Credentials", "true", msg);
			controller.AddHeader("Access-Control-Max-Age", landlord.SystemConfiguration.AccessControlMaxAge, msg);
			controller.AddHeader("Access-Control-Allow-Methods", landlord.SystemConfiguration.AccessControlAllowMethods, msg);
			if (string.IsNullOrEmpty(landlord.SystemConfiguration.AccessControlRequestHeaders))
			{

				// allow whatever headers are being requested
				var hdr = controller.GetHeader("Access-Control-Request-Headers"); // typically: "x-requested-with"
				if (hdr != null)
					controller.AddHeader("Access-Control-Allow-Headers", hdr, msg);
			}
			else
			{
				controller.AddHeader("Access-Control-Request-Headers", landlord.SystemConfiguration.AccessControlRequestHeaders, msg);
			}
		}
コード例 #41
0
        static string GetToken(RavenBaseApiController controller)
		{
			const string bearerPrefix = "Bearer ";

			var auth = controller.GetHeader("Authorization");
			if (auth == null)
			{
				auth = controller.GetCookie("OAuth-Token");
				if (auth != null)
					auth = Uri.UnescapeDataString(auth);
			}
			if (auth == null || auth.Length <= bearerPrefix.Length ||
				!auth.StartsWith(bearerPrefix, StringComparison.OrdinalIgnoreCase))
				return null;

			var token = auth.Substring(bearerPrefix.Length, auth.Length - bearerPrefix.Length);

			return token;
		}
コード例 #42
0
	    // Cross-Origin Resource Sharing (CORS) is documented here: http://www.w3.org/TR/cors/
        public void AddAccessControlHeaders(RavenBaseApiController controller, HttpResponseMessage msg)
		{
			if (string.IsNullOrEmpty(landlord.SystemConfiguration.AccessControlAllowOrigin))
				return;

			controller.AddHeader("Access-Control-Allow-Credentials", "true", msg);

			bool originAllowed = landlord.SystemConfiguration.AccessControlAllowOrigin == "*" ||
					landlord.SystemConfiguration.AccessControlAllowOrigin.Split(' ')
						.Any(o => o == controller.GetHeader("Origin"));
			if (originAllowed)
			{
				controller.AddHeader("Access-Control-Allow-Origin", controller.GetHeader("Origin"), msg);
			}

			controller.AddHeader("Access-Control-Max-Age", landlord.SystemConfiguration.AccessControlMaxAge, msg);
			controller.AddHeader("Access-Control-Allow-Methods", landlord.SystemConfiguration.AccessControlAllowMethods, msg);
			if (string.IsNullOrEmpty(landlord.SystemConfiguration.AccessControlRequestHeaders))
			{
				// allow whatever headers are being requested
				var hdr = controller.GetHeader("Access-Control-Request-Headers"); // typically: "x-requested-with"
				if (hdr != null) 
					controller.AddHeader("Access-Control-Allow-Headers", hdr, msg);
			}
			else
			{
				controller.AddHeader("Access-Control-Request-Headers", landlord.SystemConfiguration.AccessControlRequestHeaders, msg);
			}
		}
コード例 #43
0
ファイル: RequestManager.cs プロジェクト: xinix00/ravendb
        private void FinalizeRequestProcessing(IResourceApiController controller, HttpResponseMessage response, Stopwatch sw)
        {
            LogHttpRequestStatsParams logHttpRequestStatsParam = null;

            try
            {
                StringBuilder sb = null;
                if (controller.CustomRequestTraceInfo != null && controller.CustomRequestTraceInfo.Count > 0)
                {
                    sb = new StringBuilder();
                    foreach (var action in controller.CustomRequestTraceInfo)
                    {
                        try
                        {
                            action(sb);
                        }
                        catch (Exception e)
                        {
                            Logger.WarnException("Could not gather information to log request stats custom info, so far got " + sb, e);
                        }
                        sb.AppendLine();
                    }
                    while (sb.Length > 0)
                    {
                        if (!char.IsWhiteSpace(sb[sb.Length - 1]))
                        {
                            break;
                        }
                        sb.Length--;
                    }
                }
                var innerRequest       = controller.InnerRequest;
                var httpRequestHeaders = innerRequest.Headers;
                var httpContentHeaders = innerRequest.Content == null ? null : innerRequest.Content.Headers;
                logHttpRequestStatsParam = new LogHttpRequestStatsParams(
                    sw,
                    new Lazy <HttpHeaders>(() => RavenBaseApiController.CloneRequestHttpHeaders(httpRequestHeaders, httpContentHeaders)),
                    controller.InnerRequest.Method.Method,
                    response != null ? (int)response.StatusCode : 500,
                    controller.InnerRequest.RequestUri.ToString(),
                    sb != null ? sb.ToString() : null,
                    controller.InnerRequestsCount
                    );
            }
            catch (Exception e)
            {
                Logger.WarnException("Could not gather information to log request stats", e);
            }

            if (logHttpRequestStatsParam == null || sw == null)
            {
                return;
            }

            sw.Stop();

            MarkRequestDuration(controller, sw.ElapsedMilliseconds);

            object requestNumber;

            if (controller.InnerRequest.Properties.TryGetValue("requestNum", out requestNumber) && requestNumber is long)
            {
                LogHttpRequestStats(controller, logHttpRequestStatsParam, controller.ResourceName, (long)requestNumber);
            }

            if (controller.IsInternalRequest == false)
            {
                TraceTraffic(controller, logHttpRequestStatsParam, controller.ResourceName, response);
            }

            RememberRecentRequests(logHttpRequestStatsParam, controller.ResourceName);
        }
コード例 #44
0
        private bool TryAuthorizeSingleUseAuthToken(RavenBaseApiController controller, string token, out HttpResponseMessage msg)
		{
            if (controller.WasAlreadyAuthorizedUsingSingleAuthToken)
            {
                msg = controller.GetEmptyMessage();
                return true;
            }

            object result;
            HttpStatusCode statusCode;
            IPrincipal user;
            var success = TryAuthorizeSingleUseAuthToken(token, controller.TenantName, out result, out statusCode, out user);
            controller.User = user;
            if (success == false)
                msg = controller.GetMessageWithObject(result, statusCode);
            else
                msg = controller.GetEmptyMessage();

            controller.WasAlreadyAuthorizedUsingSingleAuthToken = success;
            return success;
        }
コード例 #45
0
        public HttpTracePushContent(RavenBaseApiController controller)
		{
			Connected = true;
		}
コード例 #46
0
        private void FinalizeRequestProcessing(RavenBaseApiController controller, HttpResponseMessage response, Stopwatch sw)
		{
			LogHttpRequestStatsParams logHttpRequestStatsParam = null;
		    try
		    {
		        StringBuilder sb = null;
		        if (controller.CustomRequestTraceInfo != null)
		        {
		            sb = new StringBuilder();
                    foreach (var action in controller.CustomRequestTraceInfo)
                    {
                        action(sb);
                        sb.AppendLine();
                    }
		            while (sb.Length > 0)
		            {
		                if (!char.IsWhiteSpace(sb[sb.Length - 1])) 
                            break;
		                sb.Length--;
		            }
		        }
		        logHttpRequestStatsParam = new LogHttpRequestStatsParams(
		            sw,
		            GetHeaders(controller.InnerHeaders), 
		            controller.InnerRequest.Method.Method,
		            response != null ? (int) response.StatusCode : 500,
		            controller.InnerRequest.RequestUri.PathAndQuery,
		            sb != null ? sb.ToString() : null
		            );
		    }
		    catch (Exception e)
		    {
		        Logger.WarnException("Could not gather information to log request stats", e);
		    }

		    if (logHttpRequestStatsParam == null || sw == null)
				return;

			sw.Stop();

		    controller.MarkRequestDuration(sw.ElapsedMilliseconds);

			LogHttpRequestStats(logHttpRequestStatsParam, controller.TenantName);

			TraceRequest(logHttpRequestStatsParam, controller.TenantName);

		}
コード例 #47
0
        public bool TryAuthorize(RavenBaseApiController controller, bool hasApiKey, bool ignoreDbAccess, out HttpResponseMessage msg)
        {
            var isGetRequest = IsGetRequest(controller);
            var allowUnauthenticatedUsers = // we need to auth even if we don't have to, for bundles that want the user
                                            Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.All ||
                                            Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.Admin ||
                                            Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.Get &&
                                            isGetRequest;

            var token = GetToken(controller);

            if (token == null)
            {
                if (allowUnauthenticatedUsers)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                msg = WriteAuthorizationChallenge(controller, hasApiKey ? 412 : 401, "invalid_request", "The access token is required");

                return(false);
            }

            AccessTokenBody tokenBody;

            if (!AccessToken.TryParseBody(Settings.OAuthTokenKey, token, out tokenBody))
            {
                if (allowUnauthenticatedUsers)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                msg = WriteAuthorizationChallenge(controller, 401, "invalid_token", "The access token is invalid");

                return(false);
            }

            if (tokenBody.IsExpired())
            {
                if (allowUnauthenticatedUsers)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                msg = WriteAuthorizationChallenge(controller, 401, "invalid_token", "The access token is expired");

                return(false);
            }

            var writeAccess = isGetRequest == false;

            if (!tokenBody.IsAuthorized(controller.ResourceName, writeAccess))
            {
                if (allowUnauthenticatedUsers || ignoreDbAccess)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                msg = WriteAuthorizationChallenge(controller, 403, "insufficient_scope",
                                                  writeAccess ?
                                                  "Not authorized for read/write access for tenant " + controller.ResourceName :
                                                  "Not authorized for tenant " + controller.ResourceName);

                return(false);
            }

            controller.User = new OAuthPrincipal(tokenBody, controller.ResourceName);
            CurrentOperationContext.User.Value = controller.User;
            msg = controller.GetEmptyMessage();

            return(true);
        }
コード例 #48
0
        public bool TryAuthorize(RavenBaseApiController controller, bool hasApiKey, bool ignoreDbAccess, out HttpResponseMessage msg)
		{
			var isGetRequest = IsGetRequest(controller.InnerRequest.Method.Method, controller.InnerRequest.RequestUri.AbsolutePath);
			var allowUnauthenticatedUsers = // we need to auth even if we don't have to, for bundles that want the user 
				Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.All ||
				Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.Admin ||
					Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.Get &&
					isGetRequest;

			var token = GetToken(controller);

			if (token == null)
			{
				if (allowUnauthenticatedUsers)
				{
					msg = controller.GetEmptyMessage();
					return true;
				}

				msg = WriteAuthorizationChallenge(controller, hasApiKey ? 412 : 401, "invalid_request", "The access token is required");

				return false;
			}

			AccessTokenBody tokenBody;
			if (!AccessToken.TryParseBody(Settings.OAuthTokenKey, token, out tokenBody))
			{
				if (allowUnauthenticatedUsers)
				{
					msg = controller.GetEmptyMessage();
					return true;
				}

				msg = WriteAuthorizationChallenge(controller, 401, "invalid_token", "The access token is invalid");

				return false;
			}

			if (tokenBody.IsExpired())
			{
				if (allowUnauthenticatedUsers)
				{
					msg = controller.GetEmptyMessage();
					return true;
				}

				msg = WriteAuthorizationChallenge(controller, 401, "invalid_token", "The access token is expired");

				return false;
			}

			var writeAccess = isGetRequest == false;
            if (!tokenBody.IsAuthorized(controller.TenantName, writeAccess))
			{
				if (allowUnauthenticatedUsers || ignoreDbAccess)
				{
					msg = controller.GetEmptyMessage();
					return true;
				}

				msg = WriteAuthorizationChallenge(controller, 403, "insufficient_scope",
					writeAccess ?
                    "Not authorized for read/write access for tenant " + controller.TenantName :
					"Not authorized for tenant " + controller.TenantName);

				return false;
			}

            controller.User = new OAuthPrincipal(tokenBody, controller.TenantName);
			CurrentOperationContext.Headers.Value[Constants.RavenAuthenticatedUser] = tokenBody.UserId;
			CurrentOperationContext.User.Value = controller.User;
			msg = controller.GetEmptyMessage();

			return true;
		}
コード例 #49
0
ファイル: AdminLogsTarget.cs プロジェクト: heinnge/ravendb
        public AdminLogsConnectionState For(string id, RavenBaseApiController controller = null)
        {
            var connection = connections.GetOrAdd(
                id,
                _ =>
                {
                    IEventsTransport logsTransport = null;
                    if (controller != null)
                        logsTransport = new LogsPushContent(controller);

                    var connectionState = new AdminLogsConnectionState(logsTransport);
                    TimeSensitiveStore.Missing(id);
                    return connectionState;
                });

            AlterEnabled();
            return connection;
        }
コード例 #50
0
		public async Task<HttpResponseMessage> HandleActualRequest(RavenBaseApiController controller,
																   HttpControllerContext controllerContext,
																   Func<Task<HttpResponseMessage>> action,
																   Func<HttpException, HttpResponseMessage> onHttpException)
		{

			HttpResponseMessage response = null;
			cancellationToken.ThrowIfCancellationRequested();

			Stopwatch sw = Stopwatch.StartNew();
			try
			{
				Interlocked.Increment(ref concurrentRequests);

				if (controller.SetupRequestToProperDatabase(this))
				{
					if (controller.ResourceConfiguration.RejectClientsMode && controllerContext.Request.Headers.Contains(Constants.RavenClientVersion))
					{
						response = new HttpResponseMessage(HttpStatusCode.ServiceUnavailable)
						{
							Content = new StringContent("This service is not accepting clients calls")
						};
					}
					else
					{
						response = await action();
					}
				}
			}
			catch (HttpException httpException)
			{
				response = onHttpException(httpException);
			}

			finally
			{

				Interlocked.Decrement(ref concurrentRequests);
				try
				{
					FinalizeRequestProcessing(controller, response, sw);
				}

				catch (Exception e)
				{

					var aggregateException = e as AggregateException;
					if (aggregateException != null)
					{

						e = aggregateException.ExtractSingleInnerException();
					}

					Logger.ErrorException("Could not finalize request properly", e);
				}
			}
			return response;
		}
コード例 #51
0
        private bool TryCreateUser(RavenBaseApiController controller, string databaseName, out Func<HttpResponseMessage> onRejectingRequest)
		{
			var invalidUser = (controller.User == null || controller.User.Identity.IsAuthenticated == false);
			if (invalidUser)
			{
				onRejectingRequest = () =>
				{
					var msg = ProvideDebugAuthInfo(controller, new
					{
						Reason = "User is null or not authenticated"
					});
					controller.AddHeader("Raven-Required-Auth", "Windows", msg);
					if (string.IsNullOrEmpty(controller.SystemConfiguration.OAuthTokenServer) == false)
					{
						controller.AddHeader("OAuth-Source", controller.SystemConfiguration.OAuthTokenServer, msg);
					}
					msg.StatusCode = HttpStatusCode.Unauthorized;

					return msg;
				};
				return false;
			}

			var dbUsersIsAllowedAccessTo = requiredUsers
				.Where(data => controller.User.Identity.Name.Equals(data.Name, StringComparison.InvariantCultureIgnoreCase))
				.SelectMany(source => source.Databases)
				.Concat(requiredGroups.Where(data => controller.User.IsInRole(data.Name)).SelectMany(x => x.Databases))
				.ToList();

            var user = UpdateUserPrincipal(controller, dbUsersIsAllowedAccessTo);

			onRejectingRequest = () =>
			{
				var msg = ProvideDebugAuthInfo(controller, new
				{
					user.Identity.Name,
					user.AdminDatabases,
					user.ReadOnlyDatabases,
					user.ReadWriteDatabases,
					DatabaseName = databaseName
				});

				msg.StatusCode = HttpStatusCode.Forbidden;

				throw new HttpResponseException(msg);
			};
			return true;
		}
コード例 #52
0
		private void FinalizeRequestProcessing(RavenBaseApiController controller, HttpResponseMessage response, Stopwatch sw)
		{
			LogHttpRequestStatsParams logHttpRequestStatsParam = null;
			try
			{
				StringBuilder sb = null;
				if (controller.CustomRequestTraceInfo != null && controller.CustomRequestTraceInfo.Count > 0)
				{

					sb = new StringBuilder();
					foreach (var action in controller.CustomRequestTraceInfo)
					{
						action(sb);
						sb.AppendLine();
					}
					while (sb.Length > 0)
					{

						if (!char.IsWhiteSpace(sb[sb.Length - 1]))
							break;
						sb.Length--;
					}
				}

				logHttpRequestStatsParam = new LogHttpRequestStatsParams(
					sw,
					GetHeaders(controller.InnerHeaders),
					controller.InnerRequest.Method.Method,
					response != null ? (int)response.StatusCode : 500,
					controller.InnerRequest.RequestUri.ToString(),
					sb != null ? sb.ToString() : null,
                    controller.InnerRequestsCount
					);
			}


			catch (Exception e)
			{

				Logger.WarnException("Could not gather information to log request stats", e);
			}

			if (logHttpRequestStatsParam == null || sw == null)
				return;

			sw.Stop();

			if (landlord.IsDatabaseLoaded(controller.TenantName ?? Constants.SystemDatabase))
			{
				controller.MarkRequestDuration(sw.ElapsedMilliseconds);
			}

			var curReq = Interlocked.Increment(ref reqNum);

			LogHttpRequestStats(controller, logHttpRequestStatsParam, controller.TenantName, curReq);

            if (controller.IsInternalRequest == false)
            {
                TraceTraffic(controller, logHttpRequestStatsParam, controller.TenantName);    
            }

			RememberRecentRequests(logHttpRequestStatsParam, controller.TenantName);
		}
コード例 #53
0
        private static HttpResponseMessage ProvideDebugAuthInfo(RavenBaseApiController controller, object msg)
		{
			string debugAuth = controller.GetQueryStringValue("debug-auth");
			if (debugAuth == null)
				return controller.GetEmptyMessage();

			bool shouldProvideDebugAuthInformation;
			if (bool.TryParse(debugAuth, out shouldProvideDebugAuthInformation) && shouldProvideDebugAuthInformation)
			{
				return controller.GetMessageWithObject(msg);
			}

			return controller.GetEmptyMessage();
		}
コード例 #54
0
		private void LogHttpRequestStats(RavenBaseApiController controller, LogHttpRequestStatsParams logHttpRequestStatsParams, string databaseName, long curReq)
		{
			if (Logger.IsDebugEnabled == false)
				return;

			if (controller is StudioController || controller is HardRouteController || controller is SilverlightController)
				return;

			// we filter out requests for the UI because they fill the log with information
			// we probably don't care about them anyway. That said, we do output them if they take too
			// long.
			if (logHttpRequestStatsParams.Headers["Raven-Timer-Request"] == "true" &&
				logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds <= 25)
				return;

			var message = string.Format(CultureInfo.InvariantCulture, "Request #{0,4:#,0}: {1,-7} - {2,5:#,0} ms - {5,-10} - {3} - {4}",
				curReq,
				logHttpRequestStatsParams.HttpMethod,
				logHttpRequestStatsParams.Stopwatch.ElapsedMilliseconds,
				logHttpRequestStatsParams.ResponseStatusCode,
				logHttpRequestStatsParams.RequestUri,
				databaseName);
			Logger.Debug(message);
			if (string.IsNullOrWhiteSpace(logHttpRequestStatsParams.CustomInfo) == false)
			{
				Logger.Debug(logHttpRequestStatsParams.CustomInfo);
			}
		}
コード例 #55
0
ファイル: TransportState.cs プロジェクト: j2jensen/ravendb
 public ConnectionState For(string id, RavenBaseApiController controller = null)
 {
     return connections.GetOrAdd(id, _ =>
     {
         IEventsTransport eventsTransport = null;
         if (controller != null)
             eventsTransport = new ChangesPushContent(controller);
         
         var connectionState = new ConnectionState(eventsTransport);
         TimeSensitiveStore.Missing(id);
         return connectionState;
     });
 }