QGIS API Documentation 3.99.0-Master (e9821da5c6b)
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 "qgsauthbasicmethod.h"
33#include "qgsauthesritokenmethod.h"
34#include "qgsauthidentcertmethod.h"
35#ifdef HAVE_OAUTH2_PLUGIN
36#include "qgsauthoauth2method.h"
37#endif
38#include "qgsauthpkipathsmethod.h"
39#include "qgsauthpkcs12method.h"
40#endif
41
42#include <QString>
43#include <QDir>
44#include <QLibrary>
45#include <QRegularExpression>
46
47
48static QgsAuthMethodRegistry *sInstance = nullptr;
49
50
51QgsAuthMethodRegistry *QgsAuthMethodRegistry::instance( const QString &pluginPath )
52{
53 if ( !sInstance )
54 {
55 static QMutex sMutex;
56 const QMutexLocker locker( &sMutex );
57 if ( !sInstance )
58 {
59 sInstance = new QgsAuthMethodRegistry( pluginPath );
60 }
61 }
62 return sInstance;
63}
64
73static QgsAuthMethodMetadata *findMetadata_( QgsAuthMethodRegistry::AuthMethods const &metaData,
74 QString const &authMethodKey )
75{
76 const QgsAuthMethodRegistry::AuthMethods::const_iterator i =
77 metaData.find( authMethodKey );
78
79 if ( i != metaData.end() )
80 {
81 return i->second;
82 }
83
84 return nullptr;
85}
86
87QgsAuthMethodRegistry::QgsAuthMethodRegistry( const QString &pluginPath )
88{
89 // At startup, examine the libs in the qgis/lib dir and store those that
90 // are an auth method shared lib
91 // check all libs in the current plugin directory and get name and descriptions
92#if 0
93 char **argv = qApp->argv();
94 QString appDir = argv[0];
95 int bin = appDir.findRev( "/bin", -1, false );
96 QString baseDir = appDir.left( bin );
97 QString mLibraryDirectory = baseDir + "/lib";
98#endif
99 mLibraryDirectory.setPath( pluginPath );
100 mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
101 mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );
102
103 init();
104}
105
106void QgsAuthMethodRegistry::init()
107{
108#ifdef HAVE_STATIC_PROVIDERS
109 mAuthMethods[ QgsAuthBasicMethod::AUTH_METHOD_KEY] = new QgsAuthBasicMethodMetadata();
110 mAuthMethods[ QgsAuthEsriTokenMethod::AUTH_METHOD_KEY] = new QgsAuthEsriTokenMethodMetadata();
111 mAuthMethods[ QgsAuthIdentCertMethod::AUTH_METHOD_KEY] = new QgsAuthIdentCertMethodMetadata();
112#ifdef HAVE_OAUTH2_PLUGIN
113 mAuthMethods[ QgsAuthOAuth2Method::AUTH_METHOD_KEY] = new QgsAuthOAuth2MethodMetadata();
114#endif
115 mAuthMethods[ QgsAuthPkiPathsMethod::AUTH_METHOD_KEY] = new QgsAuthPkiPathsMethodMetadata();
116 mAuthMethods[ QgsAuthPkcs12Method::AUTH_METHOD_KEY] = new QgsAuthPkcs12MethodMetadata();
117#else
118 typedef QgsAuthMethodMetadata *factory_function( );
119
120#if defined(Q_OS_WIN) || defined(__CYGWIN__)
121 mLibraryDirectory.setNameFilters( QStringList( "*authmethod_*.dll" ) );
122#else
123 mLibraryDirectory.setNameFilters( QStringList( u"*authmethod_*.so"_s ) );
124#endif
125 QgsDebugMsgLevel( u"Checking for auth method plugins in: %1"_s.arg( mLibraryDirectory.path() ), 2 );
126
127 if ( mLibraryDirectory.count() == 0 )
128 {
129 QString msg = QObject::tr( "No QGIS auth method plugins found in:\n%1\n" ).arg( mLibraryDirectory.path() );
130 msg += QObject::tr( "No authentication methods can be used. Check your QGIS installation" );
131
132 QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
133 output->setTitle( QObject::tr( "No Authentication Methods" ) );
135 output->showMessage();
136 return;
137 }
138
139 // auth method file regex pattern, only files matching the pattern are loaded if the variable is defined
140 const QString filePattern = getenv( "QGIS_AUTHMETHOD_FILE" );
141 QRegularExpression fileRegexp;
142 if ( !filePattern.isEmpty() )
143 {
144 fileRegexp.setPattern( filePattern );
145 }
146
147 QListIterator<QFileInfo> it( mLibraryDirectory.entryInfoList() );
148 while ( it.hasNext() )
149 {
150 const QFileInfo fi( it.next() );
151
152 if ( !filePattern.isEmpty() )
153 {
154 if ( fi.fileName().indexOf( fileRegexp ) == -1 )
155 {
156 QgsDebugError( "auth method " + fi.fileName() + " skipped because doesn't match pattern " + filePattern );
157 continue;
158 }
159 }
160
161 QLibrary myLib( fi.filePath() );
162 if ( !myLib.load() )
163 {
164 QgsDebugError( u"Checking %1: ...invalid (lib not loadable): %2"_s.arg( myLib.fileName(), myLib.errorString() ) );
165 continue;
166 }
167
168 bool libraryLoaded { false };
169 QFunctionPointer func = myLib.resolve( u"authMethodMetadataFactory"_s.toLatin1().data() );
170 factory_function *function = reinterpret_cast< factory_function * >( cast_to_fptr( func ) );
171 if ( function )
172 {
173 QgsAuthMethodMetadata *meta = function();
174 if ( meta )
175 {
176 if ( findMetadata_( mAuthMethods, meta->key() ) )
177 {
178 QgsDebugError( u"Checking %1: ...invalid (key %2 already registered)"_s.arg( myLib.fileName() ).arg( meta->key() ) );
179 delete meta;
180 continue;
181 }
182 // add this method to the map
183 mAuthMethods[meta->key()] = meta;
184 libraryLoaded = true;
185 }
186 }
187 if ( ! libraryLoaded )
188 {
189 QgsDebugMsgLevel( u"Checking %1: ...invalid (no authMethodMetadataFactory method)"_s.arg( myLib.fileName() ), 2 );
190 }
191 }
192#endif
193}
194
195// typedef for the unload auth method function
196typedef void cleanupAuthMethod_t();
197
199{
200 clean();
201 if ( sInstance == this )
202 sInstance = nullptr;
203};
204
205void QgsAuthMethodRegistry::clean()
206{
207 AuthMethods::const_iterator it = mAuthMethods.begin();
208
209 while ( it != mAuthMethods.end() )
210 {
211 QgsDebugMsgLevel( u"cleanup: %1"_s.arg( it->first ), 5 );
212 const QString lib = it->second->library();
213 QLibrary myLib( lib );
214 if ( myLib.isLoaded() )
215 {
216 cleanupAuthMethod_t *cleanupFunc = reinterpret_cast< cleanupAuthMethod_t * >( cast_to_fptr( myLib.resolve( "cleanupAuthMethod" ) ) );
217 if ( cleanupFunc )
218 cleanupFunc();
219 }
220 // clear cached QgsAuthMethodMetadata *
221 delete it->second;
222 ++it;
223 }
224
225 mAuthMethods.clear();
226}
227
228
229QString QgsAuthMethodRegistry::library( const QString &authMethodKey ) const
230{
231 QgsAuthMethodMetadata *md = findMetadata_( mAuthMethods, authMethodKey );
232
233 if ( md )
234 {
236 return md->library();
238 }
239
240 return QString();
241}
242
243QString QgsAuthMethodRegistry::pluginList( bool asHtml ) const
244{
245 AuthMethods::const_iterator it = mAuthMethods.begin();
246
247 if ( mAuthMethods.empty() )
248 {
249 return QObject::tr( "No authentication method plugins are available." );
250 }
251
252 QString list;
253
254 if ( asHtml )
255 {
256 list += "<ol>"_L1;
257 }
258
259 while ( it != mAuthMethods.end() )
260 {
261 if ( asHtml )
262 {
263 list += "<li>"_L1;
264 }
265
266 list += it->second->description();
267
268 if ( asHtml )
269 {
270 list += "<br></li>"_L1;
271 }
272 else
273 {
274 list += '\n';
275 }
276
277 ++it;
278 }
279
280 if ( asHtml )
281 {
282 list += "</ol>"_L1;
283 }
284
285 return list;
286}
287
289{
290 return mLibraryDirectory;
291}
292
294{
295 mLibraryDirectory = path;
296}
297
298
299// typedef for the QgsAuthMethod class factory
301
302const QgsAuthMethodMetadata *QgsAuthMethodRegistry::authMethodMetadata( const QString &authMethodKey ) const
303{
304 return findMetadata_( mAuthMethods, authMethodKey );
305}
306
308{
309 QgsAuthMethodMetadata *metadata = findMetadata_( mAuthMethods, authMethodKey );
310 if ( !metadata )
311 {
312 QgsMessageLog::logMessage( QObject::tr( "Invalid auth method %1" ).arg( authMethodKey ) );
313 return nullptr;
314 }
315
316 return metadata->createAuthMethod();
317}
318
320{
321 QStringList lst;
322 for ( AuthMethods::const_iterator it = mAuthMethods.begin(); it != mAuthMethods.end(); ++it )
323 {
324 lst.append( it->first );
325 }
326 return lst;
327}
328
329
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())
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, MessageType msgType)=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:7475
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7474
#define cast_to_fptr(f)
Definition qgis.h:6776
void cleanupAuthMethod_t()
QgsAuthMethod * classFactoryFunction_t()
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59