QGIS API Documentation 4.1.0-Master (376402f9aeb)
Loading...
Searching...
No Matches
qgsauthmethodregistry.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsauthmethodregistry.cpp
3 ---------------------
4 begin : September 1, 2015
5 copyright : (C) 2015 by Boundless Spatial, Inc. USA
6 author : Larry Shaffer
7 email : lshaffer at boundlessgeo dot com
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
18
19#include "qgis.h"
20#include "qgsauthconfig.h"
21#include "qgsauthmethod.h"
23#include "qgslogger.h"
24#include "qgsmessagelog.h"
25#include "qgsmessageoutput.h"
26
27#include <QString>
28
29using namespace Qt::StringLiterals;
30
31#ifdef HAVE_STATIC_PROVIDERS
32#include "qgsauthapiheadermethod.h"
33#include "qgsauthawss3method.h"
34#include "qgsauthbasicmethod.h"
35#include "qgsauthesritokenmethod.h"
36#include "qgsauthidentcertmethod.h"
37#include "qgsauthmaptilerhmacsha256method.h"
38#ifdef HAVE_OAUTH2_PLUGIN
39#include "qgsauthoauth2method.h"
40#endif
41#include "qgsauthpkipathsmethod.h"
42#include "qgsauthpkcs12method.h"
43#include "qgsauthplanetarycomputermethod.h"
44#endif
45
46#include <QString>
47#include <QDir>
48#include <QLibrary>
49#include <QRegularExpression>
50
51
52static QgsAuthMethodRegistry *sInstance = nullptr;
53
54
55QgsAuthMethodRegistry *QgsAuthMethodRegistry::instance( const QString &pluginPath )
56{
57 if ( !sInstance )
58 {
59 static QMutex sMutex;
60 const QMutexLocker locker( &sMutex );
61 if ( !sInstance )
62 {
63 sInstance = new QgsAuthMethodRegistry( pluginPath );
64 }
65 }
66 return sInstance;
67}
68
77static QgsAuthMethodMetadata *findMetadata_( QgsAuthMethodRegistry::AuthMethods const &metaData, QString const &authMethodKey )
78{
79 const QgsAuthMethodRegistry::AuthMethods::const_iterator i = metaData.find( authMethodKey );
80
81 if ( i != metaData.end() )
82 {
83 return i->second;
84 }
85
86 return nullptr;
87}
88
89QgsAuthMethodRegistry::QgsAuthMethodRegistry( const QString &pluginPath )
90{
91 // At startup, examine the libs in the qgis/lib dir and store those that
92 // are an auth method shared lib
93 // check all libs in the current plugin directory and get name and descriptions
94#if 0
95 char **argv = qApp->argv();
96 QString appDir = argv[0];
97 int bin = appDir.findRev( "/bin", -1, false );
98 QString baseDir = appDir.left( bin );
99 QString mLibraryDirectory = baseDir + "/lib";
100#endif
101 mLibraryDirectory.setPath( pluginPath );
102 mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
103 mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );
104
105 init();
106}
107
108void QgsAuthMethodRegistry::init()
109{
110#ifdef HAVE_STATIC_PROVIDERS
111 mAuthMethods[QgsAuthApiHeaderMethod::AUTH_METHOD_KEY] = new QgsAuthApiHeaderMethodMetadata();
112 mAuthMethods[QgsAuthAwsS3Method::AUTH_METHOD_KEY] = new QgsAuthAwsS3MethodMetadata();
113 mAuthMethods[QgsAuthBasicMethod::AUTH_METHOD_KEY] = new QgsAuthBasicMethodMetadata();
114 mAuthMethods[QgsAuthEsriTokenMethod::AUTH_METHOD_KEY] = new QgsAuthEsriTokenMethodMetadata();
115 mAuthMethods[QgsAuthIdentCertMethod::AUTH_METHOD_KEY] = new QgsAuthIdentCertMethodMetadata();
116 mAuthMethods[QgsAuthMapTilerHmacSha256Method::AUTH_METHOD_KEY] = new QgsAuthMapTilerHmacSha256MethodMetadata();
117#ifdef HAVE_OAUTH2_PLUGIN
118 mAuthMethods[QgsAuthOAuth2Method::AUTH_METHOD_KEY] = new QgsAuthOAuth2MethodMetadata();
119#endif
120 mAuthMethods[QgsAuthPkiPathsMethod::AUTH_METHOD_KEY] = new QgsAuthPkiPathsMethodMetadata();
121 mAuthMethods[QgsAuthPkcs12Method::AUTH_METHOD_KEY] = new QgsAuthPkcs12MethodMetadata();
122 mAuthMethods[QgsAuthPlanetaryComputerMethod::AUTH_METHOD_KEY] = new QgsAuthPlanetaryComputerMethodMetadata();
123#else
124 typedef QgsAuthMethodMetadata *factory_function();
125
126#if defined( Q_OS_WIN ) || defined( __CYGWIN__ )
127 mLibraryDirectory.setNameFilters( QStringList( "*authmethod_*.dll" ) );
128#else
129 mLibraryDirectory.setNameFilters( QStringList( u"*authmethod_*.so"_s ) );
130#endif
131 QgsDebugMsgLevel( u"Checking for auth method plugins in: %1"_s.arg( mLibraryDirectory.path() ), 2 );
132
133 if ( mLibraryDirectory.count() == 0 )
134 {
135 QString msg = QObject::tr( "No QGIS auth method plugins found in:\n%1\n" ).arg( mLibraryDirectory.path() );
136 msg += QObject::tr( "No authentication methods can be used. Check your QGIS installation" );
137
138 QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
139 output->setTitle( QObject::tr( "No Authentication Methods" ) );
141 output->showMessage();
142 return;
143 }
144
145 // auth method file regex pattern, only files matching the pattern are loaded if the variable is defined
146 const QString filePattern = getenv( "QGIS_AUTHMETHOD_FILE" );
147 QRegularExpression fileRegexp;
148 if ( !filePattern.isEmpty() )
149 {
150 fileRegexp.setPattern( filePattern );
151 }
152
153 QListIterator<QFileInfo> it( mLibraryDirectory.entryInfoList() );
154 while ( it.hasNext() )
155 {
156 const QFileInfo fi( it.next() );
157
158 if ( !filePattern.isEmpty() )
159 {
160 if ( fi.fileName().indexOf( fileRegexp ) == -1 )
161 {
162 QgsDebugError( "auth method " + fi.fileName() + " skipped because doesn't match pattern " + filePattern );
163 continue;
164 }
165 }
166
167 QLibrary myLib( fi.filePath() );
168 if ( !myLib.load() )
169 {
170 QgsDebugError( u"Checking %1: ...invalid (lib not loadable): %2"_s.arg( myLib.fileName(), myLib.errorString() ) );
171 continue;
172 }
173
174 bool libraryLoaded { false };
175 QFunctionPointer func = myLib.resolve( u"authMethodMetadataFactory"_s.toLatin1().data() );
176 factory_function *function = reinterpret_cast< factory_function * >( cast_to_fptr( func ) );
177 if ( function )
178 {
179 QgsAuthMethodMetadata *meta = function();
180 if ( meta )
181 {
182 if ( findMetadata_( mAuthMethods, meta->key() ) )
183 {
184 QgsDebugError( u"Checking %1: ...invalid (key %2 already registered)"_s.arg( myLib.fileName() ).arg( meta->key() ) );
185 delete meta;
186 continue;
187 }
188 // add this method to the map
189 mAuthMethods[meta->key()] = meta;
190 libraryLoaded = true;
191 }
192 }
193 if ( !libraryLoaded )
194 {
195 QgsDebugMsgLevel( u"Checking %1: ...invalid (no authMethodMetadataFactory method)"_s.arg( myLib.fileName() ), 2 );
196 }
197 }
198#endif
199}
200
201// typedef for the unload auth method function
202typedef void cleanupAuthMethod_t();
203
205{
206 clean();
207 if ( sInstance == this )
208 sInstance = nullptr;
209};
210
211void QgsAuthMethodRegistry::clean()
212{
213 AuthMethods::const_iterator it = mAuthMethods.begin();
214
215 while ( it != mAuthMethods.end() )
216 {
217 QgsDebugMsgLevel( u"cleanup: %1"_s.arg( it->first ), 5 );
218 const QString lib = it->second->library();
219 QLibrary myLib( lib );
220 if ( myLib.isLoaded() )
221 {
222 cleanupAuthMethod_t *cleanupFunc = reinterpret_cast< cleanupAuthMethod_t * >( cast_to_fptr( myLib.resolve( "cleanupAuthMethod" ) ) );
223 if ( cleanupFunc )
224 cleanupFunc();
225 }
226 // clear cached QgsAuthMethodMetadata *
227 delete it->second;
228 ++it;
229 }
230
231 mAuthMethods.clear();
232}
233
234
235QString QgsAuthMethodRegistry::library( const QString &authMethodKey ) const
236{
237 QgsAuthMethodMetadata *md = findMetadata_( mAuthMethods, authMethodKey );
238
239 if ( md )
240 {
242 return md->library();
244 }
245
246 return QString();
247}
248
249QString QgsAuthMethodRegistry::pluginList( bool asHtml ) const
250{
251 AuthMethods::const_iterator it = mAuthMethods.begin();
252
253 if ( mAuthMethods.empty() )
254 {
255 return QObject::tr( "No authentication method plugins are available." );
256 }
257
258 QString list;
259
260 if ( asHtml )
261 {
262 list += "<ol>"_L1;
263 }
264
265 while ( it != mAuthMethods.end() )
266 {
267 if ( asHtml )
268 {
269 list += "<li>"_L1;
270 }
271
272 list += it->second->description();
273
274 if ( asHtml )
275 {
276 list += "<br></li>"_L1;
277 }
278 else
279 {
280 list += '\n';
281 }
282
283 ++it;
284 }
285
286 if ( asHtml )
287 {
288 list += "</ol>"_L1;
289 }
290
291 return list;
292}
293
295{
296 return mLibraryDirectory;
297}
298
300{
301 mLibraryDirectory = path;
302}
303
304
305// typedef for the QgsAuthMethod class factory
307
308const QgsAuthMethodMetadata *QgsAuthMethodRegistry::authMethodMetadata( const QString &authMethodKey ) const
309{
310 return findMetadata_( mAuthMethods, authMethodKey );
311}
312
314{
315 QgsAuthMethodMetadata *metadata = findMetadata_( mAuthMethods, authMethodKey );
316 if ( !metadata )
317 {
318 QgsMessageLog::logMessage( QObject::tr( "Invalid auth method %1" ).arg( authMethodKey ) );
319 return nullptr;
320 }
321
322 return metadata->createAuthMethod();
323}
324
326{
327 QStringList lst;
328 for ( AuthMethods::const_iterator it = mAuthMethods.begin(); it != mAuthMethods.end(); ++it )
329 {
330 lst.append( it->first );
331 }
332 return lst;
333}
@ PlainText
Text message.
Definition qgis.h:176
Holds data auth method key, description, and associated shared library file information.
virtual QgsAuthMethod * createAuthMethod() const
Class factory to return a pointer to a newly created QgsDataProvider object.
QString key() const
Returns the unique key associated with the method.
QString library() const
Returns the library file name.
A registry / canonical manager of authentication methods.
const QgsAuthMethodMetadata * authMethodMetadata(const QString &authMethodKey) const
Returns metadata of the auth method or nullptr if not found.
static QgsAuthMethodRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString pluginList(bool asHtml=false) const
Returns list of auth method plugins found.
void setLibraryDirectory(const QDir &path)
Sets library directory where to search for plugins.
QDir libraryDirectory() const
Returns library directory where plugins are found.
Q_DECL_DEPRECATED QString library(const QString &authMethodKey) const
Returns path for the library of the auth method.
QStringList authMethodList() const
Returns list of available auth methods by their keys.
std::map< QString, QgsAuthMethodMetadata * > AuthMethods
Type for auth method metadata associative container.
QgsAuthMethod * createAuthMethod(const QString &authMethodKey)
Create an instance of the auth method.
Abstract base class for authentication method plugins.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
virtual void showMessage(bool blocking=true)=0
display the message to the user and deletes itself
static QgsMessageOutput * createMessageOutput()
function that returns new class derived from QgsMessageOutput (don't forget to delete it then if show...
virtual void setMessage(const QString &message, Qgis::StringFormat format)=0
Sets message, it won't be displayed until.
virtual void setTitle(const QString &title)=0
Sets title for the messages.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:7678
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7677
#define cast_to_fptr(f)
Definition qgis.h:6993
void cleanupAuthMethod_t()
QgsAuthMethod * classFactoryFunction_t()
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59