diff options
author | Ashod Nakashian <ashod.nakashian@collabora.co.uk> | 2020-01-18 16:04:26 -0500 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2020-01-28 18:10:14 +0100 |
commit | da0f3a950a03c7ac9544176ca9d2e48e9a0126b8 (patch) | |
tree | a960af2e70dd54ac1d58e0157c96f980451dfc7a | |
parent | cypress: mobile: More font changes related tests. (diff) | |
download | online-da0f3a950a03c7ac9544176ca9d2e48e9a0126b8.tar.gz online-da0f3a950a03c7ac9544176ca9d2e48e9a0126b8.zip |
wsd: per-user cookies
Cookies may be passed from the client to the storage,
in which case each user may have its own unique set
of cookies. These cookies are now preserved in the
ClientSession, which is per connection, and are then
passed to the storage to use when communicating with
the WOPI-like backend.
(cherry picked from commit 6022faf3cc9b622b490c3f8ca91efbff8e542414)
Change-Id: Ic2e13fa541a5ee01b7383939bbbf7d46ea75684b
-rw-r--r-- | wsd/ClientSession.cpp | 14 | ||||
-rw-r--r-- | wsd/ClientSession.hpp | 5 | ||||
-rw-r--r-- | wsd/DocumentBroker.cpp | 17 | ||||
-rw-r--r-- | wsd/Storage.cpp | 53 | ||||
-rw-r--r-- | wsd/Storage.hpp | 59 |
5 files changed, 108 insertions, 40 deletions
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp index beed136e51..60ed55c6fd 100644 --- a/wsd/ClientSession.cpp +++ b/wsd/ClientSession.cpp @@ -60,7 +60,19 @@ ClientSession::ClientSession(const std::string& id, _isTextDocument(false) { const size_t curConnections = ++LOOLWSD::NumConnections; - LOG_INF("ClientSession ctor [" << getName() << "], current number of connections: " << curConnections); + LOG_INF("ClientSession ctor [" << getName() << "] for URI: [" << _uriPublic.toString() + << "], current number of connections: " << curConnections); + + for (const auto& param : _uriPublic.getQueryParameters()) + { + if (param.first == "reuse_cookies") + { + // Cache the cookies to avoid re-parsing the URI again. + _cookies = param.second; + LOG_INF("ClientSession [" << getName() << "] has cookies: " << _cookies); + break; + } + } // populate with random values. for (auto it : _clipboardKeys) diff --git a/wsd/ClientSession.hpp b/wsd/ClientSession.hpp index 8ee1846874..d714179ceb 100644 --- a/wsd/ClientSession.hpp +++ b/wsd/ClientSession.hpp @@ -123,6 +123,8 @@ public: /// The access token of this session. Authorization getAuthorization() const; + const std::string& getCookies() const { return _cookies; } + /// Set WOPI fileinfo object void setWopiFileInfo(std::unique_ptr<WopiStorage::WOPIFileInfo>& wopiFileInfo) { _wopiFileInfo = std::move(wopiFileInfo); } @@ -220,6 +222,9 @@ private: /// URI with which client made request to us const Poco::URI _uriPublic; + /// The cookies we should pass on to the storage on saving. + std::string _cookies; + /// Whether this session is the owner of currently opened document bool _isDocumentOwner; diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp index 876436abed..1eed16ea04 100644 --- a/wsd/DocumentBroker.cpp +++ b/wsd/DocumentBroker.cpp @@ -596,8 +596,8 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s WopiStorage* wopiStorage = dynamic_cast<WopiStorage*>(_storage.get()); if (wopiStorage != nullptr) { - std::unique_ptr<WopiStorage::WOPIFileInfo> wopifileinfo = - wopiStorage->getWOPIFileInfo(session->getAuthorization(), *_lockCtx); + std::unique_ptr<WopiStorage::WOPIFileInfo> wopifileinfo = wopiStorage->getWOPIFileInfo( + session->getAuthorization(), session->getCookies(), *_lockCtx); userId = wopifileinfo->getUserId(); username = wopifileinfo->getUsername(); userExtraInfo = wopifileinfo->getUserExtraInfo(); @@ -754,9 +754,9 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s if (!_storage->isLoaded()) { std::string localPath = _storage->loadStorageFileToLocal( - session->getAuthorization(), *_lockCtx, templateSource); + session->getAuthorization(), session->getCookies(), *_lockCtx, templateSource); - if (!_storage->updateLockState(session->getAuthorization(), *_lockCtx, true)) + if (!_storage->updateLockState(session->getAuthorization(), session->getCookies(), *_lockCtx, true)) LOG_ERR("Failed to lock!"); #if !MOBILEAPP @@ -990,8 +990,8 @@ bool DocumentBroker::saveToStorageInternal(const std::string& sessionId, bool su LOG_DBG("Persisting [" << _docKey << "] after saving to URI [" << uriAnonym << "]."); assert(_storage && _tileCache); - StorageBase::SaveResult storageSaveResult = _storage->saveLocalFileToStorage( - auth, *_lockCtx, saveAsPath, saveAsFilename, isRename); + const StorageBase::SaveResult storageSaveResult = _storage->saveLocalFileToStorage( + auth, it->second->getCookies(), *_lockCtx, saveAsPath, saveAsFilename, isRename); if (storageSaveResult.getResult() == StorageBase::SaveResult::OK) { #if !MOBILEAPP @@ -1146,7 +1146,7 @@ void DocumentBroker::refreshLock() else { std::shared_ptr<ClientSession> session = it->second; - if (!session || !_storage->updateLockState(session->getAuthorization(), *_lockCtx, true)) + if (!session || !_storage->updateLockState(session->getAuthorization(), session->getCookies(), *_lockCtx, true)) LOG_ERR("Failed to refresh lock"); } } @@ -1418,7 +1418,7 @@ void DocumentBroker::disconnectSessionInternal(const std::string& id) if (_markToDestroy && // last session to remove; FIXME: Editable? _lockCtx->_isLocked && _storage) { - if (!_storage->updateLockState(it->second->getAuthorization(), *_lockCtx, false)) + if (!_storage->updateLockState(it->second->getAuthorization(), it->second->getCookies(), *_lockCtx, false)) LOG_ERR("Failed to unlock!"); } @@ -1782,7 +1782,6 @@ void DocumentBroker::sendRequestedTiles(const std::shared_ptr<ClientSession>& se float tilesOnFlyUpperLimit = 0; if (normalizedVisArea.hasSurface() && session->getTileWidthInTwips() != 0 && session->getTileHeightInTwips() != 0) { - const int tilesFitOnWidth = std::ceil(normalizedVisArea.getRight() / session->getTileWidthInTwips()) - std::ceil(normalizedVisArea.getLeft() / session->getTileWidthInTwips()) + 1; const int tilesFitOnHeight = std::ceil(normalizedVisArea.getBottom() / session->getTileHeightInTwips()) - diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp index ab2ad71c61..f465e0a011 100644 --- a/wsd/Storage.cpp +++ b/wsd/Storage.cpp @@ -300,7 +300,10 @@ std::unique_ptr<LocalStorage::LocalFileInfo> LocalStorage::getLocalFileInfo() return std::unique_ptr<LocalStorage::LocalFileInfo>(new LocalFileInfo({"localhost" + std::to_string(LastLocalStorageId), "LocalHost#" + std::to_string(LastLocalStorageId++)})); } -std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/, LockContext & /*lockCtx*/, const std::string& /*templateUri*/) +std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/, + const std::string& /*cookies*/, + LockContext& /*lockCtx*/, + const std::string& /*templateUri*/) { #if !MOBILEAPP // /chroot/jailId/user/doc/childId/file.ext @@ -363,7 +366,10 @@ std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/, } -StorageBase::SaveResult LocalStorage::saveLocalFileToStorage(const Authorization& /*auth*/, LockContext &/*lockCtx*/, const std::string& /*saveAsPath*/, const std::string& /*saveAsFilename*/, bool /*isRename*/) +StorageBase::SaveResult +LocalStorage::saveLocalFileToStorage(const Authorization& /*auth*/, const std::string& /*cookies*/, + LockContext& /*lockCtx*/, const std::string& /*saveAsPath*/, + const std::string& /*saveAsFilename*/, bool /*isRename*/) { try { @@ -428,6 +434,8 @@ static void addStorageReuseCookie(Poco::Net::HTTPRequest& request, const std::st if (!reuseStorageCookies.empty()) { Poco::Net::NameValueCollection nvcCookies; + request.getCookies(nvcCookies); // Preserve existing cookies. + std::vector<std::string> cookies = LOOLProtocol::tokenize(reuseStorageCookies, ':'); for (auto cookie : cookies) { @@ -435,9 +443,10 @@ static void addStorageReuseCookie(Poco::Net::HTTPRequest& request, const std::st if (cookieTokens.size() == 2) { nvcCookies.add(cookieTokens[0], cookieTokens[1]); - LOG_DBG("Added storage reuse cookie [" << cookieTokens[0] << "=" << cookieTokens[1] << "]."); + LOG_DBG("Added storage reuse cookie [" << cookieTokens[0] << '=' << cookieTokens[1] << "]."); } } + request.setCookies(nvcCookies); } } @@ -494,7 +503,9 @@ void LockContext::dumpState(std::ostream& os) const #if !MOBILEAPP -std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Authorization& auth, LockContext &lockCtx) +std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Authorization& auth, + const std::string& cookies, + LockContext& lockCtx) { // update the access_token to the one matching to the session Poco::URI uriObject(getUri()); @@ -513,7 +524,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au auth.authorizeRequest(request); addStorageDebugCookie(request); if (_reuseCookies) - addStorageReuseCookie(request, params["reuse_cookies"]); + addStorageReuseCookie(request, cookies); addWopiProof(request, params["access_token"]); const auto startTime = std::chrono::steady_clock::now(); @@ -712,7 +723,8 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au userCanRename, callDuration})); } -bool WopiStorage::updateLockState(const Authorization &auth, LockContext &lockCtx, bool lock) +bool WopiStorage::updateLockState(const Authorization& auth, const std::string& cookies, + LockContext& lockCtx, bool lock) { if (!lockCtx._supportsLocks) return true; @@ -743,7 +755,7 @@ bool WopiStorage::updateLockState(const Authorization &auth, LockContext &lockCt request.set("X-LOOL-WOPI-ExtendedData", getExtendedData()); addStorageDebugCookie(request); if (_reuseCookies) - addStorageReuseCookie(request, params["reuse_cookies"]); + addStorageReuseCookie(request, cookies); addWopiProof(request, params["access_token"]); psession->sendRequest(request); @@ -782,7 +794,10 @@ bool WopiStorage::updateLockState(const Authorization &auth, LockContext &lockCt } /// uri format: http://server/<...>/wopi*/files/<id>/content -std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, LockContext &/* lockCtx */, const std::string& templateUri) +std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, + const std::string& cookies, + LockContext& /*lockCtx*/, + const std::string& templateUri) { // WOPI URI to download files ends in '/contents'. // Add it here to get the payload instead of file info. @@ -819,7 +834,7 @@ std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, LockC auth.authorizeRequest(request); addStorageDebugCookie(request); if (_reuseCookies) - addStorageReuseCookie(request, params["reuse_cookies"]); + addStorageReuseCookie(request, cookies); addWopiProof(request, params["access_token"]); psession->sendRequest(request); @@ -876,7 +891,10 @@ std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, LockC return ""; } -StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) +StorageBase::SaveResult +WopiStorage::saveLocalFileToStorage(const Authorization& auth, const std::string& cookies, + LockContext& lockCtx, const std::string& saveAsPath, + const std::string& saveAsFilename, const bool isRename) { // TODO: Check if this URI has write permission (canWrite = true) @@ -975,7 +993,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization& request.setContentLength(size); addStorageDebugCookie(request); if (_reuseCookies) - addStorageReuseCookie(request, params["reuse_cookies"]); + addStorageReuseCookie(request, cookies); addWopiProof(request, params["access_token"]); std::ostream& os = psession->sendRequest(request); @@ -1106,17 +1124,20 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization& return saveResult; } -std::string WebDAVStorage::loadStorageFileToLocal( - const Authorization& /*auth*/, LockContext &/*lockCtx*/, const std::string& /*templateUri*/) +std::string WebDAVStorage::loadStorageFileToLocal(const Authorization& /*auth*/, + const std::string& /*cookies*/, + LockContext& /*lockCtx*/, + const std::string& /*templateUri*/) { // TODO: implement webdav GET. setLoaded(true); return getUri().toString(); } -StorageBase::SaveResult WebDAVStorage::saveLocalFileToStorage( - const Authorization& /*auth*/, LockContext &/*lockCtx*/, const std::string& /*saveAsPath*/, - const std::string& /*saveAsFilename*/, bool /*isRename*/) +StorageBase::SaveResult +WebDAVStorage::saveLocalFileToStorage(const Authorization& /*auth*/, const std::string& /*cookies*/, + LockContext& /*lockCtx*/, const std::string& /*saveAsPath*/, + const std::string& /*saveAsFilename*/, bool /*isRename*/) { // TODO: implement webdav PUT. return StorageBase::SaveResult(StorageBase::SaveResult::OK); diff --git a/wsd/Storage.hpp b/wsd/Storage.hpp index 7060cd7a4e..bb678ac8aa 100644 --- a/wsd/Storage.hpp +++ b/wsd/Storage.hpp @@ -53,7 +53,6 @@ struct LockContext class StorageBase { public: - /// Represents basic file's attributes. /// Used for local and network files. class FileInfo @@ -217,15 +216,25 @@ public: std::string getFileExtension() const { return Poco::Path(_fileInfo.getFilename()).getExtension(); } /// Update the locking state (check-in/out) of the associated file - virtual bool updateLockState(const Authorization &auth, LockContext &lockCtx, bool lock) = 0; + virtual bool updateLockState(const Authorization& auth, const std::string& cookies, + LockContext& lockCtx, bool lock) + = 0; /// Returns a local file path for the given URI. /// If necessary copies the file locally first. - virtual std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) = 0; + virtual std::string loadStorageFileToLocal(const Authorization& auth, + const std::string& /*cookies*/, LockContext& lockCtx, + const std::string& templateUri) + = 0; /// Writes the contents of the file back to the source. + /// @param cookies A string representing key=value pairs that are set as cookies. /// @param savedFile When the operation was saveAs, this is the path to the file that was saved. - virtual SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) = 0; + virtual SaveResult + saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, const std::string& saveAsPath, + const std::string& saveAsFilename, const bool isRename) + = 0; static size_t getFileSize(const std::string& filename); @@ -312,11 +321,19 @@ public: /// obtained using getFileInfo method std::unique_ptr<LocalFileInfo> getLocalFileInfo(); - bool updateLockState(const Authorization &, LockContext &, bool) override { return true; } + bool updateLockState(const Authorization&, const std::string&, LockContext&, bool) override + { + return true; + } - std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) override; + std::string loadStorageFileToLocal(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, + const std::string& templateUri) override; - SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override; + SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, const std::string& saveAsPath, + const std::string& saveAsFilename, + const bool isRename) override; private: /// True if the jailed file is not linked but copied. @@ -545,15 +562,21 @@ public: /// which can then be obtained using getFileInfo() /// Also sets up the locking context for future operations. std::unique_ptr<WOPIFileInfo> getWOPIFileInfo(const Authorization& auth, - LockContext &lockCtx); + const std::string& cookies, LockContext& lockCtx); /// Update the locking state (check-in/out) of the associated file - bool updateLockState(const Authorization &auth, LockContext &lockCtx, bool lock) override; + bool updateLockState(const Authorization& auth, const std::string& cookies, + LockContext& lockCtx, bool lock) override; /// uri format: http://server/<...>/wopi*/files/<id>/content - std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) override; + std::string loadStorageFileToLocal(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, + const std::string& templateUri) override; - SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override; + SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, const std::string& saveAsPath, + const std::string& saveAsFilename, + const bool isRename) override; /// Total time taken for making WOPI calls during load std::chrono::duration<double> getWopiLoadDuration() const { return _wopiLoadDuration; } @@ -585,11 +608,19 @@ public: // Implement me // WebDAVFileInfo getWebDAVFileInfo(const Poco::URI& uriPublic); - bool updateLockState(const Authorization &, LockContext &, bool) override { return true; } + bool updateLockState(const Authorization&, const std::string&, LockContext&, bool) override + { + return true; + } - std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) override; + std::string loadStorageFileToLocal(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, + const std::string& templateUri) override; - SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override; + SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, const std::string& saveAsPath, + const std::string& saveAsFilename, + const bool isRename) override; private: std::unique_ptr<AuthBase> _authAgent; |