webdav portal add owa put relative support

This commit is contained in:
vfedosevich 2015-02-05 05:32:29 -08:00
parent a6b57486bd
commit 2968fbb967
16 changed files with 199 additions and 20 deletions

View file

@ -29,8 +29,13 @@ namespace WebsitePanel.WebDav.Core.Entities.Owa
public bool SupportsUpdate { get; set; }
[DataMember]
public bool UserCanWrite { get; set; }
[DataMember]
public string DownloadUrl { get; set; }
[DataMember]
public bool ReadOnly { get; set; }
//[DataMember]
//public bool ReadOnly { get; set; }
//public bool UserCanNotWriteRelative { get; set; }
//[DataMember]
//public string SHA256 { get; set; }
@ -61,8 +66,6 @@ namespace WebsitePanel.WebDav.Core.Entities.Owa
//[DataMember]
//public bool DisableTranslation { get; set; }
//[DataMember]
//public string DownloadUrl { get; set; }
//[DataMember]
//public string FileSharingUrl { get; set; }
//[DataMember]
//public string FileUrl { get; set; }
@ -112,8 +115,7 @@ namespace WebsitePanel.WebDav.Core.Entities.Owa
//public string TimeZone { get; set; }
//[DataMember]
//public bool UserCanAttend { get; set; }
//[DataMember]
//public bool UserCanNotWriteRelative { get; set; }
//[DataMember]
//public bool UserCanPresent { get; set; }
//[DataMember]

View file

@ -0,0 +1,10 @@
namespace WebsitePanel.WebDav.Core.Entities.Owa
{
public class PutRelativeFile
{
public string Name { get; set; }
public string Url { get; set; }
public string HostViewUrl { get; set; }
public string HostEditUrl { get; set; }
}
}

View file

@ -0,0 +1,12 @@
namespace WebsitePanel.WebDav.Core.Extensions
{
public static class StringExtensions
{
public static string ReplaceLast(this string source, string target, string newValue)
{
int index = source.LastIndexOf(target);
string result = source.Remove(index, target.Length).Insert(index, newValue);
return result;
}
}
}

View file

@ -9,6 +9,7 @@ namespace WebsitePanel.WebDav.Core.Interfaces.Managers
{
IEnumerable<IHierarchyItem> OpenFolder(string path);
bool IsFile(string path);
bool FileExist(string path);
byte[] GetFileBytes(string path);
void UploadFile(string path, HttpPostedFileBase file);
void UploadFile(string path, byte[] bytes);

View file

@ -226,6 +226,26 @@ namespace WebsitePanel.WebDav.Core.Managers
}
}
public bool FileExist(string path)
{
try
{
string folder = GetFileFolder(path);
var resourceName = GetResourceName(path);
OpenFolder(folder);
var resource = _currentFolder.GetResource(resourceName);
return resource != null;
}
catch (InvalidOperationException exception)
{
return false;
}
}
public string GetFileUrl(string path)
{
try

View file

@ -4,27 +4,38 @@ using System.Linq;
using System.Net.Mime;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Web;
using System.Web.Mvc;
using WebsitePanel.WebDav.Core.Client;
using WebsitePanel.WebDav.Core.Config;
using WebsitePanel.WebDav.Core.Entities.Owa;
using WebsitePanel.WebDav.Core.Interfaces.Managers;
using WebsitePanel.WebDav.Core.Interfaces.Owa;
using WebsitePanel.WebDav.Core.Interfaces.Security;
using WebsitePanel.WebDav.Core.Security.Authentication.Principals;
using WebsitePanel.WebDav.Core.Security.Authorization.Enums;
namespace WebsitePanel.WebDav.Core.Owa
{
public class WopiServer : IWopiServer
{
private readonly IWebDavManager _webDavManager;
private readonly IAccessTokenManager _tokenManager;
private readonly IWebDavAuthorizationService _webDavAuthorizationService;
public WopiServer(IWebDavManager webDavManager)
public WopiServer(IWebDavManager webDavManager, IAccessTokenManager tokenManager, IWebDavAuthorizationService webDavAuthorizationService)
{
_webDavManager = webDavManager;
_tokenManager = tokenManager;
_webDavAuthorizationService = webDavAuthorizationService;
}
public CheckFileInfo GetCheckFileInfo(string path)
{
var resource = _webDavManager.GetResource(path);
var readOnly = _webDavAuthorizationService.GetPermissions(WspContext.User, path).HasFlag(WebDavPermissions.Write) == false;
var cFileInfo = new CheckFileInfo
{
BaseFileName = resource.DisplayName,
@ -38,7 +49,8 @@ namespace WebsitePanel.WebDav.Core.Owa
SupportsScenarioLinks = false,
SupportsSecureStore = false,
SupportsUpdate = true,
UserCanWrite = true
UserCanWrite = !readOnly,
ReadOnly = readOnly
};
return cFileInfo;

View file

@ -64,8 +64,8 @@ namespace WebsitePanel.WebDav.Core.Security.Authorization
private IEnumerable<ESPermission> GetFolderEsPermissions(WspPrincipal principal, string rootFolderName)
{
var dictionary = HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.WebDavRootFoldersPermissions] as
Dictionary<string, IEnumerable<ESPermission>>;
var dictionary = HttpContext.Current.Session != null ?HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.WebDavRootFoldersPermissions] as
Dictionary<string, IEnumerable<ESPermission>> : null;
if (dictionary == null)
{
@ -80,7 +80,10 @@ namespace WebsitePanel.WebDav.Core.Security.Authorization
dictionary.Add(rootFolder.Name, permissions);
}
HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.WebDavRootFoldersPermissions] = dictionary;
if (HttpContext.Current.Session != null)
{
HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.WebDavRootFoldersPermissions] = dictionary;
}
}
return dictionary.ContainsKey(rootFolderName) ? dictionary[rootFolderName] : new ESPermission[0];
@ -88,14 +91,16 @@ namespace WebsitePanel.WebDav.Core.Security.Authorization
private IEnumerable<ExchangeAccount> GetUserSecurityGroups(WspPrincipal principal)
{
var groups = HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.UserGroupsKey] as
IEnumerable<ExchangeAccount>;
var groups = HttpContext.Current.Session != null ? HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.UserGroupsKey] as IEnumerable<ExchangeAccount> : null;
if (groups == null)
{
groups = WSP.Services.Organizations.GetSecurityGroupsByMember(principal.ItemId, principal.AccountId);
HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.UserGroupsKey] = groups;
if (HttpContext.Current.Session != null)
{
HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.UserGroupsKey] = groups;
}
}
return groups ?? new ExchangeAccount[0];

View file

@ -125,11 +125,13 @@
<Compile Include="Config\WebConfigSections\WebsitePanelConstantUserElement.cs" />
<Compile Include="Config\WebDavAppConfigManager.cs" />
<Compile Include="Entities\Owa\CheckFileInfo.cs" />
<Compile Include="Entities\Owa\PutRelativeFile.cs" />
<Compile Include="Exceptions\ConnectToWebDavServerException.cs" />
<Compile Include="Exceptions\ResourceNotFoundException.cs" />
<Compile Include="Exceptions\UnauthorizedException.cs" />
<Compile Include="Exceptions\WebDavException.cs" />
<Compile Include="Exceptions\WebDavHttpException.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Extensions\UriExtensions.cs" />
<Compile Include="IConnectionSettings.cs" />
<Compile Include="IFolder.cs" />

View file

@ -67,6 +67,7 @@ textarea {
#logout {
font-size: 1.2em;
color: #9d9d9d;
margin-bottom: 0px;
}
#logout :hover {
@ -125,6 +126,10 @@ input,div{border-radius:0px!important;}
border-color: #2e8bcc;
}
.navbar-collapse, .navbar-header {
padding-top: 4px;
}
.navbar-inverse .navbar-brand, .navbar-text, #logout{
color: #FFFFFF;
opacity: 0.8;
@ -152,6 +157,7 @@ div#breadcrumb_wrapper a:last-child {
float: none;
display: inline-block;
margin-right: 10px;
vertical-align: top;
}
.header-portal-title {

View file

@ -22,6 +22,9 @@ using WebsitePanel.WebDav.Core.Interfaces.Security;
using WebsitePanel.WebDav.Core.Security.Cryptography;
using WebsitePanel.WebDav.Core.Wsp.Framework;
using WebsitePanel.WebDavPortal.Configurations.ControllerConfigurations;
using WebsitePanel.WebDavPortal.Extensions;
using WebsitePanel.WebDavPortal.UI.Routes;
using WebsitePanel.WebDav.Core.Extensions;
namespace WebsitePanel.WebDavPortal.Controllers.Api
{
@ -53,6 +56,11 @@ namespace WebsitePanel.WebDavPortal.Controllers.Api
var fileInfo = _wopiServer.GetCheckFileInfo(token.FilePath);
var urlPart = Url.Route(FileSystemRouteNames.ShowContentPath, new { org = WspContext.User.OrganizationId, pathPart = token.FilePath });
var url = new Uri(Request.RequestUri, urlPart).ToString();
fileInfo.DownloadUrl = url;
return fileInfo;
}
@ -128,5 +136,56 @@ namespace WebsitePanel.WebDavPortal.Controllers.Api
return new HttpResponseMessage(HttpStatusCode.OK);
}
[HttpPost]
public PutRelativeFile Put_Relative(int accessTokenId)
{
var result = new PutRelativeFile();
var token = _tokenManager.GetToken(accessTokenId);
var newFilePath = string.Empty;
var target = Request.Headers.Contains("X-WOPI-RelativeTarget") ? Request.Headers.GetValues("X-WOPI-RelativeTarget").First() : Request.Headers.GetValues("X-WOPI-SuggestedTarget").First();
bool overwrite = Request.Headers.Contains("X-WOPI-RelativeTarget") && Convert.ToBoolean(Request.Headers.GetValues("X-WOPI-OverwriteRelativeTarget").First());
if (string.IsNullOrEmpty(target))
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
if (target.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries).Count() > 1)
{
var fileName = Path.GetFileName(token.FilePath);
newFilePath = token.FilePath.ReplaceLast(fileName, target);
}
else
{
newFilePath = Path.ChangeExtension(token.FilePath, target);
}
if (overwrite == false && _webDavManager.FileExist(newFilePath))
{
throw new HttpResponseException(HttpStatusCode.Conflict);
}
var bytes = Request.Content.ReadAsByteArrayAsync().Result;
_webDavManager.UploadFile(newFilePath, bytes);
var newToken = _tokenManager.CreateToken(WspContext.User,newFilePath);
var readUrlPart = Url.Route(FileSystemRouteNames.ShowOfficeOnlinePath, new { org = WspContext.User.OrganizationId, pathPart = newFilePath, fileAccess = FileAccess.Read });
var writeUrlPart = Url.Route(FileSystemRouteNames.ShowOfficeOnlinePath, new { org = WspContext.User.OrganizationId, pathPart = newFilePath, fileAccess = FileAccess.Write });
result.HostEditUrl = new Uri(Request.RequestUri, writeUrlPart).ToString();
result.HostViewUrl = new Uri(Request.RequestUri, readUrlPart).ToString(); ;
result.Name = Path.GetFileName(newFilePath);
result.Url = Url.GenerateWopiUrl(newToken, newFilePath);
return result;
}
}
}

View file

@ -83,7 +83,7 @@ namespace WebsitePanel.WebDavPortal.Controllers
}
}
public ActionResult ShowOfficeDocument(string org, string pathPart = "")
public ActionResult ShowOfficeDocument(string org, string pathPart = "", FileAccess? fileAccess = null)
{
var permissions = _webDavAuthorizationService.GetPermissions(WspContext.User, pathPart);
@ -97,11 +97,22 @@ namespace WebsitePanel.WebDavPortal.Controllers
string wopiSrc = Server.UrlDecode(url);
string owaOpenerUri = permissions.HasFlag(WebDavPermissions.Write) ? owaOpener.OwaEditor : owaOpener.OwaView;
string owaOpenerUri = string.Empty;
if (fileAccess == null)
{
owaOpenerUri = permissions.HasFlag(WebDavPermissions.Write) ? owaOpener.OwaEditor : owaOpener.OwaView;
}
else
{
owaOpenerUri = permissions.HasFlag(WebDavPermissions.Write) && fileAccess == FileAccess.Write ? owaOpener.OwaEditor : owaOpener.OwaView;
}
var uri = string.Format("{0}/{1}WOPISrc={2}&access_token={3}", WebDavAppConfigManager.Instance.OfficeOnline.Url, owaOpenerUri, Server.UrlEncode(wopiSrc), Server.UrlEncode(accessToken.AccessToken.ToString("N")));
return View(new OfficeOnlineModel(uri, new Uri(fileUrl).Segments.Last()));
string fileName = fileUrl.Split('/').Last();
return View(new OfficeOnlineModel(uri, fileName));
}
[HttpPost]

View file

@ -0,0 +1,38 @@
using System;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Http.Routing;
using WebsitePanel.EnterpriseServer.Base.HostedSolution;
using WebsitePanel.WebDav.Core;
using WebsitePanel.WebDav.Core.Config;
using WebsitePanel.WebDavPortal.UI.Routes;
namespace WebsitePanel.WebDavPortal.Extensions
{
public static class UrlHelperExtensions
{
public static String GenerateWopiUrl(this System.Web.Mvc.UrlHelper urlHelper, WebDavAccessToken token, string path)
{
var urlPart = urlHelper.HttpRouteUrl(OwaRouteNames.CheckFileInfo, new { accessTokenId = token.Id });
return GenerateWopiUrl(token, urlPart, path);
}
public static String GenerateWopiUrl(this UrlHelper urlHelper, WebDavAccessToken token, string path)
{
var urlPart = urlHelper.Route(OwaRouteNames.CheckFileInfo, new { accessTokenId = token.Id });
return GenerateWopiUrl(token, urlPart, path);
}
private static string GenerateWopiUrl(WebDavAccessToken token, string urlPart, string path)
{
var url = new Uri(HttpContext.Current.Request.Url, urlPart).ToString();
string wopiSrc = HttpUtility.UrlDecode(url);
return string.Format("{0}&access_token={1}", wopiSrc, token.AccessToken.ToString("N"));
}
}
}

View file

@ -9,7 +9,6 @@
@model WebsitePanel.WebDavPortal.Models.ModelForWebDav
@{
var webDavManager = DependencyResolver.Current.GetService<IWebDavManager>();
ViewBag.Title = WebDavAppConfigManager.Instance.ApplicationName;
}

View file

@ -7,7 +7,7 @@
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@Model.FileName</title>
<title>@Html.Raw(Model.FileName)</title>
</head>
<body>
<iframe src='@Model.Url' width="100%" height="100%" frameborder='0' style="bottom: 0px; left: 0px; position: fixed; right: 0px; top: 0px;">

View file

@ -25,8 +25,9 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<img class="header-logo" src="@Url.Content("~/Content/Images/logo.png")" />
@Html.RouteLink(WebDavAppConfigManager.Instance.ApplicationName, FileSystemRouteNames.ShowContentPath, new { pathPart = string.Empty }, new { @class = "navbar-brand header-portal-title" })
<a href="@Url.RouteUrl(FileSystemRouteNames.ShowContentPath, new { pathPart = string.Empty })">
<img class="header-logo" src="@Url.Content("~/Content/Images/logo.png")" />
</a>
</div>
<div class="navbar-collapse collapse">
@{

View file

@ -171,6 +171,7 @@
<Compile Include="DependencyInjection\Providers\WebDavManagerProvider.cs" />
<Compile Include="Extensions\DictionaryExtensions.cs" />
<Compile Include="Extensions\UriExtensions.cs" />
<Compile Include="Extensions\UrlHelperExtensions.cs" />
<Compile Include="FileOperations\FileOpenerManager.cs" />
<Compile Include="FileOperations\FileOpenerType.cs" />
<Compile Include="Global.asax.cs">