private static string[] PurgeUrlFromProxy(string url, bool async) { // PURGE /contentem/maicontent.jpg HTTP/1.1 // Host: myhost.hu if (string.IsNullOrEmpty(url)) { throw new ArgumentNullException("url"); } if (WebApplication.ProxyIPs.Count == 0) { return(null); } string contentPath; string host; var slashIndex = url.IndexOf("/"); if (slashIndex >= 0) { contentPath = url.Substring(slashIndex); host = url.Substring(0, slashIndex); } else { contentPath = "/"; host = url; } if (string.IsNullOrEmpty(host) && HttpContext.Current != null) { host = HttpContext.Current.Request.Url.Host; } string[] result = null; if (!async) { result = new string[WebApplication.ProxyIPs.Count]; } var proxyIndex = 0; foreach (var proxyIP in WebApplication.ProxyIPs) { var proxyUrl = string.Concat("http://", proxyIP, contentPath); try { var request = WebRequest.Create(proxyUrl) as HttpWebRequest; if (request == null) { break; } request.Method = "PURGE"; request.Host = host; if (!async) { using (request.GetResponse()) { // we do not need to read the request here, just the status code result[proxyIndex] = "OK"; } } else { request.BeginGetResponse(null, null); } } catch (WebException wex) { var wr = wex.Response as HttpWebResponse; if (wr != null && !async) { switch (wr.StatusCode) { case HttpStatusCode.NotFound: result[proxyIndex] = "MISS"; break; case HttpStatusCode.OK: result[proxyIndex] = "OK"; break; default: SnLog.WriteException(wex); result[proxyIndex] = wex.Message; break; } } else { SnLog.WriteException(wex); if (!async) { result[proxyIndex] = wex.Message; } } } proxyIndex++; } return(result); }
protected void BtnSave_Click(object sender, EventArgs args) { _contentView.UpdateContent(); var content = _contentView.Content; if (!_contentView.IsUserInputValid || !content.IsValid) { return; } if (!this.HasPermission) { _contentView.ContentException = new SenseNetSecurityException(HttpContext.GetGlobalResourceObject("Notification", "NotEnoughPermissions") as string); return; } Subscription subscription; if (IsSubscriptionNew) { subscription = new Subscription { IsActive = true, ContentPath = (string)content["ContentPath"], Frequency = (NotificationFrequency)Enum.Parse(typeof(NotificationFrequency), (content["Frequency"] as List <String>)[0]), UserEmail = (string)content["UserEmail"], UserId = (int)(decimal)content["UserId"], UserName = (string)content["UserName"], UserPath = (string)content["UserPath"], Language = (content["Language"] as List <String>)[0], SitePath = PortalContext.Current.Site.Path, SiteUrl = PortalContext.Current.SiteUrl }; } else { subscription = new Subscription { IsActive = (bool)content["IsActive"], ContentPath = (string)content["ContentPath"], Frequency = (NotificationFrequency)Enum.Parse(typeof(NotificationFrequency), (content["Frequency"] as List <String>)[0]), UserEmail = (string)content["UserEmail"], UserId = (int)(decimal)content["UserId"], UserName = (string)content["UserName"], UserPath = (string)content["UserPath"], Language = (content["Language"] as List <String>)[0], SitePath = PortalContext.Current.Site.Path, SiteUrl = PortalContext.Current.SiteUrl }; } try { subscription.Save(); CallDone(false); } catch (Exception ex) // logged { SnLog.WriteException(ex); _contentView.ContentException = ex; } }
public override object Execute(Content content, params object[] parameters) { var targetPath = (string)parameters[0]; var targetNode = Node.LoadNode(targetPath); if (targetNode == null) { throw new ContentNotFoundException(targetPath); } if (!(parameters[1] is object[] ids)) { throw new InvalidOperationException("No content identifiers provided."); } var results = new List <object>(); var errors = new List <ErrorContent>(); var identifiers = ids.Select(NodeIdentifier.Get).ToList(); var foundIdentifiers = new List <NodeIdentifier>(); var nodes = Node.LoadNodes(identifiers); foreach (var node in nodes) { try { // Collect already found identifiers in a separate list otherwise the error list // would contain multiple errors for the same content. foundIdentifiers.Add(NodeIdentifier.Get(node)); node.MoveTo(targetNode); results.Add(new { node.Id, node.Path, node.Name }); } catch (Exception e) { //TODO: we should log only relevant exceptions here and skip // business logic-related errors, e.g. lack of permissions or // existing target content path. SnLog.WriteException(e); errors.Add(new ErrorContent { Content = new { node?.Id, node?.Path, node?.Name }, Error = new Error { Code = "NotSpecified", ExceptionType = e.GetType().FullName, InnerError = new StackInfo { Trace = e.StackTrace }, Message = new ErrorMessage { Lang = System.Globalization.CultureInfo.CurrentUICulture.Name.ToLower(), Value = e.Message } } }); } } // iterating through the missing identifiers and making error items for them errors.AddRange(identifiers.Where(id => !foundIdentifiers.Exists(f => f.Id == id.Id || f.Path == id.Path)) .Select(missing => new ErrorContent { Content = new { missing?.Id, missing?.Path }, Error = new Error { Code = "ResourceNotFound", ExceptionType = "ContentNotFoundException", InnerError = null, Message = new ErrorMessage { Lang = System.Globalization.CultureInfo.CurrentUICulture.Name.ToLower(), Value = string.Format(SNSR.GetString(SNSR.Exceptions.OData.ErrorContentNotFound), missing?.Path) } } })); return(BatchActionResponse.Create(results, errors, results.Count + errors.Count)); }
protected virtual void Application_Error(object sender, EventArgs e, HttpApplication application) { int?originalHttpCode = null; var ex = application.Server.GetLastError(); var httpException = ex as HttpException; if (httpException != null) { originalHttpCode = httpException.GetHttpCode(); } var unknownActionException = ex as UnknownActionException; if (unknownActionException != null) { SnTrace.Web.Write("UnknownActionException: " + unknownActionException.Message); originalHttpCode = 404; } // if httpcode is contained in the dontcare list (like 404), don't log the exception var skipLogException = originalHttpCode.HasValue && dontCareErrorCodes.Contains(originalHttpCode.Value); if (!skipLogException) { try { SnLog.WriteException(ex); } catch { // if logging failed, cannot do much at this point } } if (ex.InnerException?.StackTrace != null && (ex.InnerException.StackTrace.IndexOf("System.Web.UI.PageParser.GetCompiledPageInstanceInternal", StringComparison.InvariantCulture) != -1)) { return; } if (HttpContext.Current == null) { return; } HttpResponse response; try { response = HttpContext.Current.Response; } catch (Exception) { response = null; } response?.Headers.Remove("Content-Disposition"); // HACK: HttpAction.cs (and possibly StaticFileHandler) throws 404 and 403 HttpExceptions. // These are not exceptions to be displayed, but "fake" exceptions to handle 404 and 403 requests. // Therefore, here we set the statuscode and return, no further logic is executed. if (originalHttpCode.HasValue && (originalHttpCode == 404 || originalHttpCode == 403)) { if (response != null) { response.StatusCode = originalHttpCode.Value; } HttpContext.Current.ClearError(); HttpContext.Current.ApplicationInstance.CompleteRequest(); return; } var errorPageHtml = string.Empty; var exception = ex; if (exception.InnerException != null) { exception = exception.InnerException; } var statusCode = GetStatusCode(exception); if (response != null) { if (!HttpContext.Current.Request.Url.AbsoluteUri.StartsWith("http://localhost")) { if (originalHttpCode.HasValue) { response.StatusCode = originalHttpCode.Value; } // If there is a specified status code in statusCodeString then set Response.StatusCode to it. // Otherwise go on to global error page. if (statusCode != null) { application.Response.StatusCode = statusCode.StatusCode; application.Response.SubStatusCode = statusCode.SubStatusCode; response.Clear(); HttpContext.Current.ClearError(); HttpContext.Current.ApplicationInstance.CompleteRequest(); return; } application.Response.TrySkipIisCustomErrors = true; // keeps our custom error page defined below instead of using the page of IIS - works in IIS7 only if (application.Response.StatusCode == 200) { application.Response.StatusCode = 500; } Node globalErrorNode = null; var site = Site.Current; if (site != null) { var path = string.Concat("/Root/System/ErrorMessages/", site.Name, "/UserGlobal.html"); globalErrorNode = SystemAccount.Execute(() => Node.LoadNode(path)); } if (globalErrorNode != null) { var globalBinary = globalErrorNode.GetBinary("Binary"); var stream = globalBinary.GetStream(); if (stream != null) { var str = new StreamReader(stream); errorPageHtml = str.ReadToEnd(); } } else { errorPageHtml = GetDefaultUserErrorPageHtml(application.Server.MapPath("/"), true); } } else { // if the page is requested from localhost errorPageHtml = GetDefaultLocalErrorPageHtml(application.Server.MapPath("/"), true); } } else { // TODO: SQL Error handling } errorPageHtml = InsertErrorMessagesIntoHtml(exception, errorPageHtml); application.Response.TrySkipIisCustomErrors = true; // If there is a specified status code in statusCodeString then set Response.StatusCode to it. // Otherwise go on to global error page. if (statusCode != null) { application.Response.StatusCode = statusCode.StatusCode; application.Response.SubStatusCode = statusCode.SubStatusCode; response?.Clear(); HttpContext.Current.ClearError(); HttpContext.Current.ApplicationInstance.CompleteRequest(); } else { if (application.Response.StatusCode == 200) { application.Response.StatusCode = 500; } } if (response != null) { response.Clear(); response.Write(errorPageHtml); } HttpContext.Current.ClearError(); HttpContext.Current.ApplicationInstance.CompleteRequest(); }
/// <summary> /// Add or edit a saved content query. /// </summary> /// <param name="content">A query content to modify, a user, or any content under a workspace.</param> /// <param name="query">Query text.</param> /// <param name="displayName">Display name for the saved query.</param> /// <param name="queryType">Type of the query.</param> /// <param name="uiFilters">Technical data containing filter information.</param> /// <returns></returns> public static object SaveQuery(Content content, string query, string displayName, QueryType queryType, string uiFilters = null) { if (content == null) { throw new ArgumentNullException("content"); } if (query == null) { throw new ArgumentNullException("query"); } try { // replace @@ templates, because they cannot be parsed var replacedQuery = TemplateManager.Replace(typeof(ContentQueryTemplateReplacer), query); // We need to validate the query to avoid saving unknown texts. SnQuery.Parse(replacedQuery, new SnQueryContext(QuerySettings.Default, User.Current.Id)); } catch (Exception ex) { SnLog.WriteWarning("Content query parse error during query save.", EventId.Querying, properties: new Dictionary <string, object> { { "User", User.Current.Name }, { "Query text", query }, { "Error", ex.Message } }); throw new InvalidOperationException("Cannot save an invalid content query: " + query); } ContentList queryContainer = null; Content queryContent = null; switch (queryType) { case QueryType.Private: // load the user and his profile var user = content.ContentHandler as User ?? (User)User.Current; if (!user.IsProfileExist()) { user.CreateProfile(); } var profile = user.Profile; if (profile == null) { throw new InvalidOperationException("User profile could not be created."); } queryContainer = GetQueryContainer(profile); break; case QueryType.Public: // store the query under the current workspace queryContainer = GetQueryContainer(((GenericContent)content.ContentHandler).Workspace); if (queryContainer == null) { throw new InvalidOperationException("Query container could not be created for a public query. Content: " + content.Path); } break; case QueryType.NonDefined: if (!content.ContentType.IsInstaceOfOrDerivedFrom(QueryTypeName)) { throw new InvalidOperationException("If the query type is nondefined, the content must be a query to save."); } queryContent = content; break; default: throw new InvalidOperationException("Unknown query type: " + queryType); } if (queryContainer != null) { // create a new query under the previously found container queryContent = Content.CreateNew(QueryTypeName, queryContainer, null); } if (queryContent == null) { throw new InvalidOperationException("No query content to save."); } // Elevation: a simple user does not necessarily have // 'Add' permission for the public queries folder. using (new SystemAccount()) { if (!string.IsNullOrEmpty(displayName)) { queryContent.DisplayName = displayName; } queryContent["Query"] = query; queryContent["UiFilters"] = uiFilters; queryContent.Save(); } return(queryContent); }
private static void StartUpdaterAndExit() { // this switch is monitored by the Work method because it // must not ask for a new task if an update has started _updateStarted = true; SnLog.WriteInformation($"Task#Starting update process on agent {AgentName}.", EventId.TaskManagement.General); var updaterToolName = AgentManager.UPDATER_PROCESSNAME + ".exe"; var updaterToolPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), updaterToolName); var updaterAlreadyRunning = false; // the tool should be next to the agent executable if (File.Exists(updaterToolPath)) { var startInfo = new ProcessStartInfo(updaterToolName) { UseShellExecute = false, CreateNoWindow = true, ErrorDialog = false, WindowStyle = ProcessWindowStyle.Hidden, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, }; var updaterProcess = new Process { EnableRaisingEvents = true, StartInfo = startInfo }; // listen to what the updater tool writes to the Console updaterProcess.OutputDataReceived += delegate(object sender, DataReceivedEventArgs args) { if (args == null || args.Data == null) { return; } // the updater notified us that he won if (string.CompareOrdinal(args.Data, "WINNER") == 0) { _updateWinner = true; } }; try { updaterProcess.Start(); updaterProcess.BeginOutputReadLine(); SnLog.WriteInformation($"Task#Updater tool STARTED on agent {Agent.AgentName}", EventId.TaskManagement.General); // Wait while the updater process exits (because another updater is already running) // or it notifies us that he is the winner and will do the actual update soon. do { updaterProcess.WaitForExit(1000); } while (!updaterProcess.HasExited && !_updateWinner); if (updaterProcess.HasExited) { if (updaterProcess.ExitCode == AgentManager.UPDATER_STATUSCODE_STARTED) { updaterAlreadyRunning = true; // another agent already started the updater tool, simply exit SnLog.WriteInformation($"Task#Updater tool EXITED on agent {AgentName} because another updater is already running.", EventId.TaskManagement.General); } else { // unknown error code SnLog.WriteWarning($"Task#Updater tool EXITED on agent {AgentName} with an unexpected code: {updaterProcess.ExitCode}.", EventId.TaskManagement.General); } } else if (_updateWinner) { // Download the package only if we started the one // and only true updater exe - that has not exited. DownloadUpdatePackage(); } } catch (Exception ex) { SnLog.WriteException(ex, "Agent update error.", EventId.TaskManagement.General); } } else { // the updater tool is missing SnLog.WriteError(string.Format("Task#Updater tool not found ({0}), but there is a new version on the server. Please update the TaskManagement folder manually.", updaterToolPath), EventId.TaskManagement.General); // no update will be performed: switch back to working mode _updateStarted = false; // do not exit if there is no updater: the operator must handle // this use-case manually (stop the service and copy the files) return; } // wait for the last task executor to finish while (_working) { Thread.Sleep(1000); } SnLog.WriteInformation(string.Format(updaterAlreadyRunning ? "Task#Agent {0} exits before updating." : "Task#Agent {0} exits before updating. This is Ripley, last survivor of the Nostromo, signing off.", AgentName), EventId.TaskManagement.General); // shut down this agent Environment.Exit(0); }
/// <summary> /// MUST BE SYNCHRON /// GAPS MUST BE ORDERED /// </summary> internal static void Start(int lastDatabaseId, int lastExecutedId, int[] gaps, System.IO.TextWriter consoleOut) { if (consoleOut != null) { consoleOut.WriteLine("Executing unprocessed activities. {0}-{1} {2}", lastExecutedId, lastDatabaseId, CompletionState.GapsToString(gaps, 5, 3)); } SnLog.WriteInformation("Executing unprocessed activities.", EventId.RepositoryRuntime, properties: new Dictionary <string, object> { { "LastDatabaseId", lastDatabaseId }, { "LastExecutedId", lastExecutedId }, { "CountOfGaps", gaps.Length }, { "Gaps", String.Join(", ", gaps) } }); DependencyManager.Start(); var count = 0; if (gaps.Any()) { var loadedActivities = new IndexingActivityLoader(gaps, true); foreach (LuceneIndexingActivity loadedActivity in loadedActivities) { // wait and start processing loaded activities in the meantime WaitIfOverloaded(true); SnTrace.IndexQueue.Write("IAQ: Startup: A{0} enqueued from db.", loadedActivity.Id); IndexingActivityHistory.Arrive(loadedActivity); _arrivalQueue.Enqueue(loadedActivity); _lastQueued = loadedActivity.Id; count++; } } if (lastExecutedId < lastDatabaseId) { var loadedActivities = new IndexingActivityLoader(lastExecutedId + 1, lastDatabaseId, true); foreach (LuceneIndexingActivity loadedActivity in loadedActivities) { // wait and start processing loaded activities in the meantime WaitIfOverloaded(true); SnTrace.IndexQueue.Write("IAQ: Startup: A{0} enqueued from db.", loadedActivity.Id); IndexingActivityHistory.Arrive(loadedActivity); _arrivalQueue.Enqueue(loadedActivity); _lastQueued = loadedActivity.Id; count++; } } if (_lastQueued < lastExecutedId) { _lastQueued = lastExecutedId; } // ensure that the arrival activity queue is not empty at this pont. DependencyManager.ActivityEnqueued(); if (lastDatabaseId != 0 || lastExecutedId != 0 || gaps.Any()) { while (IsWorking()) { Thread.Sleep(200); } } // At this point we know for sure that the original gap is not there anymore. // In case there is a false gap (e.g. because there are missing activity ids // in the db) we have to remove these ids manually from the in-memory gap. if (gaps.Any()) { TerminationHistory.RemoveGaps(gaps); // Commit is necessary because otherwise the gap is removed only in memory, but // the index is not updated in the file system. LuceneManager.Commit(); } SnLog.WriteInformation($"Executing unprocessed activities ({count}) finished.", EventId.RepositoryLifecycle); }
/// <summary> /// Initializes a RabbitMQ service connection based on the provided service url. /// Declares the exchange and binds a consumer queue. /// Opens a receiver channel and creates a consumer for receiving messages. /// </summary> public override void Initialize() { if (_initialized) { return; } base.Initialize(); Connection = OpenConnection(ServiceUrl); string queueName; try { // declare an exchange and bind a queue unique for this application using (var initChannel = OpenChannel(Connection)) { initChannel.ExchangeDeclare(MessageExchange, "fanout"); // let the server generate a unique queue name queueName = initChannel.QueueDeclare().QueueName; SnTrace.Messaging.Write($"RMQ: RabbitMQ Security queue declared: {queueName}"); initChannel.QueueBind(queueName, MessageExchange, string.Empty); SnTrace.Messaging.Write($"RMQ: RabbitMQ Security queue {queueName} is bound to exchange {MessageExchange}."); } } catch (Exception ex) { SnLog.WriteException(ex, $"RabbitMQ Security message provider connection error. Service url: {ServiceUrl}"); throw; } // use a single channel for receiving messages ReceiverChannel = OpenChannel(Connection); var consumer = new EventingBasicConsumer(ReceiverChannel); consumer.Shutdown += (sender, args) => { SnTrace.Messaging.Write("RMQ: RabbitMQ Security consumer shutdown."); }; consumer.ConsumerCancelled += (sender, args) => { SnTrace.Messaging.Write("RMQ: RabbitMQ Security consumer cancelled."); }; consumer.Received += (model, args) => { // this is the main entry point for receiving messages using (var ms = new MemoryStream(args.Body)) { OnMessageReceived(ms); } }; ReceiverChannel.BasicConsume(queueName, true, consumer); SnLog.WriteInformation($"RabbitMQ Security message provider connected to {ServiceUrl}", properties: new Dictionary <string, object> { { "Exchange", MessageExchange }, { "QueueName", queueName } }); _initialized = true; }
public void ResizeImage(HttpContext context) { Stream imageStream = null; var imageNodePath = HttpContext.Current.Request.FilePath; var content = Content.Create(PortalContext.Current.ContextNode); var contentPath = ""; var contentFileName = ""; var contentId = -1; CheckCacheFolder(); if (!string.IsNullOrEmpty(imageNodePath)) { if (ImageType == "Binary") { var contentBinary = content.Fields["Binary"].GetData() as BinaryData; if (contentBinary == null) { throw new Exception("Can not read Binary field from the given Content. Doesn't exists?"); } imageStream = contentBinary.GetStream(); contentFileName = content.Name; contentId = content.Id; } else if (ImageType == "ImageData") { if (!String.IsNullOrEmpty(ImageFieldName)) { try { var contentImageFieldData = content.Fields[ImageFieldName].GetData() as SenseNet.ContentRepository.Fields.ImageField.ImageFieldData; if (contentImageFieldData.ImgData.Size > 0) { imageStream = contentImageFieldData.ImgData.GetStream(); contentFileName = new FileInfo(contentImageFieldData.ImgData.FileName.FullFileName).Name; contentId = contentImageFieldData.ImgData.Id; } else { imageStream = contentImageFieldData.ImgRef.Binary.GetStream(); contentFileName = new FileInfo(contentImageFieldData.ImgRef.Path).Name; contentId = contentImageFieldData.ImgRef.Id; } } catch (Exception) { throw new Exception("Invalid Image Field Name was given in the application."); } } else { throw new Exception("There was no ImageFieldName specified when using ImageData as ImageType."); } } else if (ImageType == "Reference") { if (!String.IsNullOrEmpty(ImageFieldName)) { try { //TODO: GetData can return with null, a Node or a List<node> var referenceField = content.Fields[ImageFieldName].GetData() as List <Node>; var refContent = Content.Create(referenceField[0]); var refContentBinary = refContent.Fields["Binary"].GetData() as BinaryData; imageStream = refContentBinary.GetStream(); contentFileName = refContent.Name; contentId = refContent.Id; } catch (Exception) { //TODO: empty catch block } } else { throw new Exception("There was no ImageFieldName specified when using ImageData as ImageType."); } } else if (ImageType == "Attachment") { if (!String.IsNullOrEmpty(ImageFieldName)) { try { var binary = content.Fields[ImageFieldName].GetData() as BinaryData; imageStream = binary.GetStream(); contentFileName = new FileInfo(binary.FileName.FullFileName).Name; contentId = binary.Id; } catch (Exception) { throw new Exception( String.Format("The given image field field '{0}' is not a valid binary field of an image.", ImageFieldName)); } } } // generating contentPath int lastDotIndex = contentFileName.LastIndexOf('.'); contentPath = lastDotIndex != -1 ? contentFileName.Insert(lastDotIndex, String.Format("_{1}{0}", contentId.ToString(), ResizeType == ResizeTypeList.Resize ? "R_" : "C_")) : String.Format("{0}_{2}{1}", contentFileName, contentId.ToString(), ResizeType == ResizeTypeList.Resize ? "R_" : "C_"); if (IsCached(contentPath)) { FlushCachedFile(contentPath, context); return; } if (ResizeType == ResizeTypeList.Resize) { // Resize image imageStream = ImageResizer.CreateResizedImageFile(imageStream, Width, Height, 0, Stretch, IsAutoOutputFormat ? GetImageFormat(GetMimeType(contentPath)) : this.ResizeOutputFormat, this.ResizeSmoothingMode, this.ResizeInterpolationMode, this.ResizePixelOffsetMode); } else { double verticalDiff; double horizontalDiff; switch (CropVAlign.ToLower()) { case "top": verticalDiff = 0; break; case "center": verticalDiff = -1; break; case "bottom": verticalDiff = double.MaxValue; break; default: try { verticalDiff = Convert.ToDouble(CropVAlign); } catch (Exception ex) { SnLog.WriteException(ex); verticalDiff = 0; } break; } switch (CropHAlign.ToLower()) { case "left": horizontalDiff = 0; break; case "center": horizontalDiff = -1; break; case "right": horizontalDiff = double.MaxValue; break; default: try { horizontalDiff = Convert.ToDouble(CropHAlign); } catch (Exception ex) { SnLog.WriteException(ex); horizontalDiff = 0; } break; } // Crop image imageStream = ImageResizer.CreateCropedImageFile(imageStream, Width, Height, 0, IsAutoOutputFormat ? GetImageFormat(GetMimeType(contentPath)) : this.ResizeOutputFormat, this.ResizeSmoothingMode, this.ResizeInterpolationMode, this.ResizePixelOffsetMode, verticalDiff, horizontalDiff); } Cache(imageStream, GetImageCachePath(contentPath)); FlushStream(imageStream, context, GetMimeType(contentPath)); return; } else { throw new Exception("There was no image in the requested file path."); } }
private void StartManagers() { object dummy; IClusterChannel channel = null; try { ConsoleWrite("Initializing cache ... "); dummy = Cache.Count; // Log this, because logging is switched off when creating the cache provider // to avoid circular reference. SnLog.WriteInformation($"CacheProvider created: {Cache.Instance?.GetType().FullName}"); ConsoleWriteLine("ok."); ConsoleWrite("Starting message channel ... "); channel = DistributedApplication.ClusterChannel; channel.StartAsync(CancellationToken.None).GetAwaiter().GetResult(); ConsoleWriteLine("ok."); SnLog.WriteInformation($"Message channel {channel.GetType().FullName} started." + $"Instance id: {channel.ClusterMemberInfo.InstanceID}"); ConsoleWrite("Sending greeting message ... "); new PingMessage(new string[0]).SendAsync(CancellationToken.None).GetAwaiter().GetResult(); ConsoleWriteLine("ok."); ConsoleWrite("Starting NodeType system ... "); dummy = Providers.Instance.StorageSchema.NodeTypes[0]; ConsoleWriteLine("ok."); ConsoleWrite("Starting ContentType system ... "); dummy = ContentType.GetByName("GenericContent"); ConsoleWriteLine("ok."); ConsoleWrite("Starting AccessProvider ... "); dummy = User.Current; ConsoleWriteLine("ok."); SnQuery.SetPermissionFilterFactory(Providers.Instance.PermissionFilterFactory); if (_settings.StartIndexingEngine) { StartIndexingEngine(); } else { ConsoleWriteLine("IndexingEngine is not started."); } // switch on message processing after IndexingEngine was started. channel.AllowMessageProcessing = true; if (_settings.StartWorkflowEngine) { StartWorkflowEngine(); } else { ConsoleWriteLine("Workflow subsystem is not started."); } ConsoleWrite("Loading string resources ... "); dummy = SenseNetResourceManager.Current; ConsoleWriteLine("ok."); _serviceInstances = new List <ISnService>(); foreach (var serviceType in TypeResolver.GetTypesByInterface(typeof(ISnService))) { var service = (ISnService)Activator.CreateInstance(serviceType); service.Start(); ConsoleWriteLine("Service started: ", serviceType.Name); _serviceInstances.Add(service); } // register this application in the task management component SnTaskManager.RegisterApplication(); } catch { // If an error occoured, shut down the cluster channel. channel?.ShutDownAsync(CancellationToken.None).GetAwaiter().GetResult(); throw; } }
public override Stream Open() { if (_node == null) { try { var allowCompiledContent = AllowCompiledContent(_repositoryPath); // http://localhost/TestDoc.docx?action=RestoreVersion&version=2.0A // When there are 'action' and 'version' parameters in the requested URL the portal is trying to load the desired version of the node of the requested action. // This leads to an exception when the action doesn't have that version. // _repositoryPath will point to the node of action and ContextNode will be the document // if paths are not equal then we will return the last version of the requested action. // We also have to ignore the version request parameter in case of binary handler, because that // ashx must not have multiple versions. if (PortalContext.Current == null || PortalContext.Current.BinaryHandlerRequestedNodeHead != null || string.IsNullOrEmpty(PortalContext.Current.VersionRequest) || _repositoryPath != PortalContext.Current.ContextNodePath) { if (allowCompiledContent) { // elevated mode: pages, ascx files, etc. using (new SystemAccount()) { _node = Node.LoadNode(_repositoryPath, VersionNumber.LastFinalized); } } else { _node = Node.LoadNode(_repositoryPath, VersionNumber.LastFinalized); } } else { VersionNumber version; if (VersionNumber.TryParse(PortalContext.Current.VersionRequest, out version)) { Node node; if (allowCompiledContent) { // elevated mode: pages, ascx files, etc. using (new SystemAccount()) { node = Node.LoadNode(_repositoryPath, version); } } else { node = Node.LoadNode(_repositoryPath, version); } if (node != null && node.SavingState == ContentSavingState.Finalized) { _node = node; } } } // we cannot serve the binary if the user has only See or Preview permissions for the content if (_node != null && (_node.IsHeadOnly || _node.IsPreviewOnly) && HttpContext.Current != null) { AuthenticationHelper.ThrowForbidden(_node.Name); } } catch (SenseNetSecurityException ex) // logged { SnLog.WriteException(ex); if (HttpContext.Current == null || (_repositoryPath != null && _repositoryPath.ToLower().EndsWith(".ascx"))) { throw; } AuthenticationHelper.DenyAccess(HttpContext.Current.ApplicationInstance); } } if (_node == null) { throw new ApplicationException(string.Format("{0} not found. RepositoryFile cannot be served.", _repositoryPath)); } string propertyName = string.Empty; if (PortalContext.Current != null) { propertyName = PortalContext.Current.QueryStringNodePropertyName; } if (string.IsNullOrEmpty(propertyName)) { propertyName = PortalContext.DefaultNodePropertyName; } var propType = _node.PropertyTypes[propertyName]; if (propType == null) { throw new ApplicationException("Property not found: " + propertyName); } var propertyDataType = propType.DataType; Stream stream; switch (propertyDataType) { case DataType.Binary: string contentType; BinaryFileName fileName; stream = DocumentBinaryProvider.Current.GetStream(_node, propertyName, out contentType, out fileName); if (stream == null) { throw new ApplicationException(string.Format("BinaryProperty.Value.GetStream() returned null. RepositoryPath={0}, OriginalUri={1}, AppDomainFriendlyName={2} ", this._repositoryPath, ((PortalContext.Current != null) ? PortalContext.Current.RequestedUri.ToString() : "PortalContext.Current is null"), AppDomain.CurrentDomain.FriendlyName)); } // Set MIME type only if this is the main content (skip asp controls and pages, // page templates and other repository files opened during the request). // We need this in case of special images, fonts, etc, and handle the variable // at the end of the request (PortalContextModule.EndRequest method). if (HttpContext.Current != null && PortalContext.Current != null && string.Equals(PortalContext.Current.RepositoryPath, _repositoryPath, StringComparison.InvariantCultureIgnoreCase) && (string.IsNullOrEmpty(PortalContext.Current.ActionName) || string.Equals(PortalContext.Current.ActionName, "Browse", StringComparison.InvariantCultureIgnoreCase)) && !string.IsNullOrEmpty(contentType) && contentType != "text/asp") { if (!HttpContext.Current.Items.Contains(RESPONSECONTENTTYPEKEY)) { HttpContext.Current.Items.Add(RESPONSECONTENTTYPEKEY, contentType); } // set the value anyway as it may be useful in case of our custom file handler (SenseNetStaticFileHandler) HttpContext.Current.Response.ContentType = contentType; // add the necessary header for the css font-face rule if (MimeTable.IsFontType(fileName.Extension)) { HttpHeaderTools.SetAccessControlHeaders(); } } // set compressed encoding if necessary if (HttpContext.Current != null && MimeTable.IsCompressedType(fileName.Extension)) { HttpContext.Current.Response.Headers.Add("Content-Encoding", "gzip"); } // let the client code log file downloads var file = _node as ContentRepository.File; if (file != null) { ContentRepository.File.Downloaded(file.Id); } break; case DataType.String: case DataType.Text: case DataType.Int: case DataType.DateTime: stream = new MemoryStream(Encoding.UTF8.GetBytes(_node[propertyName].ToString())); break; default: throw new NotSupportedException(string.Format("The {0} property cannot be served because that's datatype is {1}.", propertyName, propertyDataType)); } return(stream); }
internal void DoStart() { ConsoleWriteLine(); ConsoleWriteLine("Starting Repository..."); ConsoleWriteLine(); if (_settings.TraceCategories != null) { LoggingSettings.SnTraceConfigurator.UpdateCategories(_settings.TraceCategories); } else { LoggingSettings.SnTraceConfigurator.UpdateStartupCategories(); } InitializeLogger(); RegisterAppdomainEventHandlers(); if (_settings.IndexPath != null) { Providers.Instance.SearchManager.IndexDirectoryPath = _settings.IndexPath; } LoadAssemblies(_settings.IsWebContext); _settings.Services.GetRequiredService <SecurityHandler>().StartSecurity(_settings.IsWebContext, _settings.Services); //UNDONE: modernize TemplateManager // Set legacy collection from the new services collection and reset the // current singleton list to force the system to regenerate it. TemplateManager.TemplateReplacerInstances = _settings.Services.GetService <IEnumerable <TemplateReplacerBase> >()?.ToArray() ?? Array.Empty <TemplateReplacerBase>(); TemplateManager.Clear(); SnQueryVisitor.VisitorExtensionTypes = new[] { typeof(Sharing.SharingVisitor) }; // We have to log the access provider here because it cannot be logged // during creation as it would lead to a circular reference. SnLog.WriteInformation($"AccessProvider created: {AccessProvider.Current?.GetType().FullName}"); using (new SystemAccount()) StartManagers(); if (_settings.TraceCategories != null) { LoggingSettings.SnTraceConfigurator.UpdateCategories(_settings.TraceCategories); } else { LoggingSettings.SnTraceConfigurator.UpdateCategories(); } InitializeOAuthProviders(); ConsoleWriteLine(); ConsoleWriteLine("Repository has started."); ConsoleWriteLine(); _startupInfo.Started = DateTime.UtcNow; }
/// <summary> /// Executes all modifications. /// Current user must have SetPermissions permission on any modified entity. /// An Auditlog record with changed data will be writen. /// OnPermissionChanging and OnPermissionChanged events are fired on any active NodeObserver that is not in the exclusion list (see "disabledObservers" parameter). /// </summary> /// <param name="disabledObservers">NodeObserver exclusion list.</param> public void Apply(List <Type> disabledObservers) { foreach (var entityId in this._acls.Keys) { this.Context.AssertPermission(entityId, PermissionType.SetPermissions); } using (var audit = new AuditBlock(AuditEvent.PermissionChanged, "Trying to execute permission modifications", new Dictionary <string, object> { { "Entities", this._acls.Count }, { "Breaks", this._breaks.Count }, { "Unbreaks", this._unbreaks.Count } })) { using (var op = SnTrace.Security.StartOperation("AclEditor.Apply (acl count: {0})", _acls.Count)) { string msg = null; if ((msg = Validate(this._acls)) != null) { // Log the error, but allow the operation to continue, because acl editor // may contain many different operations that we do not want to lose. SnLog.WriteWarning("Invalid ACL: " + msg, EventId.Security); } var relatedEntities = new List <int>(); // collect related aces var originalAces = new List <string>(); // changed acls foreach (var entityId in this._acls.Keys) { relatedEntities.Add(entityId); originalAces.Add(AcesToString(entityId, this.Context.GetExplicitEntries(entityId))); } // breaks that are not in changed aces foreach (var entityId in this._breaks) { if (!this._acls.ContainsKey(entityId)) { relatedEntities.Add(entityId); originalAces.Add(AcesToString(entityId, this.Context.GetExplicitEntries(entityId))); } } // unbreaks that are not in changed aces foreach (var entityId in this._unbreaks) { if (!this._acls.ContainsKey(entityId)) { relatedEntities.Add(entityId); originalAces.Add(AcesToString(entityId, this.Context.GetExplicitEntries(entityId))); } } var relatedNodeHeads = relatedEntities.Select(NodeHead.Get).ToArray(); var changedData = new[] { new ChangedData { Name = "SetPermissions", Original = originalAces } }; // fire "before" event var args1 = new CancellablePermissionChangingEventArgs(relatedNodeHeads, changedData); using (var op1 = SnTrace.Security.StartOperation("AclEditor.Apply / FireOnPermissionChanging")) { NodeObserver.FireOnPermissionChanging(null, null, args1, disabledObservers); if (args1.Cancel) { throw new CancelNodeEventException(args1.CancelMessage, args1.EventType, null); } op1.Successful = true; } var customData = args1.GetCustomData(); // main operation base.Apply(); // collect new values changedData[0].Value = relatedEntities.Select(x => AcesToString(x, this.Context.GetExplicitEntries(x))).ToList(); // fire "after" event var args2 = new PermissionChangedEventArgs(relatedNodeHeads, customData, changedData); using (var op2 = SnTrace.Security.StartOperation("AclEditor.Apply / FireOnPermissionChanged")) { NodeObserver.FireOnPermissionChanged(null, null, args2, disabledObservers); op2.Successful = true; } // iterate through all edited entities and log changes one by one for (var i = 0; i < relatedEntities.Count; i++) { var entity = relatedNodeHeads[i]; SnLog.WriteAudit(AuditEvent.PermissionChanged, new Dictionary <string, object> { { "Id", entity != null ? entity.Id : 0 }, { "Path", entity != null ? entity.Path : string.Empty }, { "Type", changedData[0].Name }, { "OldAcl", (changedData[0].Original as List <string>)[i] }, // changed data lists are in the same order as relatedentities { "NewAcl", (changedData[0].Value as List <string>)[i] } }); } op.Successful = true; } audit.Successful = true; } }
/// <summary> /// Processes the OData web request. Designed for test purposes. /// </summary> /// <param name="context">An <see cref="HttpContext" /> object that provides references to the intrinsic server objects (for example, <see langword="Request" />, <see langword="Response" />, <see langword="Session" />, and <see langword="Server" />) used to service HTTP requests. </param> /// <param name="httpMethod">HTTP protocol method.</param> /// <param name="inputStream">Request stream containing the posted JSON object.</param> public void ProcessRequest(HttpContext context, string httpMethod, Stream inputStream) { ODataRequest odataReq = null; ODataFormatter formatter = null; var portalContext = (PortalContext)context.Items[PortalContext.CONTEXT_ITEM_KEY]; try { Content content; odataReq = portalContext.ODataRequest; if (odataReq == null) { formatter = ODataFormatter.Create("json", portalContext); throw new ODataException("The Request is not an OData request.", ODataExceptionCode.RequestError); } this.ODataRequest = portalContext.ODataRequest; Exception requestError = this.ODataRequest.RequestError; formatter = ODataFormatter.Create(portalContext, odataReq); if (formatter == null) { formatter = ODataFormatter.Create("json", portalContext); throw new ODataException(ODataExceptionCode.InvalidFormatParameter); } if (requestError != null) { var innerOdataError = requestError as ODataException; var message = "An error occured during request parsing. " + requestError.Message + " See inner exception for details."; var code = innerOdataError?.ODataExceptionCode ?? ODataExceptionCode.RequestError; throw new ODataException(message, code, requestError); } odataReq.Format = formatter.FormatName; formatter.Initialize(odataReq); var exists = Node.Exists(odataReq.RepositoryPath); if (!exists && !odataReq.IsServiceDocumentRequest && !odataReq.IsMetadataRequest && !AllowedMethodNamesWithoutContent.Contains(httpMethod)) { ContentNotFound(context, odataReq.RepositoryPath); return; } JObject model; switch (httpMethod) { case "GET": if (odataReq.IsServiceDocumentRequest) { formatter.WriteServiceDocument(portalContext, odataReq); } else if (odataReq.IsMetadataRequest) { formatter.WriteMetadata(context, odataReq); } else { if (!Node.Exists(odataReq.RepositoryPath)) { ContentNotFound(context, odataReq.RepositoryPath); } else if (odataReq.IsCollection) { formatter.WriteChildrenCollection(odataReq.RepositoryPath, portalContext, odataReq); } else if (odataReq.IsMemberRequest) { formatter.WriteContentProperty(odataReq.RepositoryPath, odataReq.PropertyName, odataReq.IsRawValueRequest, portalContext, odataReq); } else { formatter.WriteSingleContent(odataReq.RepositoryPath, portalContext); } } break; case "PUT": // update if (odataReq.IsMemberRequest) { throw new ODataException("Cannot access a member with HTTP PUT.", ODataExceptionCode.IllegalInvoke); } else { model = Read(inputStream); content = LoadContentOrVirtualChild(odataReq); if (content == null) { ContentNotFound(context, odataReq.RepositoryPath); return; } ResetContent(content); UpdateContent(content, model, odataReq); formatter.WriteSingleContent(content, portalContext); } break; case "MERGE": case "PATCH": // update if (odataReq.IsMemberRequest) { throw new ODataException( String.Concat("Cannot access a member with HTTP ", httpMethod, "."), ODataExceptionCode.IllegalInvoke); } else { model = Read(inputStream); content = LoadContentOrVirtualChild(odataReq); if (content == null) { ContentNotFound(context, odataReq.RepositoryPath); return; } UpdateContent(content, model, odataReq); formatter.WriteSingleContent(content, portalContext); } break; case "POST": // invoke an action, create content if (odataReq.IsMemberRequest) { formatter.WriteOperationResult(inputStream, portalContext, odataReq); } else { // parent must exist if (!Node.Exists(odataReq.RepositoryPath)) { ContentNotFound(context, odataReq.RepositoryPath); return; } model = Read(inputStream); content = CreateContent(model, odataReq); formatter.WriteSingleContent(content, portalContext); } break; case "DELETE": if (odataReq.IsMemberRequest) { throw new ODataException( String.Concat("Cannot access a member with HTTP ", httpMethod, "."), ODataExceptionCode.IllegalInvoke); } else { content = LoadContentOrVirtualChild(odataReq); content?.Delete(); } break; } } catch (ContentNotFoundException e) { var oe = new ODataException(ODataExceptionCode.ResourceNotFound, e); formatter?.WriteErrorResponse(context, oe); } catch (ODataException e) { if (e.HttpStatusCode == 500) { SnLog.WriteException(e); } formatter?.WriteErrorResponse(context, e); } catch (SenseNetSecurityException e) { // In case of a visitor we should not expose the information that this content actually exists. We return // a simple 404 instead to provide exactly the same response as the regular 404, where the content // really does not exist. But do this only if the visitor really does not have permission for the // requested content (because security exception could be thrown by an action or something else too). if (odataReq != null && User.Current.Id == User.Visitor.Id) { var head = NodeHead.Get(odataReq.RepositoryPath); if (head != null && !SecurityHandler.HasPermission(head, PermissionType.Open)) { ContentNotFound(context, odataReq.RepositoryPath); return; } } var oe = new ODataException(ODataExceptionCode.NotSpecified, e); SnLog.WriteException(oe); formatter?.WriteErrorResponse(context, oe); } catch (InvalidContentActionException ex) { var oe = new ODataException(ODataExceptionCode.NotSpecified, ex); if (ex.Reason != InvalidContentActionReason.NotSpecified) { oe.ErrorCode = Enum.GetName(typeof(InvalidContentActionReason), ex.Reason); } // it is unnecessary to log this exception as this is not a real error formatter?.WriteErrorResponse(context, oe); } catch (ContentRepository.Storage.Data.NodeAlreadyExistsException nae) { var oe = new ODataException(ODataExceptionCode.ContentAlreadyExists, nae); formatter?.WriteErrorResponse(context, oe); } catch (System.Threading.ThreadAbortException tae) { if (!context.Response.IsRequestBeingRedirected) { var oe = new ODataException(ODataExceptionCode.RequestError, tae); formatter?.WriteErrorResponse(context, oe); } // specific redirect response so do nothing } catch (Exception ex) { var oe = new ODataException(ODataExceptionCode.NotSpecified, ex); SnLog.WriteException(oe); formatter?.WriteErrorResponse(context, oe); } finally { context.Response.End(); } }
static void Connection_Reconnected() { SnLog.WriteInformation($"Agent {AgentName}: connection reconnected.", EventId.TaskManagement.Communication); }
private int ExecuteInner(SnTask task) { var workerExe = GetWorkerExePath(task); if (string.IsNullOrEmpty(workerExe) || !File.Exists(workerExe)) { throw new TaskManagementException("Task executor command was not found", task.AppId, task.Id, task.Type); } var user = Configuration.GetUserCredentials(task.AppId); var userParameter = "USERNAME:\"" + (user != null ? user.UserName : string.Empty) + "\""; var passwordParameter = "PASSWORD:\"" + (user != null ? user.Password : string.Empty) + "\""; var dataParameter = "DATA:\"" + EscapeArgument(task.TaskData) + "\""; var prms = new List <string> { userParameter, passwordParameter, dataParameter }; var processArgs = string.Join(" ", prms); var startInfo = new ProcessStartInfo(workerExe, processArgs) { UseShellExecute = false, WorkingDirectory = Path.GetDirectoryName(workerExe), CreateNoWindow = true, ErrorDialog = false, WindowStyle = ProcessWindowStyle.Hidden, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, }; //_process = Process.Start(startInfo); _process = new Process(); _process.EnableRaisingEvents = true; _process.StartInfo = startInfo; _process.OutputDataReceived += process_OutputDataReceived; SnLog.WriteInformation(string.Format( "Task#{1} execution STARTED on agent {0}:\r\n id: {1},\r\n type: {2},\r\n hash: {3},\r\n order: {4},\r\n registered: {5},\r\n key: {6},\r\n data: {7}" , Agent.AgentName, task.Id, task.Type, task.Hash, task.Order, task.RegisteredAt, task.TaskKey, task.TaskData), EventId.TaskManagement.Lifecycle); _process.Start(); _process.BeginOutputReadLine(); _process.WaitForExit(); _process.OutputDataReceived -= process_OutputDataReceived; var result = _process.ExitCode; if (result != 0) { SnLog.WriteWarning($"Task#{task.Id} execution TERMINATED with error. Result:{result}, task type: {task.Type}, agent: {Agent.AgentName}", EventId.TaskManagement.General); } else { SnLog.WriteInformation($"Task#{task.Id} execution FINISHED: type: {task.Type}, agent: {Agent.AgentName}", EventId.TaskManagement.Lifecycle); } _process.Dispose(); _process = null; return(result); }
static void Connection_Closed() { SnLog.WriteWarning($"Agent {AgentName}: connection is closed.", EventId.TaskManagement.Communication); }
// ================================================================================ Notification protected virtual void SendMail() { if (!(LoadContentList() is SurveyList parentForm)) { return; } var smtpClient = new SmtpClient(); if (string.IsNullOrEmpty(smtpClient.Host)) { return; } var itemContent = Content.Create(this); var fromEmail = parentForm.GetSenderEmail(); var adminEmailList = string.Empty; if (!string.IsNullOrEmpty(parentForm.EmailList)) { adminEmailList = parentForm.EmailList.Trim(' ', ';', ',') .Replace(";", ",") .Replace("\n", " ") .Replace("\t", " ") .Replace("\r", " "); } // send mail to administrator if (!string.IsNullOrEmpty(adminEmailList)) { var ms = new MailMessage(fromEmail, adminEmailList) { Subject = string.IsNullOrEmpty(parentForm.DisplayName) ? parentForm.Name : ReplaceField(parentForm.DisplayName, false, itemContent), Body = string.IsNullOrEmpty(parentForm.AdminEmailTemplate) ? CreateEmailText() : ReplaceField(parentForm.AdminEmailTemplate, false, itemContent), IsBodyHtml = !string.IsNullOrEmpty(parentForm.AdminEmailTemplate) }; if (Attachments.Count > 0) { foreach (var a in Attachments) { ms.Attachments.Add(a); } } try { smtpClient.Send(ms); } catch (Exception ex) { SnLog.WriteException(ex, $"Error during sending notification email to {ms.To} after a user completed the following form: {parentForm.Path}."); } } // send mail to submitter var submitterAddress = GetSubmitterAddress(itemContent, parentForm.EmailField); if (!string.IsNullOrEmpty(submitterAddress)) { var ms = new MailMessage(fromEmail, submitterAddress) { Subject = string.IsNullOrEmpty(parentForm.MailSubject) ? parentForm.Name : ReplaceField(parentForm.MailSubject, true, itemContent), Body = string.IsNullOrEmpty(parentForm.SubmitterEmailTemplate) ? CreateEmailText() : ReplaceField(parentForm.SubmitterEmailTemplate, true, itemContent), IsBodyHtml = !string.IsNullOrEmpty(parentForm.SubmitterEmailTemplate) }; if (Attachments.Count > 0) { foreach (var a in Attachments) { ms.Attachments.Add(a); } } try { smtpClient.Send(ms); } catch (Exception ex) { SnLog.WriteException(ex, $"Error during sending notification email to {ms.To} after completing the following form: {parentForm.Path}."); } } try { // dispose attachment streams if (Streams != null) { foreach (var stream in Streams.Where(stream => stream != null)) { stream.Dispose(); } } } catch (Exception ex) { SnLog.WriteException(ex, $"Error when disposing attachments for {Path} (id: {Id})."); } }
private DocumentOpenLevel GetDocumentLevel(int nodeId) { var userId = _userId; if (userId == -1) { return(DocumentOpenLevel.OpenMinor); } if (userId < -1) { return(DocumentOpenLevel.Denied); } List <int> identities; try { identities = SecurityHandler.GetIdentitiesByMembership(_user, nodeId); } catch (EntityNotFoundException) { return(DocumentOpenLevel.Denied); } List <AceInfo> entries; try { using (new SystemAccount()) entries = SecurityHandler.GetEffectiveEntries(nodeId); } catch (Exception ex) // LOGGED { //TODO: collect aggregated errors per query instead of logging every error SnLog.WriteWarning($"GetEffectiveEntries threw an exception for id {nodeId}. Error: {ex}"); return(DocumentOpenLevel.Denied); } var allowBits = 0UL; var denyBits = 0UL; foreach (var entry in entries) { if (identities.Contains(entry.IdentityId)) { allowBits |= entry.AllowBits; denyBits |= entry.DenyBits; } } allowBits = allowBits & ~denyBits; var docLevel = DocumentOpenLevel.Denied; if ((allowBits & PermissionType.See.Mask) > 0) { docLevel = DocumentOpenLevel.See; } if ((allowBits & PermissionType.Preview.Mask) > 0) { docLevel = DocumentOpenLevel.Preview; } if ((allowBits & PermissionType.PreviewWithoutRedaction.Mask) > 0) { docLevel = DocumentOpenLevel.Open; } if ((allowBits & PermissionType.OpenMinor.Mask) > 0) { docLevel = DocumentOpenLevel.OpenMinor; } return(docLevel); }
internal async Task ProcessRequestAsync(HttpContext httpContext, ODataRequest odataRequest) { httpContext.SetODataRequest(odataRequest); var request = httpContext.Request; var httpMethod = request.Method; var inputStream = request.Body; ODataWriter odataWriter = null; try { Content content; if (odataRequest == null) { odataWriter = new ODataJsonWriter(); throw new ODataException("The Request is not an OData request.", ODataExceptionCode.RequestError); } odataWriter = ODataWriter.Create(httpContext, odataRequest); if (odataWriter == null) { odataWriter = new ODataJsonWriter(); odataWriter.Initialize(odataRequest); throw new ODataException(ODataExceptionCode.InvalidFormatParameter); } odataWriter.Initialize(odataRequest); var requestError = odataRequest.RequestError; if (requestError != null) { var innerOdataError = requestError as ODataException; var message = "An error occured during request parsing. " + requestError.Message + " See inner exception for details."; var code = innerOdataError?.ODataExceptionCode ?? ODataExceptionCode.RequestError; throw new ODataException(message, code, requestError); } odataRequest.Format = odataWriter.FormatName; var requestedContent = LoadContentByVersionRequest(odataRequest.RepositoryPath, httpContext); var exists = requestedContent != null; if (!exists && !odataRequest.IsServiceDocumentRequest && !odataRequest.IsMetadataRequest && !AllowedMethodNamesWithoutContent.Contains(httpMethod)) { ContentNotFound(httpContext); return; } JObject model; switch (httpMethod) { case "GET": if (odataRequest.IsServiceDocumentRequest) { await odataWriter.WriteServiceDocumentAsync(httpContext, odataRequest) .ConfigureAwait(false); } else if (odataRequest.IsMetadataRequest) { await odataWriter.WriteMetadataAsync(httpContext, odataRequest) .ConfigureAwait(false); } else { if (!Node.Exists(odataRequest.RepositoryPath)) { ContentNotFound(httpContext); } else if (odataRequest.IsCollection) { await odataWriter.WriteChildrenCollectionAsync(odataRequest.RepositoryPath, httpContext, odataRequest) .ConfigureAwait(false); } else if (odataRequest.IsMemberRequest) { await odataWriter.WriteContentPropertyAsync( odataRequest.RepositoryPath, odataRequest.PropertyName, odataRequest.IsRawValueRequest, httpContext, odataRequest, _appConfig) .ConfigureAwait(false); } else { await odataWriter.WriteSingleContentAsync(requestedContent, httpContext) .ConfigureAwait(false); } } break; case "PUT": // update if (odataRequest.IsMemberRequest) { throw new ODataException("Cannot access a member with HTTP PUT.", ODataExceptionCode.IllegalInvoke); } else { model = await ReadToJsonAsync(httpContext).ConfigureAwait(false); content = LoadContentOrVirtualChild(odataRequest); if (content == null) { ContentNotFound(httpContext); return; } ResetContent(content); UpdateContent(content, model, odataRequest); await odataWriter.WriteSingleContentAsync(content, httpContext) .ConfigureAwait(false); } break; case "MERGE": case "PATCH": // update if (odataRequest.IsMemberRequest) { throw new ODataException( String.Concat("Cannot access a member with HTTP ", httpMethod, "."), ODataExceptionCode.IllegalInvoke); } else { model = await ReadToJsonAsync(httpContext).ConfigureAwait(false); content = LoadContentOrVirtualChild(odataRequest); if (content == null) { ContentNotFound(httpContext); return; } UpdateContent(content, model, odataRequest); await odataWriter.WriteSingleContentAsync(content, httpContext) .ConfigureAwait(false); } break; case "POST": // invoke an action, create content if (odataRequest.IsMemberRequest) { // MEMBER REQUEST await odataWriter.WritePostOperationResultAsync(httpContext, odataRequest, _appConfig) .ConfigureAwait(false); } else { // CREATION if (!Node.Exists(odataRequest.RepositoryPath)) { // parent does not exist ContentNotFound(httpContext); return; } model = await ReadToJsonAsync(httpContext).ConfigureAwait(false); var newContent = CreateNewContent(model, odataRequest); await odataWriter.WriteSingleContentAsync(newContent, httpContext) .ConfigureAwait(false); } break; case "DELETE": if (odataRequest.IsMemberRequest) { throw new ODataException( String.Concat("Cannot access a member with HTTP ", httpMethod, "."), ODataExceptionCode.IllegalInvoke); } else { content = LoadContentOrVirtualChild(odataRequest); if (content != null) { var x = httpContext.Request.Query["permanent"].ToString(); if (x.Equals("true", StringComparison.OrdinalIgnoreCase)) { content.DeletePhysical(); } else { content.Delete(); } } } break; } } catch (ContentNotFoundException e) { var oe = new ODataException(ODataExceptionCode.ResourceNotFound, e); await odataWriter.WriteErrorResponseAsync(httpContext, oe) .ConfigureAwait(false); } catch (ODataException e) { if (e.HttpStatusCode == 500) { SnLog.WriteException(e); } await odataWriter.WriteErrorResponseAsync(httpContext, e) .ConfigureAwait(false); } catch (AccessDeniedException e) { var oe = new ODataException(ODataExceptionCode.Forbidden, e); await odataWriter.WriteErrorResponseAsync(httpContext, oe) .ConfigureAwait(false); } catch (UnauthorizedAccessException e) { var oe = new ODataException(ODataExceptionCode.Unauthorized, e); await odataWriter.WriteErrorResponseAsync(httpContext, oe) .ConfigureAwait(false); } catch (SenseNetSecurityException e) { // In case of a visitor we should not expose the information that this content actually exists. We return // a simple 404 instead to provide exactly the same response as the regular 404, where the content // really does not exist. But do this only if the visitor really does not have permission for the // requested content (because security exception could be thrown by an action or something else too). if (odataRequest != null && User.Current.Id == Identifiers.VisitorUserId) { var head = NodeHead.Get(odataRequest.RepositoryPath); if (head != null && !SecurityHandler.HasPermission(head, PermissionType.Open)) { ContentNotFound(httpContext); return; } } var oe = new ODataException(ODataExceptionCode.NotSpecified, e); SnLog.WriteException(oe); await odataWriter.WriteErrorResponseAsync(httpContext, oe) .ConfigureAwait(false); } catch (InvalidContentActionException ex) { var oe = new ODataException(ODataExceptionCode.NotSpecified, ex); if (ex.Reason != InvalidContentActionReason.NotSpecified) { oe.ErrorCode = Enum.GetName(typeof(InvalidContentActionReason), ex.Reason); } // it is unnecessary to log this exception as this is not a real error await odataWriter.WriteErrorResponseAsync(httpContext, oe) .ConfigureAwait(false); } catch (ContentRepository.Storage.Data.NodeAlreadyExistsException nae) { var oe = new ODataException(ODataExceptionCode.ContentAlreadyExists, nae); await odataWriter.WriteErrorResponseAsync(httpContext, oe) .ConfigureAwait(false); } catch (Exception ex) { var oe = new ODataException(ODataExceptionCode.NotSpecified, ex); SnLog.WriteException(oe); await odataWriter.WriteErrorResponseAsync(httpContext, oe) .ConfigureAwait(false); } }
internal static void Shutdown() { if (_instance == null) { SnLog.WriteWarning("Repository shutdown has already completed."); return; } lock (_shutDownSync) { if (_instance == null) { SnLog.WriteWarning("Repository shutdown has already completed."); return; } SnTrace.Repository.Write("Sending a goodbye message."); _instance.ConsoleWriteLine(); _instance.ConsoleWriteLine("Sending a goodbye message..."); DistributedApplication.ClusterChannel.ClusterMemberInfo.NeedToRecover = false; var pingMessage = new PingMessage(); pingMessage.Send(); foreach (var svc in _instance.serviceInstances) { SnTrace.Repository.Write("Shutting down {0}", svc.GetType().Name); svc.Shutdown(); } SnTrace.Repository.Write("Shutting down {0}", DistributedApplication.ClusterChannel.GetType().Name); DistributedApplication.ClusterChannel.ShutDown(); if (Instance.BackupIndexAtTheEnd) { SnTrace.Repository.Write("Backing up the index."); if (LuceneManagerIsRunning) { _instance.ConsoleWriteLine("Backing up the index..."); SenseNet.Search.Indexing.BackupTools.SynchronousBackupIndex(); _instance.ConsoleWriteLine("The backup of index is finished."); } else { _instance.ConsoleWriteLine("Backing up index is skipped because Lucene was not started."); } } if (LuceneManagerIsRunning) { SnTrace.Repository.Write("Shutting down LuceneManager."); SenseNet.Search.Indexing.LuceneManager.ShutDown(); } SnTrace.Repository.Write("Waiting for writer lock file is released."); WaitForWriterLockFileIsReleased(WaitForLockFileType.OnEnd); var t = DateTime.UtcNow - _instance._startupInfo.Starting; var msg = String.Format("Repository has stopped. Running time: {0}.{1:d2}:{2:d2}:{3:d2}", t.Days, t.Hours, t.Minutes, t.Seconds); SnTrace.Repository.Write(msg); SnTrace.Flush(); _instance.ConsoleWriteLine(msg); _instance.ConsoleWriteLine(); SnLog.WriteInformation(msg); _instance = null; } }
internal static Dictionary <Version, PackagingResult> ExecuteAssemblyPatches(SnComponentInfo assemblyComponent, RepositoryStartSettings settings = null) { var patchResults = new Dictionary <Version, PackagingResult>(); // If there is no installed component for this id, skip patching. var installedComponent = RepositoryVersionInfo.Instance.Components.FirstOrDefault(c => c.ComponentId == assemblyComponent.ComponentId); if (installedComponent == null) { return(patchResults); } // check which db version is supported by the assembly if (assemblyComponent.SupportedVersion == null || assemblyComponent.SupportedVersion <= installedComponent.Version) { return(patchResults); } // Supported version in the assembly is higher than // the physical version: there should be a patch. if (!(assemblyComponent.Patches?.Any() ?? false)) { throw new InvalidOperationException($"Missing patch for component {installedComponent.ComponentId}. " + $"Installed version is {installedComponent.Version}. " + $"The assembly requires at least version {assemblyComponent.SupportedVersion}."); } foreach (var patch in assemblyComponent.Patches) { // this variable is refreshed in every cycle if (installedComponent == null) { break; } if (patch.MinVersion > patch.MaxVersion || patch.MaxVersion > patch.Version) { // the patch version numbers are the responsibility of the developer of the component SnLog.WriteWarning( $"Patch {patch.Version} for component {assemblyComponent.ComponentId} cannot be executed because it contains invalid version numbers.", properties: new Dictionary <string, object> { { "MinVersion", patch.MinVersion }, { "MaxVersion", patch.MaxVersion } }); continue; } if (!string.IsNullOrEmpty(patch.Contents) && patch.Execute != null) { // ambigous patch definition SnLog.WriteWarning( $"Patch {patch.Version} for component {assemblyComponent.ComponentId} cannot be executed because it contains multiple patch definitions."); continue; } // check if the patch is relevant for the currently installed component version if (patch.MinVersion > installedComponent.Version || patch.MinVersionIsExclusive && patch.MinVersion == installedComponent.Version || patch.MaxVersion < installedComponent.Version || patch.MaxVersionIsExclusive && patch.MaxVersion == installedComponent.Version) { continue; } PackagingResult patchResult; try { if (patch.Contents?.StartsWith("<?xml", StringComparison.InvariantCultureIgnoreCase) ?? false) { // execute manifest patch patchResult = ExecutePatch(patch.Contents, settings); } else if (patch.Execute != null) { // execute code patch patch.Execute(new PatchContext { Settings = settings }); // save the new package info manually based on the patch version number Storage.SavePackage(new Package { ComponentId = assemblyComponent.ComponentId, ComponentVersion = patch.Version, ExecutionResult = ExecutionResult.Successful, PackageType = PackageType.Patch }); patchResult = new PackagingResult { NeedRestart = false, Successful = true, Terminated = false, Errors = 0 }; } else { //TODO: handle other patch formats (resource or filesystem path) // unknown patch format patchResult = new PackagingResult { NeedRestart = false, Successful = false, Terminated = false, Errors = 0 }; } } catch (Exception ex) { SnLog.WriteException(ex, $"Error during patch execution for component {assemblyComponent.ComponentId}. Patch target version: {patch.Version}."); throw; } patchResults[patch.Version] = patchResult; // reload installedComponent = RepositoryVersionInfo.Instance.Components.FirstOrDefault(c => c.ComponentId == assemblyComponent.ComponentId); } return(patchResults); }
/* ============================================================================== Receive */ private void ReceiveMessages() { while (true) { try { var message = _receiveQueue.Receive(TimeSpan.FromSeconds(1)); if (message == null) { return; } if (Shutdown) { return; } OnMessageReceived(message.Body as Stream); } catch (ThreadAbortException tex) { // suppress threadabortexception on shutdown if (Shutdown) { return; } SnLog.WriteException(tex, $"An error occurred when receiving from the queue ({_receiveQueue.Path}).", EventId.Messaging); } catch (MessageQueueException mex) { // check if receive timed out: this is not a problem if (mex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout) { if (Shutdown) { return; } continue; } SnLog.WriteException(mex, $"An error occurred when receiving from the queue ({_receiveQueue.Path}).", EventId.Messaging); OnReceiveException(mex); try { _receiveQueue = RecoverQueue(_receiveQueue); SnLog.WriteInformation("Receiver queue has been repaired.", EventId.Messaging); } catch (Exception ex) { SnLog.WriteException(ex, EventMessage.Errors.RepairError, EventId.Messaging); } var thread = new Thread(ReceiveMessages); thread.Start(); return; } catch (Exception e) { SnLog.WriteException(e, $"An error occurred when receiving from the queue ({_receiveQueue.Path}).", EventId.Messaging); OnReceiveException(e); } } }
public static BatchActionResponse DeleteBatch(Content content, bool permanent, object[] paths) { // no need to throw an exception if no ids are provided: we simply do not have to delete anything if (paths == null || paths.Length == 0) { return(null); } var results = new List <object>(); var errors = new List <ErrorContent>(); var identifiers = paths.Select(NodeIdentifier.Get).ToList(); var foundIdentifiers = new List <NodeIdentifier>(); var nodes = Node.LoadNodes(identifiers); foreach (var node in nodes) { try { // Collect already found identifiers in a separate list otherwise the error list // would contain multiple errors for the same content. foundIdentifiers.Add(NodeIdentifier.Get(node)); switch (node) { case GenericContent gc: gc.Delete(permanent); break; case ContentType ct: ct.Delete(); break; } results.Add(new { node.Id, node.Path, node.Name }); } catch (Exception e) { //TODO: we should log only relevant exceptions here and skip // business logic-related errors, e.g. lack of permissions or // existing target content path. SnLog.WriteException(e); errors.Add(new ErrorContent { Content = new { node?.Id, node?.Path }, Error = new Error { Code = "NotSpecified", ExceptionType = e.GetType().FullName, InnerError = new StackInfo { Trace = e.StackTrace }, Message = new ErrorMessage { Lang = System.Globalization.CultureInfo.CurrentUICulture.Name.ToLower(), Value = e.Message } } }); } } // iterating through the missing identifiers and making error items for them errors.AddRange(identifiers.Where(id => !foundIdentifiers.Exists(f => f.Id == id.Id || f.Path == id.Path)) .Select(missing => new ErrorContent { Content = new { missing?.Id, missing?.Path }, Error = new Error { Code = "ResourceNotFound", ExceptionType = "ContentNotFoundException", InnerError = null, Message = new ErrorMessage { Lang = System.Globalization.CultureInfo.CurrentUICulture.Name.ToLower(), Value = string.Format(SNSR.GetString(SNSR.Exceptions.OData.ErrorContentNotFound), missing?.Path) } } })); return(BatchActionResponse.Create(results, errors, results.Count + errors.Count)); }
public async Task TaskFinished(SnTaskResult taskResult) { SnTrace.TaskManagement.Write("AgentHub TaskFinished called. Agent: {0} / {1}, taskId: {2}, code: {3}, error: {4}", taskResult.MachineName, taskResult.AgentName, taskResult.Task.Id, taskResult.ResultCode, taskResult.Error == null ? "" : taskResult.Error.Message); try { if (string.IsNullOrEmpty(taskResult.Task.AppId)) { SnLog.WriteWarning($"AppId is empty for task #{taskResult.Task.Id}.", EventId.TaskManagement.Lifecycle); return; } var app = _applicationHandler.GetApplication(taskResult.Task.AppId); var doesApplicationNeedNotification = !string.IsNullOrWhiteSpace(taskResult.Task.GetFinalizeUrl(app)); // first we make sure that the app is accessible by sending a ping request if (doesApplicationNeedNotification && !(await _applicationHandler.SendPingRequestAsync(taskResult.Task.AppId, Context.ConnectionAborted) .ConfigureAwait(false))) { SnLog.WriteError($"Ping request to application {taskResult.Task.AppId} " + $"({(app == null ? "unknown app" : app.ApplicationUrl)}) " + $"failed when finalizing task #{taskResult.Task.Id}. " + $"Task success: {taskResult.Successful}, " + $"error: {(taskResult.Error == null ? "-" : taskResult.Error.ToString())}", EventId.TaskManagement.Communication); doesApplicationNeedNotification = false; } // remove the task from the database first await _dataHandler.FinalizeTaskAsync(taskResult, Context.ConnectionAborted).ConfigureAwait(false); SnTrace.TaskManagement.Write("AgentHub TaskFinished: task {0} has been deleted.", taskResult.Task.Id); if (doesApplicationNeedNotification) { // This method does not need to be awaited, because we do not want to do anything // with the result, only notify the app that the task has been finished. #pragma warning disable 4014 _applicationHandler.SendFinalizeNotificationAsync(taskResult, CancellationToken.None); #pragma warning restore 4014 } // notify monitors var te = taskResult.Successful ? SnTaskEvent.CreateDoneEvent(taskResult.Task.Id, taskResult.Task.Title, taskResult.ResultData, taskResult.Task.AppId, taskResult.Task.Tag, taskResult.MachineName, taskResult.AgentName) : SnTaskEvent.CreateFailedEvent(taskResult.Task.Id, taskResult.Task.Title, taskResult.ResultData, taskResult.Task.AppId, taskResult.Task.Tag, taskResult.MachineName, taskResult.AgentName); await _monitorHub.OnTaskEvent(te).ConfigureAwait(false); } catch (Exception ex) { SnLog.WriteException(ex, "AgentHub TaskFinished failed.", EventId.TaskManagement.General); } }
/// <summary> /// Returns a new <see cref="TrashBag"/> instance that packages the /// given <see cref="GenericContent"/> instance. /// </summary> /// <param name="node">The <see cref="GenericContent"/> instance that will be wrapped.</param> public static TrashBag BagThis(GenericContent node) { var bin = TrashBin.Instance; if (bin == null) { return(null); } if (node == null) { throw new ArgumentNullException("node"); } // creating a bag has nothing to do with user permissions: Move will handle that TrashBag bag = null; var currentUserId = User.Current.Id; var wsId = 0; var wsRelativePath = string.Empty; var ws = SystemAccount.Execute(() => node.Workspace); if (ws != null) { wsId = ws.Id; wsRelativePath = node.Path.Substring(ws.Path.Length); } using (new SystemAccount()) { bag = new TrashBag(bin) { KeepUntil = DateTime.UtcNow.AddDays(bin.MinRetentionTime), OriginalPath = RepositoryPath.GetParentPath(node.Path), WorkspaceRelativePath = wsRelativePath, WorkspaceId = wsId, DisplayName = node.DisplayName, Link = node, Owner = node.Owner }; bag.Save(); CopyPermissions(node, bag); // Add Delete permission for the owner to let them remove it later and also // AddNew permission to let the move operation below actually move // the content into the TrashBag. SecurityHandler.CreateAclEditor() .Allow(bag.Id, node.OwnerId, false, PermissionType.Delete, PermissionType.AddNew) .Allow(bag.Id, currentUserId, true, PermissionType.Delete, PermissionType.AddNew) .Apply(); } try { Node.Move(node.Path, bag.Path); } catch (SenseNetSecurityException ex) { SnLog.WriteException(ex); bag.Destroy(); if (ex.Data.Contains("PermissionType") && (string)ex.Data["PermissionType"] == "Delete") { throw new InvalidOperationException("You do not have enough permissions to delete this content to the Trash.", ex); } throw new InvalidOperationException("Error moving item to the trash", ex); } catch (Exception ex) { SnLog.WriteException(ex); bag.Destroy(); throw new InvalidOperationException("Error moving item to the trash", ex); } return(bag); }
protected virtual void BuildResultView() { Content rootContent = null; Exception controlException = null; try { // Elevation: it should be possible to search for content // under a folder where the user does not have explicit // permissions but on one of the child content may have. using (new SystemAccount()) { rootContent = GetModel() as Content; } if (rootContent != null) { rootContent.ChildrenDefinition.AllChildren = AllChildren; } } catch (Exception ex) { SnLog.WriteException(ex); controlException = ex; } var model = new ContentCollectionViewModel { State = this.State }; var childCount = 0; if (rootContent != null) { try { childCount = rootContent.Children.Count(); } catch (Exception ex) { SnLog.WriteException(ex); if (controlException == null) { controlException = ex; } } } try { model.Pager = GetPagerModel(childCount, State, string.Empty); model.Content = rootContent; } catch (Exception ex) { SnLog.WriteException(ex); if (controlException == null) { controlException = ex; } // in case of error, set dummy pager model model.Pager = new PagerModel(0, State, string.Empty); } try { if (RenderingMode == RenderMode.Xslt) { XmlModelData = model.ToXPathNavigator(); } else { // the Renderer property may contain a skin-relative path var viewPath = RenderingMode == RenderMode.Native ? "/root/Global/Renderers/ContentCollectionView.ascx" : SkinManager.Resolve(Renderer); Control presenter = null; try { presenter = Page.LoadControl(viewPath); } catch (Exception ex) { SnLog.WriteException(ex); if (controlException == null) { controlException = ex; } } if (presenter != null) { Controls.Add(presenter); PresenterClientId = presenter.ClientID; var ccView = presenter as ContentCollectionView; if (ccView != null) { ccView.Model = model; } if (rootContent != null) { var itemlist = presenter.FindControl(ContentListID); if (itemlist != null) { try { ContentQueryPresenterPortlet.DataBindingHelper.SetDataSourceAndBind(itemlist, rootContent. Children); } catch (Exception ex) { SnLog.WriteException(ex); if (controlException == null) { controlException = ex; } } } itemlist = presenter.FindControl("ViewDatasource"); if (itemlist != null) { try { ContentQueryPresenterPortlet.DataBindingHelper.SetDataSourceAndBind(itemlist, rootContent.Children); } catch (Exception ex) { SnLog.WriteException(ex); if (controlException == null) { controlException = ex; } } } } var itemPager = presenter.FindControl("ContentListPager"); if (itemPager != null) { try { ContentQueryPresenterPortlet.DataBindingHelper.SetDataSourceAndBind(itemPager, model.Pager.PagerActions); } catch (Exception ex) { SnLog.WriteException(ex); if (controlException == null) { controlException = ex; } } } } } } catch (Exception ex) { SnLog.WriteException(ex); if (controlException == null) { controlException = ex; } } try { if (controlException != null) { BuildErrorMessage(controlException); } } catch (Exception ex) { var errorText = SR.GetString(SR.Portlets.ContentCollection.ErrorLoadingContentView, HttpUtility.HtmlEncode(ex.Message)); this.Controls.Clear(); this.Controls.Add(new LiteralControl(errorText)); } }
protected override void CreateChildControls() { if (Cacheable && CanCache && IsInCache) { return; } Controls.Clear(); var node = GetContextNode(); if (node == null) { if (this.RenderException != null) { Controls.Clear(); Controls.Add(new System.Web.UI.WebControls.Label() { Text = string.Format("Error loading content view: {0}", this.RenderException.Message) }); } else { Controls.Clear(); Controls.Add(new System.Web.UI.WebControls.Label() { Text = "Content could not be loaded" }); } ChildControlsCreated = true; return; } var content = Content.Create(node); var contentView = String.IsNullOrEmpty(ContentViewPath) ? ContentView.Create(content, Page, ViewMode.InlineEdit) : ContentView.Create(content, Page, ViewMode.InlineEdit, ContentViewPath); if (contentView == null) { this.Controls.Clear(); this.Controls.Add(new System.Web.UI.WebControls.Label { Text = SR.GetString(SR.Exceptions.ContentView.NotFound) }); return; } contentView.CommandButtonsAction += new EventHandler <CommandButtonsEventArgs>(contentView_CommandButtonsAction); // backward compatibility: use eventhandler for contentviews using defaultbuttons and not commandbuttons contentView.UserAction += new EventHandler <UserActionEventArgs>(contentView_UserAction); try { Controls.Add(contentView); } catch (Exception ex) { SnLog.WriteException(ex); this.Controls.Clear(); var message = ex.Message.Contains("does not contain Field") ? string.Format("Content and view mismatch: {0}", ex.Message) : string.Format("Error: {0}", ex.Message); Controls.Add(new LiteralControl(message)); } ChildControlsCreated = true; }
public static void Restore(TrashBag trashBag, string targetPath, bool addNewName) { if (trashBag == null || string.IsNullOrEmpty(targetPath)) { throw new RestoreException(RestoreResultType.Nonedefined); } targetPath = targetPath.TrimEnd(new [] { '/' }); var node = trashBag.DeletedContent; if (node == null) { throw new InvalidOperationException("TrashBag is empty"); } var targetContentPath = RepositoryPath.Combine(targetPath, node.Name); var targetParent = Node.Load <GenericContent>(targetPath); if (targetParent == null) { throw new RestoreException(RestoreResultType.NoParent, RepositoryPath.GetParentPath(targetPath)); } // assert permissions if (!targetParent.Security.HasPermission(PermissionType.Open)) { throw new RestoreException(RestoreResultType.PermissionError, targetContentPath); } // target type check: ContentTypes field AssertRestoreContentType(targetParent, node); if (Node.Exists(targetContentPath)) { var newName = ContentNamingProvider.IncrementNameSuffixToLastName(node.Name, targetParent.Id); targetContentPath = RepositoryPath.Combine(targetPath, newName); if (addNewName) { try { // there is no other way right now (rename and move cannot be done at the same time) node.Name = newName; node.Save(); } catch (SenseNetSecurityException ex) { SnLog.WriteException(ex); throw new RestoreException(RestoreResultType.PermissionError, targetContentPath, ex); } catch (Exception ex) { SnLog.WriteException(ex); throw new RestoreException(RestoreResultType.UnknownError, targetContentPath, ex); } } else { throw new RestoreException(RestoreResultType.ExistingName, targetContentPath); } } var originalUser = User.Current; try { node.MoveTo(targetParent); AccessProvider.Current.SetCurrentUser(User.Administrator); trashBag.KeepUntil = DateTime.Today.AddDays(-1); trashBag.ForceDelete(); } catch (SenseNetSecurityException ex) { SnLog.WriteException(ex); throw new RestoreException(RestoreResultType.PermissionError, targetContentPath, ex); } catch (Exception ex) { SnLog.WriteException(ex); throw new RestoreException(RestoreResultType.UnknownError, targetContentPath, ex); } finally { AccessProvider.Current.SetCurrentUser(originalUser); } }
/// <summary> /// Check if the origin header sent by the client is a known domain. It has to be the /// same that the request was sent to, OR it has to be among the whitelisted external /// domains that are allowed to access the Content Repository. /// </summary> public static bool TrySetAllowedOriginHeader() { if (HttpContext.Current == null) { return(true); } // Get the Origin header from the request, if it was sent by the browser. // Command-line tools or local html files will not send this. var originHeader = HttpContext.Current.Request.Headers[HEADER_ACESSCONTROL_ORIGIN_NAME]; if (string.IsNullOrEmpty(originHeader) || string.Compare(originHeader, "null", StringComparison.InvariantCultureIgnoreCase) == 0) { SetAccessControlHeaders(); return(true); } // We compare only the domain parts of the two urls, because interim servers // may change the scheme and port of the url (e.g. from https to http). var currentDomain = HttpContext.Current.Request.Url.GetComponents(UriComponents.Host, UriFormat.SafeUnescaped); var originDomain = string.Empty; var error = false; try { var origin = new Uri(originHeader.Trim(' ')); originDomain = origin.GetComponents(UriComponents.Host, UriFormat.SafeUnescaped); } catch (Exception) { SnLog.WriteWarning("Unknown or incorrectly formatted origin header: " + originHeader, EventId.Portal); error = true; } if (!error) { // check if the request arrived from an external domain if (string.Compare(currentDomain, originDomain, StringComparison.InvariantCultureIgnoreCase) != 0) { // We allow requests from external domains only if they are registered in this whitelist. var corsDomains = Settings.GetValue <IEnumerable <string> >(PortalSettings.SETTINGSNAME, PortalSettings.SETTINGS_ALLOWEDORIGINDOMAINS, PortalContext.Current.ContextNodePath, new string[0]); // try to find the domain in the whitelist (or the '*') var externalDomain = corsDomains.FirstOrDefault(d => d == HEADER_ACESSCONTROL_ALLOWCREDENTIALS_ALL || string.Compare(d, originDomain, StringComparison.InvariantCultureIgnoreCase) == 0); if (!string.IsNullOrEmpty(externalDomain)) { // Set the desired domain as allowed (or '*' if it is among the whitelisted domains). We cannot use // the value from the whitelist (e.g. 'example.com'), because the browser expects the full origin // (with schema and port, e.g. 'http://example.com:80'). SetAccessControlHeaders(externalDomain == HEADER_ACESSCONTROL_ALLOWCREDENTIALS_ALL ? HEADER_ACESSCONTROL_ALLOWCREDENTIALS_ALL : originHeader); return(true); } // not found in the whitelist error = true; } } SetAccessControlHeaders(); return(!error); }