summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAshod Nakashian <ashod.nakashian@collabora.co.uk>2020-01-18 16:04:26 -0500
committerJan Holesovsky <kendy@collabora.com>2020-01-28 18:10:14 +0100
commitda0f3a950a03c7ac9544176ca9d2e48e9a0126b8 (patch)
treea960af2e70dd54ac1d58e0157c96f980451dfc7a
parentcypress: mobile: More font changes related tests. (diff)
downloadonline-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.cpp14
-rw-r--r--wsd/ClientSession.hpp5
-rw-r--r--wsd/DocumentBroker.cpp17
-rw-r--r--wsd/Storage.cpp53
-rw-r--r--wsd/Storage.hpp59
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;