예제 #1
0
        /// <summary>
        /// Gets a specific event by ID.
        /// </summary>
        /// <returns></returns>
        public ActionResult GetEvent()
        {
            GetEventRequest request = ApiRequestBase.ParseRequest <GetEventRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            Event ev = null;

            using (DB db = new DB(p.Name))
            {
                ev = db.GetEvent(request.eventId);
                if (ev != null)
                {
                    db.AddReadState(session.GetUser().UserId, ev.EventId);
                }
            }
            if (ev != null)
            {
                GetEventDataResponse response = new GetEventDataResponse();
                response.ev = ev;
                response.eventListCustomTagKey = session.GetUser().GetEventListCustomTagKey(p.Name);
                return(Json(response));
            }
            return(ApiError("Unable to find event with ID " + request.eventId));
        }
예제 #2
0
        public ActionResult AddFilter()
        {
            AddFilterRequest request = ApiRequestBase.ParseRequest <AddFilterRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (DB db = new DB(p.Name))
            {
                Filter newFilter = new Filter();
                newFilter.Name = request.name;
                if (Enum.IsDefined(typeof(ConditionHandling), request.conditionHandling))
                {
                    newFilter.ConditionHandling = request.conditionHandling;
                }
                if (db.AddFilter(newFilter, request.conditions, out string errorMessage))
                {
                    Logger.Info("[" + p.Name + "] Filter " + newFilter.FilterId + " (\"" + newFilter.Name + "\") was added by \"" + session.userName + "\"");
                    return(Json(new ApiResponseBase(true)));
                }
                else
                {
                    return(ApiError(errorMessage));
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Gets all login records within a time range, ordered by Date descending.  Session must have admin privilege.
        /// </summary>
        /// <returns></returns>
        public ActionResult GeolocateIP()
        {
            GeolocateIPRequest request = ApiRequestBase.ParseRequest <GeolocateIPRequest>(this);

            if (IPAddress.TryParse(request.ip, out IPAddress ip))
            {
                string url = Settings.data.geolocationWebServiceBaseUrl;
                if (string.IsNullOrWhiteSpace(url))
                {
                    return(ApiError("The geolocation web service endpoint is not configured."));
                }
                if (!url.EndsWith("/"))
                {
                    url += "/";
                }
                url += "embed/" + ip.ToString();
                BpWebResponse proxyResponse = proxyClient.GET(url);
                return(Json(new GeolocateIPResponse()
                {
                    html = proxyResponse.str
                }));
            }
            else
            {
                return(ApiError("Invalid IP Address"));
            }
        }
예제 #4
0
        public ActionResult FinishChange()
        {
            ChangePasswordRequest request = ApiRequestBase.ParseRequest <ChangePasswordRequest>(this);

            byte[] challenge = session.authChallenge;
            if (challenge == null || challenge.Length == 0)
            {
                return(ApiError("Missing session state.  Please retry."));
            }

            User user = session.GetUser();

            if (user.AuthenticateUser(request.oldPwToken, challenge))
            {
                byte[] newPwTokenBytes    = Hex.ToByteArray(request.newPwToken);
                byte[] encryptionKey      = Hash.GetSHA512Bytes(user.PasswordHash, challenge);
                byte[] decryptedNewPwHash = ByteUtil.XORByteArrays(encryptionKey, newPwTokenBytes);
                user.PasswordHash = Hash.GetSHA512Bytes(decryptedNewPwHash);
                Settings.data.Save();

                session.authChallenge = null;

                return(Json(new ApiResponseBase(true)));
            }
            else
            {
                return(ApiError("Old password was incorrect."));
            }
        }
예제 #5
0
        public ActionResult AddProject()
        {
            ProjectRequest request = ApiRequestBase.ParseRequest <ProjectRequest>(this);

            if (string.IsNullOrWhiteSpace(request.projectName) || !StringUtil.IsAlphaNumericOrUnderscore(request.projectName))
            {
                return(Json(new ApiResponseBase(false, "project name is invalid")));
            }

            request.projectName = request.projectName.Trim();
            if (request.projectName.Length > 64)
            {
                return(Json(new ApiResponseBase(false, "project name is too long. Max length: 64 characters.")));
            }

            Project p = new Project();

            p.Name = request.projectName;
            p.InitializeSubmitKey();
            if (Settings.data.TryAddProject(p))
            {
                Settings.data.Save();
                Logger.Info("Project \"" + request.projectName + "\" was added by \"" + session.userName + "\"");
                return(Json(new ApiResponseBase(true)));
            }
            else
            {
                return(Json(new ApiResponseBase(false, "project name is already taken")));
            }
        }
예제 #6
0
파일: Auth.cs 프로젝트: bp2008/ErrorTracker
        public ActionResult Logout()
        {
            ApiRequestBase args = ApiRequestBase.ParseRequest <ApiRequestBase>(this);

            SessionManager.RemoveSession(args.sid);
            return(Json(new ApiResponseBase(true)));
        }
예제 #7
0
        public ActionResult SetSettingsData()
        {
            SetSettingsRequest request = ApiRequestBase.ParseRequest <SetSettingsRequest>(this);

            bool requiresRestart = false;

            Settings.data.systemName = request.settings.systemName;
            if (Settings.data.port_http != request.settings.port_http)
            {
                Settings.data.port_http = request.settings.port_http;
                requiresRestart         = true;
            }
            if (Settings.data.port_https != request.settings.port_https)
            {
                Settings.data.port_https = request.settings.port_https;
                requiresRestart          = true;
            }
            Settings.data.appPath = request.settings.appPath;
            if (Settings.data.certificatePath != request.settings.certificatePath)
            {
                Settings.data.certificatePath = request.settings.certificatePath;
                requiresRestart = true;
            }
            if (Settings.data.certificatePassword != request.settings.certificatePassword)
            {
                Settings.data.certificatePassword = request.settings.certificatePassword;
                requiresRestart = true;
            }
            Settings.data.loginStyle = request.settings.loginStyle.ToString();
            Settings.data.geolocationWebServiceBaseUrl = request.settings.geolocationWebServiceBaseUrl.ToString();
            Settings.data.trustedProxyIPs      = request.settings.trustedProxyIPs;
            Settings.data.useXRealIP           = request.settings.useXRealIP;
            Settings.data.useXForwardedFor     = request.settings.useXForwardedFor;
            Settings.data.smtpHost             = request.settings.smtpHost;
            Settings.data.smtpPort             = request.settings.smtpPort;
            Settings.data.smtpSsl              = request.settings.smtpSsl;
            Settings.data.smtpUser             = request.settings.smtpUser;
            Settings.data.smtpPass             = request.settings.smtpPass;
            Settings.data.smtpSendFrom         = request.settings.smtpSendFrom;
            Settings.data.defaultErrorEmail    = request.settings.defaultErrorEmail;
            Settings.data.verboseSubmitLogging = request.settings.verboseSubmitLogging;
            Settings.data.serviceWorkerEnabled = request.settings.serviceWorkerEnabled;
            Settings.data.Save();

            SetSettingsResponse response = new SetSettingsResponse(true, null);

            if (requiresRestart)
            {
                response.message = "Some changes will take effect the next time the web server is restarted.";
            }
            return(Json(response));
        }
예제 #8
0
        public ActionResult RunEnabledFiltersAgainstAllEvents()
        {
            ProjectRequestBase request = ApiRequestBase.ParseRequest <ProjectRequestBase>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (FilterEngine fe = new FilterEngine(request.projectName))
                fe.RunEnabledFiltersAgainstAllEvents();
            return(Json(new ApiResponseBase(true)));
        }
예제 #9
0
        public ActionResult RunFilterAgainstAllEvents()
        {
            OneFilterRequest request = ApiRequestBase.ParseRequest <OneFilterRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (FilterEngine fe = new FilterEngine(request.projectName))
                fe.RunFilterAgainstAllEvents(request.filterId, true);
            return(Json(new ApiResponseBase(true)));
        }
예제 #10
0
        /// <summary>
        /// Sets the custom tag to be included in event summaries provided to this user. Set null to unset the preference.
        /// </summary>
        /// <returns></returns>
        public ActionResult SetEventListCustomTagKey()
        {
            SetEventListCustomTagKeyRequest request = ApiRequestBase.ParseRequest <SetEventListCustomTagKeyRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            session.GetUser().SetEventListCustomTagKey(p.Name, request.eventListCustomTagKey);
            Settings.data.Save();

            return(Json(new ApiResponseBase(true)));
        }
예제 #11
0
        public ActionResult GetAllFilters()
        {
            ProjectRequestBase request = ApiRequestBase.ParseRequest <ProjectRequestBase>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            GetAllFiltersResponse response = new GetAllFiltersResponse();

            using (DB db = new DB(p.Name))
                response.filters = db.GetAllFiltersSummary();
            return(Json(response));
        }
예제 #12
0
        /// <summary>
        /// Gets all login records for the specified user, ordered by Date descending.  Session must have admin privilege.
        /// </summary>
        /// <returns></returns>
        public ActionResult GetLoginRecordsForUser()
        {
            if (!session.IsAdminValid)
            {
                return(ApiError("Not Authorized"));
            }

            LoginRecordsByUserNameRequest request = ApiRequestBase.ParseRequest <LoginRecordsByUserNameRequest>(this);

            using (GlobalDb db = new GlobalDb())
                return(Json(new LoginRecordsResponse()
                {
                    records = db.GetLoginRecordsByUserName(request.userName)
                }));
        }
예제 #13
0
        public ActionResult AddFolder()
        {
            AddFolderRequest request = ApiRequestBase.ParseRequest <AddFolderRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (DB db = new DB(p.Name))
            {
                if (db.AddFolder(request.folderName, request.parentFolderId, out string errorMessage, out Folder newFolder))
                {
                    return(Json(new ApiResponseBase(true)));
                }
예제 #14
0
        /// <summary>
        /// Gets all login records within a time range, ordered by Date descending.  Session must have admin privilege.
        /// </summary>
        /// <returns></returns>
        public ActionResult GetLoginRecordsGlobal()
        {
            if (!session.IsAdminValid)
            {
                return(ApiError("Not Authorized"));
            }

            LoginRecordsGlobalRequest request = ApiRequestBase.ParseRequest <LoginRecordsGlobalRequest>(this);

            using (GlobalDb db = new GlobalDb())
                return(Json(new LoginRecordsResponse()
                {
                    records = db.GetLoginRecordsGlobal(request.startDate, request.endDate)
                }));
        }
예제 #15
0
        public ActionResult GetFilter()
        {
            OneFilterRequest request = ApiRequestBase.ParseRequest <OneFilterRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            GetFilterResponse response = new GetFilterResponse();

            using (DB db = new DB(p.Name))
                response.filter = db.GetFilter(request.filterId);
            return(Json(response));
        }
예제 #16
0
        public ActionResult GetFolderStructure()
        {
            ProjectRequestBase request = ApiRequestBase.ParseRequest <ProjectRequestBase>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            GetFolderStructureResponse response = new GetFolderStructureResponse();

            using (DB db = new DB(p.Name))
                response.root = db.GetFolderStructure();
            return(Json(response));
        }
예제 #17
0
        /// <summary>
        /// Gets the number of unread events in every folder that contains unread events.
        /// </summary>
        /// <returns></returns>
        public ActionResult CountUnreadEventsByFolder()
        {
            ProjectRequestBase request = ApiRequestBase.ParseRequest <ProjectRequestBase>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (DB db = new DB(p.Name))
            {
                Dictionary <int, uint> folderIdToUnreadEventCount = db.CountUnreadEventsByFolder(session.GetUser().UserId);
                return(Json(new CountUnreadEventsByFolderResponse(folderIdToUnreadEventCount)));
            }
        }
예제 #18
0
        public ActionResult GetRegistrationStatus()
        {
            PushRegistrationRequest request = ApiRequestBase.ParseRequest <PushRegistrationRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            User user = session.GetUser();

            string[] keys       = user.GetPushNotificationSubscriptions(request.projectName, request.folderId);
            bool     subscribed = keys.Contains(request.subscriptionKey);

            return(Json(new GetRegistrationStatusResponse(subscribed)));
        }
예제 #19
0
        public ActionResult UnregisterForPush()
        {
            PushRegistrationRequest request = ApiRequestBase.ParseRequest <PushRegistrationRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            User user = session.GetUser();

            user.SetPushNotificationSubscription(request.projectName, request.folderId, request.subscriptionKey, false);
            Settings.data.Save();

            return(Json(new ApiResponseBase(true)));
        }
예제 #20
0
        public ActionResult ReorderFilters()
        {
            ReorderFiltersRequest request = ApiRequestBase.ParseRequest <ReorderFiltersRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (DB db = new DB(p.Name))
            {
                db.ReorderFilters(request.newOrder);
            }
            Logger.Info("[" + p.Name + "] Filters reordered by \"" + session.userName + "\"");
            return(Json(new ApiResponseBase(true)));
        }
예제 #21
0
        public ActionResult ReplaceSubmitKey()
        {
            ProjectRequest request = ApiRequestBase.ParseRequest <ProjectRequest>(this);

            Project p = Settings.data.GetProject(request.projectName);

            if (p == null)
            {
                return(Json(new ApiResponseBase(false, "project could not be found")));
            }

            p.InitializeSubmitKey();
            Settings.data.Save();

            Logger.Info("Project \"" + request.projectName + "\" had its submit key replaced by \"" + session.userName + "\"");
            return(Json(new ApiResponseBase(true)));
        }
예제 #22
0
        /// <summary>
        /// Sets the color of events by ID.
        /// </summary>
        /// <returns></returns>
        public ActionResult SetEventsColor()
        {
            SetEventsColorRequest request = ApiRequestBase.ParseRequest <SetEventsColorRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (DB db = new DB(p.Name))
            {
                if (db.SetEventsColor(request.eventIds, request.color))
                {
                    return(Json(new ApiResponseBase(true)));
                }
                return(ApiError("Unable to delete all events with IDs " + string.Join(",", request.eventIds)));
            }
        }
예제 #23
0
        /// <summary>
        /// Move events by ID to a new folder by ID.
        /// </summary>
        /// <returns></returns>
        public ActionResult MoveEvents()
        {
            MoveEventsRequest request = ApiRequestBase.ParseRequest <MoveEventsRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (DB db = new DB(p.Name))
            {
                if (db.MoveEvents(request.eventIds, request.newFolderId))
                {
                    return(Json(new ApiResponseBase(true)));
                }
                return(ApiError("Unable to move all events with IDs " + string.Join(",", request.eventIds)));
            }
        }
예제 #24
0
        /// <summary>
        /// May allow or disallow access to the controller.  This is called before the client-specified action method is called.
        /// </summary>
        /// <param name="result">If authorization fails, this should be set to an appropriate result such as an HTTP 403 Forbidden response. If null, authorization will be assumed to have succeeded.</param>
        public override void OnAuthorization(ref ActionResult result)
        {
            base.OnAuthorization(ref result);
            if (result != null)
            {
                return;
            }
            ApiRequestBase args = ApiRequestBase.ParseRequest <ApiRequestBase>(this);

            session = args.GetSession();
            if (session == null)
            {
                result = StatusCode("403 Forbidden");
            }
            else if (!session.IsAuthValid)
            {
                result = StatusCode("418 Insufficient Privilege");
            }
        }
예제 #25
0
        public ActionResult InitiateRequest()
        {
            if (!Emailer.Enabled)
            {
                return(ApiError("This server does not have email configured. Therefore, this function is not usable."));
            }

            if (requestLimiterByIP.Get(Context.httpProcessor.RemoteIPAddressStr))
            {
                return(ApiError("A password reset request was recently initiated from " + Context.httpProcessor.RemoteIPAddressStr + ". Rate-limiting is in effect. Please wait " + TimeSpan.FromMinutes(minutesBetweenRequestsByIp).TotalSeconds + " seconds between requests."));
            }
            requestLimiterByIP.Add(Context.httpProcessor.RemoteIPAddressStr, true);

            ForgotPasswordRequest     request  = ApiRequestBase.ParseRequest <ForgotPasswordRequest>(this);
            ErrorTrackerPasswordReset resetter = new ErrorTrackerPasswordReset();
            PasswordResetRequest      req      = resetter.GetResetRequest(request.accountIdentifier);

            if (req != null)
            {
                if (requestLimiterByUsername.Get(req.accountIdentifier))
                {
                    return(ApiError("A password reset request was recently received for this user. Rate-limiting is in effect. Please wait " + TimeSpan.FromMinutes(minutesBetweenRequestsByName).TotalMinutes + " minutes between requests."));
                }
                requestLimiterByUsername.Add(req.accountIdentifier, true);
                StringBuilder sb = new StringBuilder();
                sb.Append("Hello ");
                sb.Append(req.displayName);
                sb.Append(",\r\n\r\n");
                sb.Append("Someone at the address \"" + Context.httpProcessor.RemoteIPAddressStr
                          + "\" has requested a reset of your password at \"" + Settings.data.systemName
                          + "\". If you did not make this request, you can ignore this message and your password will not be changed.\r\n\r\n");
                sb.Append("Here is your Security Code:\r\n\r\n");
                sb.Append("-----------------------------\r\n");
                sb.Append(req.secureToken);
                sb.Append("\r\n-----------------------------");
                sb.Append("\r\n\r\nCopy it to the \"Password Recovery\" page and a new password will be emailed to you.  This code expires in ");
                sb.Append((int)req.tokenExpiration.TotalMinutes);
                sb.Append(" minutes.\r\n\r\n(This email is automated.  Please do not reply.)");
                Emailer.SendEmail(req.email, Settings.data.systemName + " Password Recovery", sb.ToString(), false);
            }
            return(Json(new ApiResponseBase(true)));
        }
예제 #26
0
        public ActionResult SearchAdvanced()
        {
            SearchAdvancedRequest request = ApiRequestBase.ParseRequest <SearchAdvancedRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            SearchResultsResponse response = new SearchResultsResponse();

            using (FilterEngine fe = new FilterEngine(p.Name))
            {
                HashSet <long> readEventIds = new HashSet <long>(fe.db.GetAllReadEventIds(session.GetUser().UserId));

                response.events = fe.AdvancedSearch(request.conditions, request.matchAll, request.folderId, session.GetUser().GetEventListCustomTagKey(p.Name))
                                  .Select(ev => ProduceEventSummary(ev, readEventIds))
                                  .ToList();
            }
            return(Json(response));
        }
예제 #27
0
        public ActionResult RemoveProject()
        {
            ProjectRequest request = ApiRequestBase.ParseRequest <ProjectRequest>(this);
            Project        p       = Settings.data.GetProject(request.projectName);

            if (p == null)
            {
                return(Json(new ApiResponseBase(false, "project could not be found")));
            }

            if (Settings.data.TryRemoveProject(request.projectName) != null)
            {
                Settings.data.Save();
                Logger.Info("Project \"" + request.projectName + "\" was deleted by \"" + session.userName + "\"");
                return(Json(new ApiResponseBase(true)));
            }
            else
            {
                return(Json(new ApiResponseBase(false, "project could not be found")));
            }
        }
예제 #28
0
        public ActionResult AddCondition()
        {
            OneFilterConditionRequest request = ApiRequestBase.ParseRequest <OneFilterConditionRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (DB db = new DB(p.Name))
            {
                if (db.AddFilterCondition(request.condition, out string errorMessage))
                {
                    Logger.Info("[" + p.Name + "] Filter condition " + request.condition.FilterConditionId + " was added by \"" + session.userName + "\"");
                    return(Json(new ApiResponseBase(true)));
                }
                else
                {
                    return(ApiError(errorMessage));
                }
            }
        }
예제 #29
0
        /// <summary>
        /// Updates a filter and all attached conditions and actions.  This method cannot be used to add or remove conditions or actions, or to update filter properties separately from conditions and actions.
        /// </summary>
        /// <returns></returns>
        public ActionResult EditFilter()
        {
            EditFilterRequest request = ApiRequestBase.ParseRequest <EditFilterRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (DB db = new DB(p.Name))
            {
                if (db.EditFilter(request.filter, out string errorMessage))
                {
                    Logger.Info("[" + p.Name + "] Filter " + request.filter.filter.FilterId + " (\"" + request.filter.filter.Name + "\") was edited by \"" + session.userName + "\"");
                    return(Json(new ApiResponseBase(true)));
                }
                else
                {
                    return(ApiError(errorMessage));
                }
            }
        }
예제 #30
0
        public ActionResult DeleteAction()
        {
            OneFilterActionRequest request = ApiRequestBase.ParseRequest <OneFilterActionRequest>(this);

            if (!request.Validate(out Project p, out ApiResponseBase error))
            {
                return(Json(error));
            }

            using (DB db = new DB(p.Name))
            {
                if (db.DeleteFilterAction(request.action.FilterActionId))
                {
                    Logger.Info("[" + p.Name + "] Filter action " + request.action.FilterActionId + " was deleted by \"" + session.userName + "\"");
                    return(Json(new ApiResponseBase(true)));
                }
                else
                {
                    return(ApiError("Unable to delete filter action " + request.action.FilterActionId));
                }
            }
        }