Files
OurUmbraco/OurUmbraco/Repository/Controllers/PackageRepositoryController.cs
T

181 lines
7.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Cors;
using OurUmbraco.Repository.Models;
using OurUmbraco.Repository.Services;
using Umbraco.Core.Cache;
using Umbraco.Web.WebApi;
using System.Net.Http;
using System.Net;
using System.Net.Http.Headers;
using OurUmbraco.Wiki.BusinessLogic;
using Semver;
using Umbraco.Core;
using Umbraco.Web;
namespace OurUmbraco.Repository.Controllers
{
/// <summary>
/// The package repository controller for querying packages
/// </summary>
/// <remarks>
/// This is NOT auto-routed
/// </remarks>
[EnableCors(origins: "*", headers: "*", methods: "*")]
[CamelCaseFormatter]
[OutgoingDateTimeFormat]
public class PackageRepositoryController : UmbracoApiControllerBase
{
private PackageRepositoryService _service;
internal PackageRepositoryService Service
{
get { return _service ?? (_service = new PackageRepositoryService(Umbraco, Members, DatabaseContext)); }
}
public IEnumerable<Models.Category> GetCategories()
{
// [LK:2016-06-13@CGRT16] We're hardcoding the categories as the 'icon' isn't
// content-manageable (yet). There is a media-picker icon, but that's for a different use.
// When the time comes, we can switch to query for the Category nodes directly.
return new[]
{
new Models.Category
{
Icon = "icon-male-and-female",
Name = "Collaboration"
},
new Models.Category
{
Icon = "icon-molecular-network",
Name = "Backoffice extensions"
},
new Models.Category
{
Icon = "icon-brackets",
Name = "Developer tools"
},
new Models.Category
{
Icon = "icon-wand",
Name = "Starter kits"
},
new Models.Category
{
Icon = "icon-medal",
Name = "Umbraco Pro"
},
new Models.Category
{
Icon = "icon-wrench",
Name = "Website utilities"
}
};
}
[HttpGet]
public PagedPackages Search(
int pageIndex,
int pageSize,
string category = null,
string query = null,
string version = null,
PackageSortOrder order = PackageSortOrder.Latest)
{
//return the results, but cache for 1 minute
var key = string.Format("PackageRepositoryController.GetCategories.{0}.{1}.{2}.{3}.{4}", pageIndex, pageSize, category ?? string.Empty, query ?? string.Empty, order);
return ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem<PagedPackages>
(key,
() => Service.GetPackages(pageIndex, pageSize, category, query, version, order),
TimeSpan.FromMinutes(1)); //cache for 1 min
}
/// <summary>
/// Returns the package details for the package Id passed in and ensures that
/// the resulting ZipUrl is the compatible package for the version passed in.
/// </summary>
/// <param name="id"></param>
/// <param name="version">The umbraco version requesting the details, if null than the ZipUrl will be the latest package zip</param>
/// <param name="asFile">pass in true to get the package file otherwise leave blank or set to false to retreive the package details</param>
/// <returns></returns>
public HttpResponseMessage Get(Guid id, string version = null, bool? asFile = false)
{
SemVersion parsed = null;
if (version.IsNullOrWhiteSpace() == false)
{
SemVersion.TryParse(version, out parsed);
}
else
{
//if the version is null then the current umbraco version must be 7.5.x because this endpoint was only ever used by 7.5.x and 7.6.x and above will always
// suppy the version, therefore we can assume that this is 7.5.x, let's make it 7.5.13 which is the latest 7.5 we have right now
parsed = new SemVersion(7, 5, 13);
}
//this should never be null, if it is return not found
if (parsed == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
var v = new System.Version(parsed.Major, parsed.Minor, parsed.Patch);
return asFile.HasValue && asFile.Value
? GetPackageFile(id, v)
: GetDetails(id, v);
}
private HttpResponseMessage GetDetails(Guid id, System.Version currUmbracoVersion)
{
//return the results, but cache for 1 minute
var key = string.Format("PackageRepositoryController.GetDetails.{0}.{1}", id, currUmbracoVersion.ToString(3));
var package = ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem<PackageDetails>
(key,
() =>
{
var details = Service.GetDetails(id, currUmbracoVersion);
if (details.ZipUrl.IsNullOrWhiteSpace())
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "This package is not compatible with the Umbraco version " + currUmbracoVersion));
return details;
},
TimeSpan.FromMinutes(1)); //cache for 1 min
if (package == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return Request.CreateResponse(HttpStatusCode.OK, package);
}
private HttpResponseMessage GetPackageFile(Guid packageId, System.Version currUmbracoVersion)
{
var pckRepoService = new PackageRepositoryService(Umbraco, Members, DatabaseContext);
var details = pckRepoService.GetDetails(packageId, currUmbracoVersion);
if (details == null)
throw new InvalidOperationException("No package found with id " + packageId);
if (details.ZipUrl.IsNullOrWhiteSpace())
throw new InvalidOperationException("This package is not compatible with the Umbraco version " + currUmbracoVersion);
var wf = new WikiFile(details.ZipFileId);
if (wf == null)
throw new InvalidOperationException("Could not find wiki file by id " + details.ZipFileId);
wf.UpdateDownloadCounter(true, true);
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(wf.ToByteArray())
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return result;
}
}
}