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