Browse Source

Make gRPC credentials dynamic

- Refactor gRPC credentials interface
- Credentials interface now provides dynamic credentials generation
TODO: Still dirty interface
Alexey Edelev 5 năm trước cách đây
mục cha
commit
73543e6a70

+ 5 - 0
src/grpc/abstractcredentials.cpp

@@ -24,3 +24,8 @@
  */
 
 #include "abstractcredentials.h"
+
+using namespace QtProtobuf;
+
+CallCredentials::~CallCredentials() = default;
+ChannelCredentials::~ChannelCredentials() = default;

+ 68 - 55
src/grpc/abstractcredentials.h

@@ -30,6 +30,7 @@
 #include <QVariant>
 
 #include <functional>
+#include <memory>
 
 #include "qtgrpcglobal.h"
 
@@ -42,77 +43,89 @@ namespace QtProtobuf {
 class CallCredentials;
 class ChannelCredentials;
 
+using CredentialMap = QHash<QLatin1String, QVariant>;
+
+//! \private
+class QGrpcAbstractCredentials {
+public:
+    virtual CredentialMap callCredentials() = 0;
+    virtual CredentialMap channelCredentials() = 0;
+};
+
 /*!
- * \brief The AbstractCredentials class
+ * \brief The CallCredentials class
  */
-class Q_GRPC_EXPORT AbstractCredentials
+class Q_GRPC_EXPORT CallCredentials
 {
 public:
-    template<typename Call, typename Channel,
-             typename std::enable_if_t<std::is_base_of<QtProtobuf::CallCredentials, Call>::value
-                                       && std::is_base_of<QtProtobuf::ChannelCredentials, Channel>::value, int> = 0>
-    AbstractCredentials(const Call &call, const Channel &channel) {
-        mCallCredentials = call.mCallCredentials;
-        mChannelCredentials = channel.mChannelCredentials;
-    }
+    CallCredentials() = default;
+    virtual ~CallCredentials();
+};
 
-    template<typename Call,
-             typename std::enable_if_t<std::is_base_of<QtProtobuf::CallCredentials, Call>::value, int> = 0>
-    AbstractCredentials(const Call &call) {
-        mCallCredentials = call.mCallCredentials;
-    }
+/*!
+ * \brief The ChannelCredentials class
+ */
+class Q_GRPC_EXPORT ChannelCredentials
+{
+public:
+    ChannelCredentials() = default;
+    virtual ~ChannelCredentials();
+};
 
-    template<typename Channel,
-             typename std::enable_if_t<std::is_base_of<QtProtobuf::ChannelCredentials, Channel>::value, int> = 0>
-    AbstractCredentials(const Channel &channel) {
-        mChannelCredentials = channel.mChannelCredentials;
-    }
 
-    using CredentialMap = QHash<QLatin1String, QVariant>;
+/*!
+ * \brief The QGrpcCredentials class
+ */
+template<typename Call, typename Channel,
+         typename std::enable_if_t<std::is_base_of<QtProtobuf::CallCredentials, Call>::value
+                                   && std::is_base_of<QtProtobuf::ChannelCredentials, Channel>::value, int> = 0>
+class Q_GRPC_EXPORT QGrpcCredentials : public QGrpcAbstractCredentials
+{
+public:
+    static QtProtobuf::QGrpcAbstractCredentials *withCredentials(const Call &call, const Channel &channel)
+    {
+        return new QGrpcCredentials<Call, Channel>(call, channel);
+    }
+    static QtProtobuf::QGrpcAbstractCredentials *withCallCredentials(const Call &call) {
+        return new QGrpcCredentials<Call, Channel>(call);
+    }
+    static QtProtobuf::QGrpcAbstractCredentials *withChannelCredentials(const Channel &channel) {
+        return new QGrpcCredentials<Call, Channel>(channel);
+    }
 
     CredentialMap callCredentials() {
-        return mCallCredentials;
+        return mCall();
     }
 
     CredentialMap channelCredentials() {
-        return mChannelCredentials;
+        return mChannel();
     }
-protected:
-    AbstractCredentials() = default;
-    void setCallCredentials(const CredentialMap &credentialMap) { mCallCredentials = credentialMap; }
-    void setChannelCredentials(const CredentialMap &credentialMap) { mChannelCredentials = credentialMap; }
 
-private:
-    CredentialMap mCallCredentials;
-    CredentialMap mChannelCredentials;
-};
+public:
+    QGrpcCredentials(const Call &call, const Channel &channel) :
+        mCall(call)
+      , mChannel(channel)
+    {
+    }
 
-/*!
- * \brief The CallCredentials class
- */
-class Q_GRPC_EXPORT CallCredentials : public AbstractCredentials
-{
-protected:
-    CallCredentials(const CredentialMap &credentialMap) {
-        setCallCredentials(credentialMap);
-        setChannelCredentials(CredentialMap{});
+    QGrpcCredentials(const Call &call) :
+        mCall(call)
+    {
     }
 
-private:
-    CallCredentials() = default;
-};
+    QGrpcCredentials(const Channel &channel) :
+        mChannel(channel)
+    {
+    }
 
-/*!
- * \brief The ChannelCredentials class
- */
-class Q_GRPC_EXPORT ChannelCredentials : public AbstractCredentials
-{
 protected:
-    ChannelCredentials(const CredentialMap &credentialMap) {
-        setCallCredentials(CredentialMap{});
-        setChannelCredentials(credentialMap);
-    }
+    QGrpcCredentials() = default;
+
+private:
+    Call mCall;
+    Channel mChannel;
 };
+
 /*! \} */
 }
 
@@ -120,16 +133,16 @@ protected:
 template<typename Call, typename Channel,
          typename std::enable_if_t<std::is_base_of<QtProtobuf::CallCredentials, Call>::value
                                    && std::is_base_of<QtProtobuf::ChannelCredentials, Channel>::value, int> = 0>
-QtProtobuf::AbstractCredentials operator |(const Call &call, const Channel &channel)
+std::unique_ptr<QtProtobuf::QGrpcAbstractCredentials> operator |(const Call &call, const Channel &channel)
 {
-    return QtProtobuf::AbstractCredentials(call, channel);
+    return std::unique_ptr<QtProtobuf::QGrpcAbstractCredentials>(QtProtobuf::QGrpcCredentials<Call, Channel>::withCredentials(call, channel));
 }
 
 //! \private
 template<typename Call, typename Channel,
          typename std::enable_if_t<std::is_base_of<QtProtobuf::CallCredentials, Call>::value
                                    && std::is_base_of<QtProtobuf::ChannelCredentials, Channel>::value, int> = 0>
-QtProtobuf::AbstractCredentials operator |(const Channel &channel, const Call &call)
+std::unique_ptr<QtProtobuf::QGrpcAbstractCredentials> operator |(const Channel &channel, const Call &call)
 {
-    return QtProtobuf::AbstractCredentials(call, channel);
+    return std::unique_ptr<QtProtobuf::QGrpcAbstractCredentials>(new QtProtobuf::QGrpcCredentials<Call, Channel>(call, channel));
 }

+ 4 - 1
src/grpc/insecurecredentials.h

@@ -37,6 +37,9 @@ namespace QtProtobuf {
 class Q_GRPC_EXPORT InsecureCredentials : public ChannelCredentials
 {
 public:
-    InsecureCredentials() : ChannelCredentials(CredentialMap()) {}
+    InsecureCredentials() = default;
+    CredentialMap operator()() {
+        return CredentialMap{};
+    }
 };
 }

+ 8 - 8
src/grpc/qgrpchttp2channel.cpp

@@ -104,7 +104,7 @@ struct QGrpcHttp2ChannelPrivate {
 
     QUrl url;
     QNetworkAccessManager nm;
-    AbstractCredentials credentials;
+    std::unique_ptr<QGrpcAbstractCredentials> credentials;
     QSslConfiguration sslConfig;
     std::unordered_map<QNetworkReply *, ExpectedData> activeStreamReplies;
 
@@ -119,7 +119,7 @@ struct QGrpcHttp2ChannelPrivate {
         request.setRawHeader(AcceptEncodingHeader, "identity,gzip");
         request.setRawHeader(TEHeader, "trailers");
         request.setSslConfiguration(sslConfig);
-        AbstractCredentials::CredentialMap callCredentials = credentials.callCredentials();
+        CredentialMap callCredentials = credentials->callCredentials();
         for (auto i = callCredentials.begin(); i != callCredentials.end(); ++i) {
             request.setRawHeader(i.key().data(), i.value().toString().toUtf8());
         }
@@ -172,15 +172,15 @@ struct QGrpcHttp2ChannelPrivate {
         return networkReply->readAll().mid(GrpcMessageSizeHeaderSize);
     }
 
-    QGrpcHttp2ChannelPrivate(const QUrl &_url, const AbstractCredentials &_credentials)
+    QGrpcHttp2ChannelPrivate(const QUrl &_url, std::unique_ptr<QGrpcAbstractCredentials> _credentials)
         : url(_url)
-        , credentials(_credentials)
+        , credentials(std::move(_credentials))
     {
         if (url.scheme() == "https") {
-            if (!credentials.channelCredentials().contains(QLatin1String("sslConfig"))) {
+            if (!credentials->channelCredentials().contains(QLatin1String("sslConfig"))) {
                 throw std::invalid_argument("Https connection requested but not ssl configuration provided.");
             }
-            sslConfig = credentials.channelCredentials().value(QLatin1String("sslConfig")).value<QSslConfiguration>();
+            sslConfig = credentials->channelCredentials().value(QLatin1String("sslConfig")).value<QSslConfiguration>();
         } else if (url.scheme().isEmpty()) {
             url.setScheme("http");
         }
@@ -195,8 +195,8 @@ struct QGrpcHttp2ChannelPrivate {
 
 }
 
-QGrpcHttp2Channel::QGrpcHttp2Channel(const QUrl &url, const AbstractCredentials &credentials) : QAbstractGrpcChannel()
-  , d_ptr(std::make_unique<QGrpcHttp2ChannelPrivate>(url, credentials))
+QGrpcHttp2Channel::QGrpcHttp2Channel(const QUrl &url, std::unique_ptr<QGrpcAbstractCredentials> credentials) : QAbstractGrpcChannel()
+  , d_ptr(std::make_unique<QGrpcHttp2ChannelPrivate>(url, std::move(credentials)))
 {
 }
 

+ 2 - 2
src/grpc/qgrpchttp2channel.h

@@ -32,7 +32,7 @@
 
 namespace QtProtobuf {
 
-class AbstractCredentials;
+class QGrpcAbstractCredentials;
 struct QGrpcHttp2ChannelPrivate;
 /*!
  * \ingroup QtGrpc
@@ -41,7 +41,7 @@ struct QGrpcHttp2ChannelPrivate;
 class Q_GRPC_EXPORT QGrpcHttp2Channel final : public QAbstractGrpcChannel
 {
 public:
-    QGrpcHttp2Channel(const QUrl &url, const AbstractCredentials &credentials);
+    QGrpcHttp2Channel(const QUrl &url, std::unique_ptr<QGrpcAbstractCredentials> credentials);
     ~QGrpcHttp2Channel();
 
     QGrpcStatus call(const QString &method, const QString &service, const QByteArray &args, QByteArray &ret) override;

+ 8 - 2
src/grpc/sslcredentials.h

@@ -40,7 +40,13 @@ class Q_GRPC_EXPORT SslCredentials : public ChannelCredentials
 {
 public:
     SslCredentials(const QSslConfiguration &configuation) :
-        ChannelCredentials(CredentialMap{{QLatin1String("sslConfig"),
-                           QVariant::fromValue<QSslConfiguration>(configuation)}}) {}
+        m_map(CredentialMap{{QLatin1String("sslConfig"),
+              QVariant::fromValue<QSslConfiguration>(configuation)}})
+    {}
+    CredentialMap operator()() {
+        return m_map;
+    }
+private:
+    CredentialMap m_map;
 };
 }