2017-12-07 16:45:25 +01:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
2020-08-21 14:52:47 +01:00
|
|
|
|
using Microsoft.Extensions.Options;
|
2021-02-09 10:22:42 +01:00
|
|
|
|
using Umbraco.Cms.Core;
|
|
|
|
|
|
using Umbraco.Cms.Core.Configuration.Models;
|
|
|
|
|
|
using Umbraco.Cms.Core.IO;
|
|
|
|
|
|
using Umbraco.Cms.Core.Models;
|
|
|
|
|
|
using Umbraco.Cms.Core.Persistence.Repositories;
|
2019-12-17 16:30:26 +01:00
|
|
|
|
using Umbraco.Core.Configuration;
|
2017-12-07 16:45:25 +01:00
|
|
|
|
using Umbraco.Core.Models;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Represents the Script Repository
|
|
|
|
|
|
/// </summary>
|
2019-11-12 13:49:56 +11:00
|
|
|
|
internal class ScriptRepository : FileRepository<string, IScript>, IScriptRepository
|
2017-12-07 16:45:25 +01:00
|
|
|
|
{
|
2019-11-12 13:49:56 +11:00
|
|
|
|
private readonly IIOHelper _ioHelper;
|
2020-08-21 14:52:47 +01:00
|
|
|
|
private readonly GlobalSettings _globalSettings;
|
2017-12-07 16:45:25 +01:00
|
|
|
|
|
2020-08-23 23:36:48 +02:00
|
|
|
|
public ScriptRepository(IFileSystems fileSystems, IIOHelper ioHelper, IOptions<GlobalSettings> globalSettings)
|
2018-07-20 09:49:05 +02:00
|
|
|
|
: base(fileSystems.ScriptsFileSystem)
|
2017-12-07 16:45:25 +01:00
|
|
|
|
{
|
2019-11-12 13:49:56 +11:00
|
|
|
|
_ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
|
2020-08-21 14:52:47 +01:00
|
|
|
|
_globalSettings = globalSettings.Value;
|
2017-12-07 16:45:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#region Implementation of IRepository<string,Script>
|
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
|
public override IScript Get(string id)
|
2017-12-07 16:45:25 +01:00
|
|
|
|
{
|
|
|
|
|
|
// get the relative path within the filesystem
|
|
|
|
|
|
// (though... id should be relative already)
|
|
|
|
|
|
var path = FileSystem.GetRelativePath(id);
|
|
|
|
|
|
|
|
|
|
|
|
if (FileSystem.FileExists(path) == false)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
// content will be lazy-loaded when required
|
|
|
|
|
|
var created = FileSystem.GetCreated(path).UtcDateTime;
|
|
|
|
|
|
var updated = FileSystem.GetLastModified(path).UtcDateTime;
|
|
|
|
|
|
//var content = GetFileContent(path);
|
|
|
|
|
|
|
|
|
|
|
|
var script = new Script(path, file => GetFileContent(file.OriginalPath))
|
|
|
|
|
|
{
|
|
|
|
|
|
//id can be the hash
|
|
|
|
|
|
Id = path.GetHashCode(),
|
|
|
|
|
|
Key = path.EncodeAsGuid(),
|
|
|
|
|
|
//Content = content,
|
|
|
|
|
|
CreateDate = created,
|
|
|
|
|
|
UpdateDate = updated,
|
|
|
|
|
|
VirtualPath = FileSystem.GetUrl(path)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// reset dirty initial properties (U4-1946)
|
|
|
|
|
|
script.ResetDirtyProperties(false);
|
|
|
|
|
|
|
|
|
|
|
|
return script;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
|
public override void Save(IScript entity)
|
2017-12-07 16:45:25 +01:00
|
|
|
|
{
|
2019-11-12 13:49:56 +11:00
|
|
|
|
// TODO: Casting :/ Review GetFileContent and it's usages, need to look into it later
|
|
|
|
|
|
var script = (Script) entity;
|
|
|
|
|
|
|
|
|
|
|
|
base.Save(script);
|
2017-12-07 16:45:25 +01:00
|
|
|
|
|
|
|
|
|
|
// ensure that from now on, content is lazy-loaded
|
2019-11-12 13:49:56 +11:00
|
|
|
|
if (script.GetFileContent == null)
|
|
|
|
|
|
script.GetFileContent = file => GetFileContent(file.OriginalPath);
|
2017-12-07 16:45:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
|
public override IEnumerable<IScript> GetMany(params string[] ids)
|
2017-12-07 16:45:25 +01:00
|
|
|
|
{
|
|
|
|
|
|
//ensure they are de-duplicated, easy win if people don't do this as this can cause many excess queries
|
|
|
|
|
|
ids = ids.Distinct().ToArray();
|
|
|
|
|
|
|
|
|
|
|
|
if (ids.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var id in ids)
|
|
|
|
|
|
{
|
|
|
|
|
|
yield return Get(id);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var files = FindAllFiles("", "*.*");
|
|
|
|
|
|
foreach (var file in files)
|
|
|
|
|
|
{
|
|
|
|
|
|
yield return Get(file);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-11-12 13:49:56 +11:00
|
|
|
|
public bool ValidateScript(IScript script)
|
2017-12-07 16:45:25 +01:00
|
|
|
|
{
|
|
|
|
|
|
// get full path
|
|
|
|
|
|
string fullPath;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// may throw for security reasons
|
|
|
|
|
|
fullPath = FileSystem.GetFullPath(script.Path);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// validate path & extension
|
2019-12-17 16:30:26 +01:00
|
|
|
|
var validDir = _globalSettings.UmbracoScriptsPath;
|
2019-11-12 13:49:56 +11:00
|
|
|
|
var isValidPath = _ioHelper.VerifyEditPath(fullPath, validDir);
|
2019-01-30 23:42:25 +11:00
|
|
|
|
var validExts = new[] {"js"};
|
2019-11-12 13:49:56 +11:00
|
|
|
|
var isValidExtension = _ioHelper.VerifyFileExtension(script.Path, validExts);
|
2017-12-07 16:45:25 +01:00
|
|
|
|
return isValidPath && isValidExtension;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Stream GetFileContentStream(string filepath)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (FileSystem.FileExists(filepath) == false) return null;
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
return FileSystem.OpenFile(filepath);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
return null; // deal with race conds
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SetFileContent(string filepath, Stream content)
|
|
|
|
|
|
{
|
|
|
|
|
|
FileSystem.AddFile(filepath, content, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|