Exemplo n.º 1
0
        public override async Task <WopiResponse> GetLock(GetLockRequest getLockRequest)
        {
            var userId             = WopiSecurity.GetIdentityNameFromToken(getLockRequest.AccessToken);
            var wopiFileRepository = new WopiFileRepository();
            var response           = await wopiFileRepository.GetLockStatus(getLockRequest.ResourceId, userId);

            // Check for file not found or no permissions
            if (response.Item1 == HttpStatusCode.NotFound)
            {
                return(getLockRequest.ResponseNotFound());
            }
            // Ensure the file isn't already locked
            else if (response.Item1 == HttpStatusCode.Conflict)
            {
                return(getLockRequest.ResponseLockConflict(response.Item2));
            }
            // File successfully locked
            else if (response.Item1 == HttpStatusCode.OK)
            {
                if (response.Item2 != null)
                {
                    return(getLockRequest.ResponseFileLocked(response.Item2));
                }
                else
                {
                    return(getLockRequest.ResponseFileNotLocked());
                }
            }
            else
            {
                return(getLockRequest.ResponseServerError(string.Format("Unknown HTTPStatusCode from WopiFileRepository.GetLockStatus: {0}", response.Item1)));
            }
        }
Exemplo n.º 2
0
        public override async Task <WopiResponse> RenameFile(RenameFileRequest renameFileRequest)
        {
            var userId = WopiSecurity.GetIdentityNameFromToken(renameFileRequest.AccessToken);

            var wopiFileRepository = new WopiFileRepository();
            var response           = await wopiFileRepository.RenameFile(renameFileRequest.ResourceId, userId, renameFileRequest.Lock, renameFileRequest.RequestedName);

            if (response.Item1 == HttpStatusCode.NotFound)
            {
                return(renameFileRequest.ResponseNotFound());
            }
            else if (response.Item1 == HttpStatusCode.Conflict)
            {
                return(renameFileRequest.ResponseLockConflict(response.Item2));
            }
            else if (response.Item1 == HttpStatusCode.BadRequest)
            {
                return(renameFileRequest.ResponseBadRequest(response.Item2));
            }
            else if (response.Item1 == HttpStatusCode.OK)
            {
                return(renameFileRequest.ResponseOK(response.Item2));
            }
            else
            {
                return(renameFileRequest.ResponseServerError(string.Format("Unknown HTTPStatusCode from WopiFileRepository.RenameFile: {0}", response.Item1)));
            }
        }
Exemplo n.º 3
0
        public override Task <bool> Authorize(WopiRequest wopiRequest)
        {
            try
            {
                if (string.IsNullOrEmpty(wopiRequest.AccessToken))
                {
                    return(Task.FromResult <bool>(false));
                }

                // Get the requested file from Document DB
                var itemId   = new Guid(wopiRequest.ResourceId);
                var wopiFile = DocumentDBRepository <DetailedFileModel> .GetItem("Files", file => file.id == itemId);

                // Check for missing file
                if (wopiFile == null)
                {
                    return(Task.FromResult <bool>(false));
                }

                // Validate the access token
                return(Task.FromResult <bool>(WopiSecurity.ValidateToken(wopiRequest.AccessToken, wopiFile.Container, wopiFile.id.ToString())));
            }
            catch (Exception)
            {
                // Any exception will return false, but should probably return an alternate status codes
                return(Task.FromResult <bool>(false));
            }
        }
Exemplo n.º 4
0
        public override async Task <WopiResponse> UnlockAndRelock(UnlockAndRelockRequest unlockAndRelockRequest)
        {
            var userId = WopiSecurity.GetIdentityNameFromToken(unlockAndRelockRequest.AccessToken);

            var wopiFileRepository = new WopiFileRepository();
            var response           = await wopiFileRepository.LockFile(unlockAndRelockRequest.ResourceId, userId, unlockAndRelockRequest.Lock, unlockAndRelockRequest.OldLock);

            if (response.Item1 == HttpStatusCode.BadRequest)
            {
                return(unlockAndRelockRequest.ResponseBadRequest());
            }
            // Check for file not found or no permissions
            else if (response.Item1 == HttpStatusCode.NotFound)
            {
                return(unlockAndRelockRequest.ResponseNotFound());
            }
            // Ensure the file isn't already locked
            else if (response.Item1 == HttpStatusCode.Conflict)
            {
                return(unlockAndRelockRequest.ResponseLockConflict(response.Item2));
            }
            // File successfully locked
            else if (response.Item1 == HttpStatusCode.OK)
            {
                return(unlockAndRelockRequest.ResponseOK());
            }
            else
            {
                return(unlockAndRelockRequest.ResponseServerError(string.Format("Unknown HTTPStatusCode from WopiFileRepository.LockFile: {0}", response.Item1)));
            }
        }
Exemplo n.º 5
0
        public async Task <ActionResult> Detail(string id)
        {
            var userId = User.Identity.Name;
            var tenant = new MailAddress(userId).Host.Replace(".", "-");

            // Make sure an action was passed in
            if (String.IsNullOrEmpty(Request["action"]))
            {
                return(RedirectToAction("Error", "Home", new { error = "No action provided" }));
            }

            var wopiFileRepository = new WopiFileRepository();
            var result             = await wopiFileRepository.GetFileInfoByTenantUser(id, userId, tenant);

            // Check for null file
            if (result.Item1 == HttpStatusCode.NotFound)
            {
                return(RedirectToAction("Error", "Home", new { error = "Files does not exist" }));
            }
            else if (result.Item1 == HttpStatusCode.Unauthorized)
            {
                return(RedirectToAction("Error", "Home", new { error = "Not authorized to access file" }));
            }
            else if (result.Item1 == HttpStatusCode.OK)
            {
                var wopiFile = result.Item2;
                // Use discovery to determine endpoint to leverage
                List <WopiAction> discoData = await WopiDiscovery.GetActions();

                var fileExt = wopiFile.FileName.Substring(wopiFile.FileName.LastIndexOf('.') + 1).ToLower();
                var action  = discoData.FirstOrDefault(i => i.name == Request["action"] && i.ext == fileExt);

                // Make sure the action isn't null
                if (action != null)
                {
                    string urlsrc = WopiDiscovery.GetActionUrl(action, wopiFile.FileId.ToString(), Request.Url.Authority);

                    // Generate JWT token for the user/document
                    WopiSecurity wopiSecurity = new WopiSecurity();
                    var          token        = wopiSecurity.GenerateToken(User.Identity.Name.ToLower());
                    ViewData["access_token"]     = wopiSecurity.WriteToken(token);
                    ViewData["access_token_ttl"] = token.ValidTo.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
                    ViewData["wopi_urlsrc"]      = urlsrc;
                    return(View());
                }
                else
                {
                    // This will only hit if the extension isn't supported by WOPI
                    return(RedirectToAction("Error", "Home", new { error = "File is not a supported WOPI extension" }));
                }
            }
            else
            {
                return(RedirectToAction("Error", "Home", new { error = "Internal server error" }));
            }
        }
Exemplo n.º 6
0
        public override async Task <WopiResponse> PutRelativeFileSpecific(PutRelativeFileSpecificRequest putRelativeFileSpecificRequest)
        {
            var userId = WopiSecurity.GetIdentityNameFromToken(putRelativeFileSpecificRequest.AccessToken);

            var wopiFileRepository = new WopiFileRepository();
            var response           = await wopiFileRepository.CreateCopy(putRelativeFileSpecificRequest.ResourceId, userId, putRelativeFileSpecificRequest.RelativeTarget, putRelativeFileSpecificRequest.OverwriteRelativeTarget);

            if (response.Item1 == HttpStatusCode.NotFound)
            {
                return(putRelativeFileSpecificRequest.ResponseNotFound());
            }
            else if (response.Item1 == HttpStatusCode.BadRequest)
            {
                return(putRelativeFileSpecificRequest.ResponseBadRequest());
            }
            else if (response.Item1 == HttpStatusCode.Conflict)
            {
                return(putRelativeFileSpecificRequest.ResponseLockConflict(response.Item3));
            }
            else if (response.Item1 == HttpStatusCode.OK)
            {
                // Get access token for the new file
                WopiSecurity security = new WopiSecurity();
                var          token    = security.GenerateToken(response.Item2.OwnerId);
                var          tokenStr = security.WriteToken(token);

                var url = new Uri(string.Format("https://{0}/wopi/files/{1}?access_token={2}",
                                                putRelativeFileSpecificRequest.RequestUri.Authority, response.Item2.FileId, tokenStr));

                Uri hostViewUrl = null;
                Uri hostEditUrl = null;
                var actions     = await WopiDiscovery.GetActions();

                var view = actions.FirstOrDefault(i => i.ext == response.Item2.FileExtension && i.name == "view");
                if (view != null)
                {
                    hostViewUrl = new Uri(WopiDiscovery.GetActionUrl(view, response.Item2.FileId, putRelativeFileSpecificRequest.RequestUri.Authority));
                }
                var edit = actions.FirstOrDefault(i => i.ext == response.Item2.FileExtension && i.name == "edit");
                if (edit != null)
                {
                    hostEditUrl = new Uri(WopiDiscovery.GetActionUrl(edit, response.Item2.FileId, putRelativeFileSpecificRequest.RequestUri.Authority));
                }

                return(putRelativeFileSpecificRequest.ResponseOK(response.Item2.FileName, url, hostViewUrl, hostEditUrl));
            }
            else
            {
                return(putRelativeFileSpecificRequest.ResponseServerError(string.Format("Unknown HTTPStatusCode from WopiFileRepository.CreateCopy: {0}", response.Item1)));
            }
        }
Exemplo n.º 7
0
        public override async Task <WopiResponse> CheckFileInfo(CheckFileInfoRequest checkFileInfoRequest)
        {
            // Lookup the file in the database
            var itemId   = new Guid(checkFileInfoRequest.ResourceId);
            var wopiFile = DocumentDBRepository <DetailedFileModel> .GetItem("Files", file => file.id == itemId);

            // Check for null file
            if (wopiFile != null)
            {
                // Get discovery information
                var fileExt = wopiFile.BaseFileName.Substring(wopiFile.BaseFileName.LastIndexOf('.') + 1).ToLower();
                var actions = await WopiDiscovery.GetActions();

                // Augments the file with additional properties CloseUrl, HostViewUrl, HostEditUrl
                wopiFile.CloseUrl = String.Format("https://{0}", checkFileInfoRequest.RequestUri.Authority);
                var view = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "view");
                if (view != null)
                {
                    wopiFile.HostViewUrl = WopiDiscovery.GetActionUrl(view, wopiFile.id.ToString(), checkFileInfoRequest.RequestUri.Authority);
                }
                var edit = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "edit");
                if (edit != null)
                {
                    wopiFile.HostEditUrl = WopiDiscovery.GetActionUrl(edit, wopiFile.id.ToString(), checkFileInfoRequest.RequestUri.Authority);
                }

                // Get the user from the token (token is already validated)
                wopiFile.UserId = WopiSecurity.GetUserFromToken(checkFileInfoRequest.AccessToken);

                // Write the response and return a success 200
                var wopiResponse = checkFileInfoRequest.ResponseOK(wopiFile.BaseFileName, wopiFile.OwnerId, wopiFile.Size, wopiFile.UserId, wopiFile.Version.ToString());
                // Add optional items
                wopiResponse.CloseUrl = new Uri(wopiFile.CloseUrl);
                if (wopiFile.HostViewUrl != null)
                {
                    wopiResponse.HostViewUrl = new Uri(wopiFile.HostViewUrl);
                }
                if (wopiFile.HostEditUrl != null)
                {
                    wopiResponse.HostEditUrl = new Uri(wopiFile.HostEditUrl);
                }

                return(wopiResponse);
            }
            else
            {
                return(checkFileInfoRequest.ResponseNotFound());
            }
        }
Exemplo n.º 8
0
        public override async Task <WopiResponse> PutRelativeFileSuggested(PutRelativeFileSuggestedRequest putRelativeFileSuggestedRequest)
        {
            var userId = WopiSecurity.GetIdentityNameFromToken(putRelativeFileSuggestedRequest.AccessToken);

            var wopiFileRepository = new WopiFileRepository();
            var response           = await wopiFileRepository.CreateCopySuggested(putRelativeFileSuggestedRequest.ResourceId, userId, putRelativeFileSuggestedRequest.SuggestedTarget);

            if (response.Item1 == HttpStatusCode.NotFound)
            {
                return(putRelativeFileSuggestedRequest.ResponseNotFound());
            }
            else if (response.Item1 == HttpStatusCode.OK)
            {
                // Get access token for the new file
                WopiSecurity security = new WopiSecurity();
                var          token    = security.GenerateToken(response.Item2.OwnerId);
                var          tokenStr = security.WriteToken(token);

                //var name = newFile.BaseFileName;

                var url = new Uri(string.Format("https://{0}/wopi/files/{1}?access_token={2}",
                                                putRelativeFileSuggestedRequest.RequestUri.Authority, response.Item2.FileId, tokenStr));

                // Add the optional properties to response if applicable (HostViewUrl, HostEditUrl)
                Uri hostViewUrl = null;
                Uri hostEditUrl = null;
                var actions     = await WopiDiscovery.GetActions();

                var view = actions.FirstOrDefault(i => i.ext == response.Item2.FileExtension && i.name == "view");
                if (view != null)
                {
                    hostViewUrl = new Uri(WopiDiscovery.GetActionUrl(view, response.Item2.FileId, putRelativeFileSuggestedRequest.RequestUri.Authority));
                }
                var edit = actions.FirstOrDefault(i => i.ext == response.Item2.FileExtension && i.name == "edit");
                if (edit != null)
                {
                    hostEditUrl = new Uri(WopiDiscovery.GetActionUrl(edit, response.Item2.FileId, putRelativeFileSuggestedRequest.RequestUri.Authority));
                }
                // Write the response and return a success 200
                return(putRelativeFileSuggestedRequest.ResponseOK(response.Item2.FileName, url, hostViewUrl, hostEditUrl));
            }
            else
            {
                return(putRelativeFileSuggestedRequest.ResponseServerError(string.Format("Unknown HTTPStatusCode from WopiFileRepository.CreateCopySuggested: {0}", response.Item1)));
            }
        }
Exemplo n.º 9
0
        public override async Task <WopiResponse> GetFile(GetFileRequest getFileRequest)
        {
            var userId = WopiSecurity.GetIdentityNameFromToken(getFileRequest.AccessToken);

            // Lookup the file in the database
            var wopiFileRepository = new WopiFileRepository();
            var response           = await wopiFileRepository.GetFileContent(getFileRequest.ResourceId, userId);

            // Check for null file
            if (response.Item1 == HttpStatusCode.NotFound)
            {
                return(getFileRequest.ResponseNotFound());
            }
            else
            {
                // Write the response and return success 200
                return(getFileRequest.ResponseOK(new StreamContent(response.Item2), response.Item3));
            }
        }
Exemplo n.º 10
0
        public override async Task <WopiResponse> PutUserInfo(PutUserInfoRequest putUserInfoRequest)
        {
            var userId = WopiSecurity.GetIdentityNameFromToken(putUserInfoRequest.AccessToken);
            var wopiFileRespository = new WopiFileRepository();
            var response            = await wopiFileRespository.SaveWopiUserInfo(putUserInfoRequest.ResourceId, userId, putUserInfoRequest.UserInfo);

            if (response == HttpStatusCode.NotFound)
            {
                return(putUserInfoRequest.ResponseNotFound());
            }
            else if (response == HttpStatusCode.OK)
            {
                return(putUserInfoRequest.ResponseOK());
            }
            else
            {
                return(putUserInfoRequest.ResponseServerError(string.Format("Unknown HTTPStatusCode from WopiFileRepository.SaveWopiUserInfo: {0}", response)));
            }
        }
Exemplo n.º 11
0
        public override async Task <WopiResponse> DeleteFile(DeleteFileRequest deleteFileRequest)
        {
            var userId = WopiSecurity.GetIdentityNameFromToken(deleteFileRequest.AccessToken);
            var wopiFileRespository = new WopiFileRepository();
            var response            = await wopiFileRespository.DeleteFile(deleteFileRequest.ResourceId, userId);

            if (response == HttpStatusCode.NotFound)
            {
                return(deleteFileRequest.ResponseNotFound());
            }
            else if (response == HttpStatusCode.OK)
            {
                return(deleteFileRequest.ResponseOK());
            }
            else
            {
                return(deleteFileRequest.ResponseServerError(string.Format("Unknown HTTPStatusCode from WopiFileRepository.UpdateFileContent: {0}", response)));
            }
        }
Exemplo n.º 12
0
        public async Task <ActionResult> Detail(Guid id)
        {
            // Make sure an action was passed in
            if (String.IsNullOrEmpty(Request["action"]))
            {
                return(RedirectToAction("Error", "Home", new { error = "No action provided" }));
            }

            // Get the specific file from DocumentDB
            var wopiFile = DocumentDBRepository <FileModel> .GetItem("Files",
                                                                     i => i.OwnerId == User.Identity.Name.ToLower() && i.id == id);

            // Check for null file
            if (wopiFile == null)
            {
                return(RedirectToAction("Error", "Home", new { error = "Files does not exist" }));
            }

            // Use discovery to determine endpoint to leverage
            List <WopiAction> discoData = await WopiDiscovery.GetActions();

            var fileExt = wopiFile.BaseFileName.Substring(wopiFile.BaseFileName.LastIndexOf('.') + 1).ToLower();
            var action  = discoData.FirstOrDefault(i => i.name == Request["action"] && i.ext == fileExt);

            // Make sure the action isn't null
            if (action != null)
            {
                string urlsrc = WopiDiscovery.GetActionUrl(action, wopiFile.id.ToString(), Request.Url.Authority);

                // Generate JWT token for the user/document
                WopiSecurity wopiSecurity = new WopiSecurity();
                var          token        = wopiSecurity.GenerateToken(User.Identity.Name.ToLower(), getUserContainer(), id.ToString());
                ViewData["access_token"]     = wopiSecurity.WriteToken(token);
                ViewData["access_token_ttl"] = token.ValidTo.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
                ViewData["wopi_urlsrc"]      = urlsrc;
                return(View());
            }
            else
            {
                // This will only hit if the extension isn't supported by WOPI
                return(RedirectToAction("Error", "Home", new { error = "File is not a supported WOPI extension" }));
            }
        }
Exemplo n.º 13
0
        public override async Task <WopiResponse> GetFile(GetFileRequest getFileRequest)
        {
            // Lookup the file in the database
            var itemId   = new Guid(getFileRequest.ResourceId);
            var wopiFile = DocumentDBRepository <DetailedFileModel> .GetItem("Files", file => file.id == itemId);

            // Check for null file
            if (wopiFile != null)
            {
                // Get discovery information
                var fileExt = wopiFile.BaseFileName.Substring(wopiFile.BaseFileName.LastIndexOf('.') + 1).ToLower();
                var actions = await WopiDiscovery.GetActions();

                // Augments the file with additional properties CloseUrl, HostViewUrl, HostEditUrl
                wopiFile.CloseUrl = String.Format("https://{0}", getFileRequest.RequestUri.Authority);
                var view = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "view");
                if (view != null)
                {
                    wopiFile.HostViewUrl = WopiDiscovery.GetActionUrl(view, wopiFile.id.ToString(), getFileRequest.RequestUri.Authority);
                }
                var edit = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "edit");
                if (edit != null)
                {
                    wopiFile.HostEditUrl = WopiDiscovery.GetActionUrl(edit, wopiFile.id.ToString(), getFileRequest.RequestUri.Authority);
                }

                // Get the user from the token (token is already validated)
                wopiFile.UserId = WopiSecurity.GetUserFromToken(getFileRequest.AccessToken);

                // Call the appropriate handler for the WOPI request we received
                // Get the file from blob storage
                var bytes = await AzureStorageUtil.GetFile(wopiFile.id.ToString(), wopiFile.Container);

                // Write the response and return success 200
                return(getFileRequest.ResponseOK(new ByteArrayContent(bytes)));
            }
            else
            {
                return(getFileRequest.ResponseNotFound());
            }
        }
Exemplo n.º 14
0
        public override Task <bool> Authorize(WopiRequest wopiRequest)
        {
            try
            {
                if (string.IsNullOrEmpty(wopiRequest.AccessToken))
                {
                    return(Task.FromResult <bool>(false));
                }

                // Validate the access token contains authenticated user
                // We're only doing authentication here and deferring authorization to the other WOPI operations
                // to avoid multiple DB queries
                var userId = WopiSecurity.GetIdentityNameFromToken(wopiRequest.AccessToken);
                return(Task.FromResult <bool>(userId != null));
            }
            catch (Exception)
            {
                // Any exception will return false, but should probably return an alternate status codes
                return(Task.FromResult <bool>(false));
            }
        }
Exemplo n.º 15
0
        public async System.Threading.Tasks.Task <string> Url(UserAction ua = null)
        {
            if (ua == null)
            {
                ua = new UserAction();
            }

            // Use discovery to determine endpoint to leverage
            List <WopiAction> discoData = await WopiUtil.GetDiscoveryInfo();

            var fileExt = BaseFileName.Substring(BaseFileName.LastIndexOf('.') + 1).ToLower();
            var action  = discoData.FirstOrDefault(i => i.name == ua.Action && i.ext == fileExt);

            if (action != null)
            {
                string urlsrc = WopiUtil.GetActionUrl(action, this, ServerUtil.Config().Domain);

                WopiSecurity wopiSecurity = new WopiSecurity();

                var token = wopiSecurity.GenerateToken(id.ToString(), ua.UserId, ua.UserDisplayName);

                if (action.name == "edit")
                {
                    token.ReadOnly = false;
                }
                else
                {
                    token.ReadOnly = true;
                }
                token.Save();

                return(String.Format("{0}&access_token={1}&access_token_ttl={2}", urlsrc, token.Identity, token.ValidTo().Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds.ToString()));
            }
            else
            {
                // This will only hit if the extension isn't supported by WOPI
                throw new Exception("Bad action on this file.");
            }
        }
Exemplo n.º 16
0
        public override async Task <WopiResponse> PutFile(PutFileRequest putFileRequest)
        {
            var userId = WopiSecurity.GetIdentityNameFromToken(putFileRequest.AccessToken);
            var wopiFileRespository = new WopiFileRepository();
            var response            = await wopiFileRespository.UpdateFileContent(putFileRequest.ResourceId, userId, putFileRequest.Lock, await putFileRequest.Content.ReadAsStreamAsync());

            if (response.Item1 == HttpStatusCode.NotFound)
            {
                return(putFileRequest.ResponseNotFound());
            }
            else if (response.Item1 == HttpStatusCode.Conflict)
            {
                return(putFileRequest.ResponseLockConflict(response.Item2));
            }
            else if (response.Item1 == HttpStatusCode.OK)
            {
                return(putFileRequest.ResponseOK(response.Item3));
            }
            else
            {
                return(putFileRequest.ResponseServerError(string.Format("Unknown HTTPStatusCode from WopiFileRepository.UpdateFileContent: {0}", response.Item1)));
            }
        }
Exemplo n.º 17
0
        // POST api/<controller>
        public HttpResponseMessage Post([FromBody] AuthInfo info)
        {
            try
            {
                var clients = ClientIdentity.Select(id => id.ClientID == info.ClientID).ToList();

                if (clients.Count == 0)
                {
                    return(ServerUtil.returnStatus(HttpStatusCode.Unauthorized, "Authorization Failed"));
                }

                var client = clients[0];
                if (WopiSecurity.MD5Encrypt(client.ClientSecret + ServerUtil.AuthenticationKey()) == info.SecureString)
                {
                    var response = ServerUtil.returnStatus(HttpStatusCode.OK, "Success");

                    client.Token   = WopiSecurity.MD5Encrypt(Guid.NewGuid().ToString());
                    client.Counter = 1;

                    client.Save();

                    response.Content = new StringContent(client.Token);

                    return(response);
                }
                else
                {
                    return(ServerUtil.returnStatus(HttpStatusCode.Unauthorized, "Authorization Failed"));
                }
            }
            catch (Exception ex)
            {
                ServerUtil.LogException(ex);
                return(ServerUtil.returnStatus(HttpStatusCode.BadRequest, "Invalid Request"));
            }
        }
Exemplo n.º 18
0
        public override async Task <WopiResponse> PutRelativeFileSuggested(PutRelativeFileSuggestedRequest putRelativeFileSuggestedRequest)
        {
            WopiResponse wopiResponse = null;
            var          file         = DocumentDBRepository <DetailedFileModel> .GetItem("Files", i => i.id.ToString() == putRelativeFileSuggestedRequest.ResourceId);

            // Check for null file
            if (file != null)
            {
                var inputStream = await putRelativeFileSuggestedRequest.Content.ReadAsStreamAsync();

                // Suggested mode...might just be an extension
                var fileName = putRelativeFileSuggestedRequest.SuggestedTarget;
                if (fileName.IndexOf('.') == 0)
                {
                    fileName = file.BaseFileName.Substring(0, file.BaseFileName.LastIndexOf('.')) + fileName;
                }

                // Create the file entity
                FileModel newFile = new FileModel()
                {
                    id           = Guid.NewGuid(),
                    OwnerId      = file.OwnerId,
                    BaseFileName = fileName,
                    Size         = inputStream.Length,
                    Container    = file.Container,
                    Version      = 1
                };

                // First stream the file into blob storage
                var bytes = new byte[inputStream.Length];
                await inputStream.ReadAsync(bytes, 0, (int)inputStream.Length);

                var id = await Utils.AzureStorageUtil.UploadFile(newFile.id.ToString(), newFile.Container, bytes);

                // Write the details into documentDB
                await DocumentDBRepository <FileModel> .CreateItemAsync("Files", (FileModel)newFile);

                // Get access token for the new file
                WopiSecurity security = new WopiSecurity();
                var          token    = security.GenerateToken(newFile.OwnerId, newFile.Container, newFile.id.ToString());
                var          tokenStr = security.WriteToken(token);

                // Prepare the Json response
                var name = newFile.BaseFileName;

                var url = string.Format("https://{0}/wopi/files/{1}?access_token={2}",
                                        putRelativeFileSuggestedRequest.RequestUri.Authority, newFile.id.ToString(), tokenStr);

                // Add the optional properties to response if applicable (HostViewUrl, HostEditUrl)
                string hostViewUrl = null;
                string hostEditUrl = null;
                var    actions     = await WopiDiscovery.GetActions();

                var fileExt = newFile.BaseFileName.Substring(newFile.BaseFileName.LastIndexOf('.') + 1).ToLower();
                var view    = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "view");
                if (view != null)
                {
                    hostViewUrl = WopiDiscovery.GetActionUrl(view, newFile.id.ToString(), putRelativeFileSuggestedRequest.RequestUri.Authority);
                }
                var edit = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "edit");
                if (edit != null)
                {
                    hostEditUrl = WopiDiscovery.GetActionUrl(edit, newFile.id.ToString(), putRelativeFileSuggestedRequest.RequestUri.Authority);
                }

                // Write the response and return a success 200
                wopiResponse = putRelativeFileSuggestedRequest.ResponseOK(fileName, new Uri(url), new Uri(hostViewUrl), new Uri(hostEditUrl));
            }
            else
            {
                wopiResponse = putRelativeFileSuggestedRequest.ResponseNotFound();
            }
            return(wopiResponse);
        }
        /// <summary>
        /// Processes a WOPI request using the HttpContext of the APIController
        /// </summary>
        public async static Task <HttpResponseMessage> ProcessWopiRequest(this HttpContext context)
        {
            // Parse the request
            var request = ParseRequest(context.Request);
            HttpResponseMessage response = null;

            try
            {
                // Lookup the file in the database
                var itemId = new Guid(request.Id);
                var file   = DocumentRepository <DetailedFileModel> .GetItem("Files", i => i.id == itemId);

                // Check for null file
                if (file == null)
                {
                    response = returnStatus(HttpStatusCode.NotFound, "File Unknown/User Unauthorized");
                }
                else
                {
                    // Validate WOPI Proof (ie - ensure request came from Office Online)
                    if (await WopiUtil.ValidateWopiProof(context))
                    {
                        // Get discovery information
                        var fileExt = file.BaseFileName.Substring(file.BaseFileName.LastIndexOf('.') + 1).ToLower();
                        var actions = await WopiUtil.GetDiscoveryInfo();

                        // Augments the file with additional properties CloseUrl, HostViewUrl, HostEditUrl
                        file.CloseUrl = String.Format("https://{0}", context.Request.Url.Authority);
                        var view = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "view");
                        if (view != null)
                        {
                            file.HostViewUrl = WopiUtil.GetActionUrl(view, file, context.Request.Url.Authority);
                        }
                        var edit = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "edit");
                        if (edit != null)
                        {
                            file.HostEditUrl = WopiUtil.GetActionUrl(edit, file, context.Request.Url.Authority);
                        }

                        // Get the user from the token (token is already validated)
                        file.UserId = WopiSecurity.GetUserFromToken(request.AccessToken);

                        // Call the appropriate handler for the WOPI request we received
                        switch (request.RequestType)
                        {
                        case WopiRequestType.CheckFileInfo:
                            response = context.CheckFileInfo(file);
                            break;

                        case WopiRequestType.GetFile:
                            response = await context.GetFile(file);

                            break;

                        case WopiRequestType.Lock:
                            response = await context.Lock(file);

                            break;

                        case WopiRequestType.GetLock:
                            response = await context.GetLock(file);

                            break;

                        case WopiRequestType.RefreshLock:
                            response = await context.RefreshLock(file);

                            break;

                        case WopiRequestType.Unlock:
                            response = await context.Unlock(file);

                            break;

                        case WopiRequestType.UnlockAndRelock:
                            response = await context.UnlockAndRelock(file);

                            break;

                        case WopiRequestType.PutFile:
                            response = await context.PutFile(file);

                            break;

                        case WopiRequestType.PutRelativeFile:
                            response = await context.PutRelativeFile(file, actions);

                            break;

                        case WopiRequestType.RenameFile:
                            response = await context.RenameFile(file);

                            break;

                        case WopiRequestType.PutUserInfo:
                            response = await context.PutUserInfo(file);

                            break;

                        default:
                            response = returnStatus(HttpStatusCode.NotImplemented, "Unsupported");
                            break;
                        }
                    }
                    else
                    {
                        // Proof validation failed...return 500
                        response = returnStatus(HttpStatusCode.InternalServerError, "Server Error");
                    }
                }
            }
            catch (Exception)
            {
                // An unknown exception occurred...return 500
                response = returnStatus(HttpStatusCode.InternalServerError, "Server Error");
            }

            return(response);
        }
        /// <summary>
        /// Processes a PutRelativeFile request
        /// </summary>
        /// <remarks>
        /// For full documentation on PutRelativeFile, see https://wopi.readthedocs.org/projects/wopirest/en/latest/files/PutRelativeFile.html
        /// </remarks>
        private async static Task <HttpResponseMessage> PutRelativeFile(this HttpContext context, DetailedFileModel file, List <WopiAction> actions)
        {
            // Determine the specific mode
            if (context.Request.Headers[WopiRequestHeaders.RELATIVE_TARGET] != null &&
                context.Request.Headers[WopiRequestHeaders.SUGGESTED_TARGET] != null)
            {
                // Theses headers are mutually exclusive, so we should return a 501 Not Implemented
                return(returnStatus(HttpStatusCode.NotImplemented, "Both RELATIVE_TARGET and SUGGESTED_TARGET were present"));
            }
            else if (context.Request.Headers[WopiRequestHeaders.RELATIVE_TARGET] != null ||
                     context.Request.Headers[WopiRequestHeaders.SUGGESTED_TARGET] != null)
            {
                string fileName = "";
                if (context.Request.Headers[WopiRequestHeaders.RELATIVE_TARGET] != null)
                {
                    // Specific mode...use the exact filename
                    fileName = context.Request.Headers[WopiRequestHeaders.RELATIVE_TARGET];
                }
                else
                {
                    // Suggested mode...might just be an extension
                    fileName = context.Request.Headers[WopiRequestHeaders.RELATIVE_TARGET];
                    if (fileName.IndexOf('.') == 0)
                    {
                        fileName = file.BaseFileName.Substring(0, file.BaseFileName.LastIndexOf('.')) + fileName;
                    }
                }

                // Create the file entity
                DetailedFileModel newFile = new DetailedFileModel()
                {
                    id           = Guid.NewGuid(),
                    OwnerId      = file.OwnerId,
                    BaseFileName = fileName,
                    Size         = context.Request.InputStream.Length,
                    Container    = file.Container,
                    Version      = 1
                };

                // First stream the file into blob storage
                var stream = context.Request.InputStream;
                var bytes  = new byte[stream.Length];
                await stream.ReadAsync(bytes, 0, (int)stream.Length);

                var id = await Utils.AzureStorageUtil.UploadFile(newFile.id.ToString(), newFile.Container, bytes);

                // Write the details into documentDB
                await DocumentRepository <FileModel> .CreateItemAsync("Files", (FileModel)newFile);

                // Get access token for the new file
                WopiSecurity security = new WopiSecurity();
                var          token    = security.GenerateToken(newFile.OwnerId, newFile.Container, newFile.id.ToString());
                var          tokenStr = security.WriteToken(token);

                // Prepare the Json response
                string json = String.Format("{ 'Name': '{0}, 'Url': 'https://{1}/wopi/files/{2}?access_token={3}'",
                                            newFile.BaseFileName, context.Request.Url.Authority, newFile.id.ToString(), tokenStr);

                // Add the optional properties to response if applicable (HostViewUrl, HostEditUrl)
                var fileExt = newFile.BaseFileName.Substring(newFile.BaseFileName.LastIndexOf('.') + 1).ToLower();
                var view    = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "view");
                if (view != null)
                {
                    json += String.Format(", 'HostViewUrl': '{0}'", WopiUtil.GetActionUrl(view, newFile, context.Request.Url.Authority));
                }
                var edit = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "edit");
                if (edit != null)
                {
                    json += String.Format(", 'HostEditUrl': '{0}'", WopiUtil.GetActionUrl(edit, newFile, context.Request.Url.Authority));
                }
                json += " }";

                // Write the response and return a success 200
                var response = returnStatus(HttpStatusCode.OK, "Success");
                response.Content = new StringContent(json);
                return(response);
            }
            else
            {
                return(returnStatus(HttpStatusCode.BadRequest, "PutRelativeFile mode was not provided in the request"));
            }
        }
Exemplo n.º 21
0
        public override async Task <WopiResponse> CheckFileInfo(CheckFileInfoRequest checkFileInfoRequest)
        {
            var userId = WopiSecurity.GetIdentityNameFromToken(checkFileInfoRequest.AccessToken);

            // For this demo server, determine tenant by host part of email address
            var tenant = new MailAddress(userId).Host.Replace(".", "-");

            // Lookup the file in the database using special repository method which grants access limited access to users in same tenant (same email domain)
            var wopiFileRepository = new WopiFileRepository();
            var response           = await wopiFileRepository.GetFileInfoByTenantUser(checkFileInfoRequest.ResourceId, userId, tenant);

            // Check for null file
            if (response.Item1 == HttpStatusCode.NotFound)
            {
                return(checkFileInfoRequest.ResponseNotFound());
            }

            else if (response.Item1 == HttpStatusCode.OK)
            {
                var wopiFile = response.Item2;
                // Get discovery information
                var actions = await WopiDiscovery.GetActions();

                string hostViewUrl = null, hostEditUrl = null;

                var closeUrl = String.Format("https://{0}", checkFileInfoRequest.RequestUri.Authority);

                var view = actions.FirstOrDefault(i => i.ext == wopiFile.FileExtension && i.name == "view");
                if (view != null)
                {
                    hostViewUrl = WopiDiscovery.GetActionUrl(view, wopiFile.FileId.ToString(), checkFileInfoRequest.RequestUri.Authority);
                }

                var edit = actions.FirstOrDefault(i => i.ext == wopiFile.FileExtension && i.name == "edit");
                if (edit != null)
                {
                    hostEditUrl = WopiDiscovery.GetActionUrl(edit, wopiFile.FileId.ToString(), checkFileInfoRequest.RequestUri.Authority);
                }

                // Write the response and return a success 200
                var wopiResponse = checkFileInfoRequest.ResponseOK(wopiFile.FileName, wopiFile.OwnerId, wopiFile.Size, userId, wopiFile.Version.ToString());
                // Add optional items
                wopiResponse.CloseUrl = new Uri(closeUrl);
                if (hostViewUrl != null)
                {
                    wopiResponse.HostViewUrl = new Uri(hostViewUrl);
                }
                if (hostEditUrl != null)
                {
                    wopiResponse.HostEditUrl = new Uri(hostEditUrl);
                }

                wopiResponse.UserInfo = wopiFile.FilePermissions.First().UserInfo;

                return(wopiResponse);
            }
            else
            {
                return(checkFileInfoRequest.ResponseServerError(string.Format("Unknown response from WopiFileRepository.GetFileInfoByTenantUser: {0}", response.Item1)));
            }
        }