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