Browse Source

Set HTTP method restriction on WebAPI actions

PR #17548.
adaptive-webui-19844
Chocobo1 2 years ago committed by GitHub
parent
commit
aa6b29fe7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      src/webui/webapplication.cpp
  2. 15
      src/webui/webapplication.h

16
src/webui/webapplication.cpp

@ -251,9 +251,11 @@ void WebApplication::doProcessRequest()
const QString action = match.captured(u"action"_qs); const QString action = match.captured(u"action"_qs);
const QString scope = match.captured(u"scope"_qs); const QString scope = match.captured(u"scope"_qs);
// Check public/private scope
if (!session() && !isPublicAPI(scope, action)) if (!session() && !isPublicAPI(scope, action))
throw ForbiddenHTTPError(); throw ForbiddenHTTPError();
// Find matching API
APIController *controller = nullptr; APIController *controller = nullptr;
if (session()) if (session())
controller = session()->getAPIController(scope); controller = session()->getAPIController(scope);
@ -265,6 +267,20 @@ void WebApplication::doProcessRequest()
throw NotFoundHTTPError(); throw NotFoundHTTPError();
} }
// Filter HTTP methods
const auto allowedMethodIter = m_allowedMethod.find({scope, action});
if (allowedMethodIter == m_allowedMethod.end())
{
// by default allow both GET, POST methods
if ((m_request.method != Http::METHOD_GET) && (m_request.method != Http::METHOD_POST))
throw MethodNotAllowedHTTPError();
}
else
{
if (*allowedMethodIter != m_request.method)
throw MethodNotAllowedHTTPError();
}
DataMap data; DataMap data;
for (const Http::UploadedFile &torrent : request().files) for (const Http::UploadedFile &torrent : request().files)
data[torrent.filename] = torrent.data; data[torrent.filename] = torrent.data;

15
src/webui/webapplication.h

@ -29,6 +29,7 @@
#pragma once #pragma once
#include <type_traits> #include <type_traits>
#include <utility>
#include <QDateTime> #include <QDateTime>
#include <QElapsedTimer> #include <QElapsedTimer>
@ -137,6 +138,20 @@ private:
const QRegularExpression m_apiPathPattern {u"^/api/v2/(?<scope>[A-Za-z_][A-Za-z_0-9]*)/(?<action>[A-Za-z_][A-Za-z_0-9]*)$"_qs}; const QRegularExpression m_apiPathPattern {u"^/api/v2/(?<scope>[A-Za-z_][A-Za-z_0-9]*)/(?<action>[A-Za-z_][A-Za-z_0-9]*)$"_qs};
QSet<QString> m_publicAPIs; QSet<QString> m_publicAPIs;
const QHash<std::pair<QString, QString>, QString> m_allowedMethod =
{
// <<controller name, action name>, HTTP method>
// TODO: this list is incomplete
{{u"app"_qs, u"setPreferences"_qs}, Http::METHOD_POST},
{{u"app"_qs, u"shutdown"_qs}, Http::METHOD_POST},
{{u"auth"_qs, u"login"_qs}, Http::METHOD_POST},
{{u"auth"_qs, u"logout"_qs}, Http::METHOD_POST},
{{u"rss"_qs, u"addFeed"_qs}, Http::METHOD_POST},
{{u"search"_qs, u"installPlugin"_qs}, Http::METHOD_POST},
{{u"torrents"_qs, u"add"_qs}, Http::METHOD_POST},
{{u"torrents"_qs, u"addPeers"_qs}, Http::METHOD_POST},
{{u"torrents"_qs, u"addTrackers"_qs}, Http::METHOD_POST}
};
bool m_isAltUIUsed = false; bool m_isAltUIUsed = false;
Path m_rootFolder; Path m_rootFolder;

Loading…
Cancel
Save