Represents the base information determined at the beginning of a WOPI request
        /// <summary>
        /// Determines if the user is authorized to access the WebAPI endpoint based on the bearer token
        /// </summary>
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            try
            {
                // Parse the query string and ensure there is an access_token
                var queryParams = parseRequestParams(actionContext.Request.RequestUri.Query);
                if (!queryParams.ContainsKey("access_token"))
                    return false;

                // Get the details of the WOPI request
                WopiRequest requestData = new WopiRequest()
                {
                    RequestType = WopiRequestType.None,
                    AccessToken = queryParams["access_token"],
                    Id = actionContext.RequestContext.RouteData.Values["id"].ToString()
                };
                
                // Get the requested file from Document DB
                var itemId = new Guid(requestData.Id);
                var file = DocumentDBRepository<DetailedFileModel>.GetItem("Files", i => i.id == itemId);

                // Check for missing file
                if (file == null)
                    return false;

                // Validate the access token
                return WopiSecurity.ValidateToken(requestData.AccessToken, file.Container, file.id.ToString());
            }
            catch (Exception)
            {
                // Any exception will return false, but should probably return an alternate status codes
                return false;
            }
        }
예제 #2
0
        /// <summary>
        /// Called at the beginning of a WOPI request to parse the request and determine the request type
        /// </summary>
        public static WopiRequest ParseRequest(HttpRequest request)
        {
            // Initilize wopi request data object with default values
            WopiRequest requestData = new WopiRequest()
            {
                RequestType = WopiRequestType.None,
                AccessToken = request.QueryString["access_token"],
                Id = ""
            };

            // Get request path, e.g. /<...>/wopi/files/<id>
            string requestPath = request.Url.AbsolutePath.ToLower();

            // Remove /<...>/wopi/
            string wopiPath = requestPath.Substring(requestPath.IndexOf(WopiUtil.WOPI_BASE_PATH) + WopiUtil.WOPI_BASE_PATH.Length);

            // Check the type of request being made
            if (wopiPath.StartsWith(WopiUtil.WOPI_FILES_PATH))
            {
                // This is a file-related request

                // Remove /files/ from the beginning of wopiPath
                string rawId = wopiPath.Substring(WopiUtil.WOPI_FILES_PATH.Length);

                if (rawId.EndsWith(WopiUtil.WOPI_CONTENTS_PATH))
                {
                    // The rawId ends with /contents so this is a request to read/write the file contents

                    // Remove /contents from the end of rawId to get the actual file id
                    requestData.Id = rawId.Substring(0, rawId.Length - WopiUtil.WOPI_CONTENTS_PATH.Length);

                    // Check request verb to determine file operation
                    if (request.HttpMethod == "GET")
                        requestData.RequestType = WopiRequestType.GetFile;
                    if (request.HttpMethod == "POST")
                        requestData.RequestType = WopiRequestType.PutFile;
                }
                else
                {
                    requestData.Id = rawId;

                    if (request.HttpMethod == "GET")
                    {
                        // GET requests to the file are always CheckFileInfo
                        requestData.RequestType = WopiRequestType.CheckFileInfo;
                    }
                    else if (request.HttpMethod == "POST")
                    {
                        // Use the X-WOPI-Override header to determine the request type for POSTs
                        string wopiOverride = request.Headers[WopiRequestHeaders.OVERRIDE];
                        switch (wopiOverride)
                        {
                            case "LOCK":
                                // Check lock type based on presence of OldLock header
                                if (request.Headers[WopiRequestHeaders.OLD_LOCK] != null)
                                    requestData.RequestType = WopiRequestType.UnlockAndRelock;
                                else
                                    requestData.RequestType = WopiRequestType.Lock;
                                break;
                            case "GET_LOCK":
                                requestData.RequestType = WopiRequestType.GetLock;
                                break;
                            case "REFRESH_LOCK":
                                requestData.RequestType = WopiRequestType.RefreshLock;
                                break;
                            case "UNLOCK":
                                requestData.RequestType = WopiRequestType.Unlock;
                                break;
                            case "PUT_RELATIVE":
                                requestData.RequestType = WopiRequestType.PutRelativeFile;
                                break;
                            case "RENAME_FILE":
                                requestData.RequestType = WopiRequestType.RenameFile;
                                break;
                            case "PUT_USER_INFO":
                                requestData.RequestType = WopiRequestType.PutUserInfo;
                                break;

                            /*
                            // The following WOPI_Override values were referenced in the product group sample, but not in the documentation
                            case "COBALT":
                                requestData.RequestType = WopiRequestType.ExecuteCobaltRequest;
                                break;
                            case "DELETE":
                                requestData.RequestType = WopiRequestType.DeleteFile;
                                break;
                            case "READ_SECURE_STORE":
                                requestData.RequestType = WopiRequestType.ReadSecureStore;
                                break;
                            case "GET_RESTRICTED_LINK":
                                requestData.RequestType = WopiRequestType.GetRestrictedLink;
                                break;
                            case "REVOKE_RESTRICTED_LINK":
                                requestData.RequestType = WopiRequestType.RevokeRestrictedLink;
                                break;
                            */
                        }
                    }
                }
            }
            else if (wopiPath.StartsWith(WopiUtil.WOPI_FOLDERS_PATH))
            {
                // This is a folder-related request

                // Remove /folders/ from the beginning of wopiPath
                string rawId = wopiPath.Substring(WopiUtil.WOPI_FOLDERS_PATH.Length);

                if (rawId.EndsWith(WopiUtil.WOPI_CHILDREN_PATH))
                {
                    // rawId ends with /children, so it's an EnumerateChildren request.

                    // Remove /children from the end of rawId
                    requestData.Id = rawId.Substring(0, WopiUtil.WOPI_CHILDREN_PATH.Length);
                    //requestData.RequestType = WopiRequestType.EnumerateChildren;
                }
                else
                {
                    // rawId doesn't end with /children, so it's a CheckFolderInfo.

                    requestData.Id = rawId;
                    //requestData.RequestType = WopiRequestType.CheckFolderInfo;
                }
            }
            else
            {
                // This is an unknown request
                requestData.RequestType = WopiRequestType.None;
            }

            return requestData;
        }