Make authenticator changes to protocol backwards-compatible
[quassel.git] / src / core / core.h
1 /***************************************************************************
2  *   Copyright (C) 2005-2016 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 #ifndef CORE_H
22 #define CORE_H
23
24 #include <QDateTime>
25 #include <QString>
26 #include <QVariant>
27 #include <QTimer>
28
29 #ifdef HAVE_SSL
30 #  include <QSslSocket>
31 #  include "sslserver.h"
32 #else
33 #  include <QTcpSocket>
34 #  include <QTcpServer>
35 #endif
36
37 #include "authenticator.h"
38 #include "bufferinfo.h"
39 #include "message.h"
40 #include "oidentdconfiggenerator.h"
41 #include "sessionthread.h"
42 #include "storage.h"
43 #include "types.h"
44
45 class CoreAuthHandler;
46 class CoreSession;
47 struct NetworkInfo;
48 class SessionThread;
49 class SignalProxy;
50
51 class AbstractSqlMigrationReader;
52 class AbstractSqlMigrationWriter;
53
54 class Core : public QObject
55 {
56     Q_OBJECT
57
58 public:
59     static Core *instance();
60     static void destroy();
61
62     static void saveState();
63     static void restoreState();
64
65     /*** Storage access ***/
66     // These methods are threadsafe.
67
68     //! Validate user
69     /**
70      * \param userName The user's login name
71      * \param password The user's uncrypted password
72      * \return The user's ID if valid; 0 otherwise
73      */
74     static inline UserId validateUser(const QString &userName, const QString &password) {
75         return instance()->_storage->validateUser(userName, password);
76     }
77
78     //! Authenticate user against auth backend
79     /**
80      * \param userName The user's login name
81      * \param password The user's uncrypted password
82      * \return The user's ID if valid; 0 otherwise
83      */
84     static inline UserId authenticateUser(const QString &userName, const QString &password) {
85         return instance()->_authenticator->validateUser(userName, password);
86     }
87
88     //! Add a new user, exposed so auth providers can call this without being the storage.
89     /**
90      * \param userName The user's login name
91      * \param password The user's uncrypted password
92      * \return The user's ID if valid; 0 otherwise
93      */
94     static inline UserId addUser(const QString &userName, const QString &password) {
95         return instance()->_storage->addUser(userName, password);
96     }
97
98     //! Change a user's password
99     /**
100      * \param userId     The user's ID
101      * \param password   The user's unencrypted new password
102      * \return true, if the password change was successful
103      */
104     static bool changeUserPassword(UserId userId, const QString &password);
105
106     //! Store a user setting persistently
107     /**
108      * \param userId       The users Id
109      * \param settingName  The Name of the Setting
110      * \param data         The Value
111      */
112     static inline void setUserSetting(UserId userId, const QString &settingName, const QVariant &data)
113     {
114         instance()->_storage->setUserSetting(userId, settingName, data);
115     }
116
117
118     //! Retrieve a persistent user setting
119     /**
120      * \param userId       The users Id
121      * \param settingName  The Name of the Setting
122      * \param defaultValue Value to return in case it's unset.
123      * \return the Value of the Setting or the default value if it is unset.
124      */
125     static inline QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultValue = QVariant())
126     {
127         return instance()->_storage->getUserSetting(userId, settingName, defaultValue);
128     }
129
130
131     /* Identity handling */
132     static inline IdentityId createIdentity(UserId user, CoreIdentity &identity)
133     {
134         return instance()->_storage->createIdentity(user, identity);
135     }
136
137
138     static bool updateIdentity(UserId user, const CoreIdentity &identity)
139     {
140         return instance()->_storage->updateIdentity(user, identity);
141     }
142
143
144     static void removeIdentity(UserId user, IdentityId identityId)
145     {
146         instance()->_storage->removeIdentity(user, identityId);
147     }
148
149
150     static QList<CoreIdentity> identities(UserId user)
151     {
152         return instance()->_storage->identities(user);
153     }
154
155
156     //! Create a Network in the Storage and store it's Id in the given NetworkInfo
157     /** \note This method is thredsafe.
158      *
159      *  \param user        The core user
160      *  \param networkInfo a NetworkInfo definition to store the newly created ID in
161      *  \return true if successfull.
162      */
163     static bool createNetwork(UserId user, NetworkInfo &info);
164
165     //! Apply the changes to NetworkInfo info to the storage engine
166     /** \note This method is thredsafe.
167      *
168      *  \param user        The core user
169      *  \param networkInfo The Updated NetworkInfo
170      *  \return true if successfull.
171      */
172     static inline bool updateNetwork(UserId user, const NetworkInfo &info)
173     {
174         return instance()->_storage->updateNetwork(user, info);
175     }
176
177
178     //! Permanently remove a Network and all the data associated with it.
179     /** \note This method is thredsafe.
180      *
181      *  \param user        The core user
182      *  \param networkId   The network to delete
183      *  \return true if successfull.
184      */
185     static inline bool removeNetwork(UserId user, const NetworkId &networkId)
186     {
187         return instance()->_storage->removeNetwork(user, networkId);
188     }
189
190
191     //! Returns a list of all NetworkInfos for the given UserId user
192     /** \note This method is thredsafe.
193      *
194      *  \param user        The core user
195      *  \return QList<NetworkInfo>.
196      */
197     static inline QList<NetworkInfo> networks(UserId user)
198     {
199         return instance()->_storage->networks(user);
200     }
201
202
203     //! Get a list of Networks to restore
204     /** Return a list of networks the user was connected at the time of core shutdown
205      *  \note This method is threadsafe.
206      *
207      *  \param user  The User Id in question
208      */
209     static inline QList<NetworkId> connectedNetworks(UserId user)
210     {
211         return instance()->_storage->connectedNetworks(user);
212     }
213
214
215     //! Update the connected state of a network
216     /** \note This method is threadsafe
217      *
218      *  \param user        The Id of the networks owner
219      *  \param networkId   The Id of the network
220      *  \param isConnected whether the network is connected or not
221      */
222     static inline void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected)
223     {
224         return instance()->_storage->setNetworkConnected(user, networkId, isConnected);
225     }
226
227
228     //! Get a hash of channels with their channel keys for a given network
229     /** The keys are channel names and values are passwords (possibly empty)
230      *  \note This method is threadsafe
231      *
232      *  \param user       The id of the networks owner
233      *  \param networkId  The Id of the network
234      */
235     static inline QHash<QString, QString> persistentChannels(UserId user, const NetworkId &networkId)
236     {
237         return instance()->_storage->persistentChannels(user, networkId);
238     }
239
240
241     //! Update the connected state of a channel
242     /** \note This method is threadsafe
243      *
244      *  \param user       The Id of the networks owner
245      *  \param networkId  The Id of the network
246      *  \param channel    The name of the channel
247      *  \param isJoined   whether the channel is connected or not
248      */
249     static inline void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined)
250     {
251         return instance()->_storage->setChannelPersistent(user, networkId, channel, isJoined);
252     }
253
254
255     //! Update the key of a channel
256     /** \note This method is threadsafe
257      *
258      *  \param user       The Id of the networks owner
259      *  \param networkId  The Id of the network
260      *  \param channel    The name of the channel
261      *  \param key        The key of the channel (possibly empty)
262      */
263     static inline void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key)
264     {
265         return instance()->_storage->setPersistentChannelKey(user, networkId, channel, key);
266     }
267
268
269     //! retrieve last known away message for session restore
270     /** \note This method is threadsafe
271      *
272      *  \param user       The Id of the networks owner
273      *  \param networkId  The Id of the network
274      */
275     static inline QString awayMessage(UserId user, NetworkId networkId)
276     {
277         return instance()->_storage->awayMessage(user, networkId);
278     }
279
280
281     //! Make away message persistent for session restore
282     /** \note This method is threadsafe
283      *
284      *  \param user       The Id of the networks owner
285      *  \param networkId  The Id of the network
286      *  \param awayMsg    The current away message of own user
287      */
288     static inline void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg)
289     {
290         return instance()->_storage->setAwayMessage(user, networkId, awayMsg);
291     }
292
293
294     //! retrieve last known user mode for session restore
295     /** \note This method is threadsafe
296      *
297      *  \param user       The Id of the networks owner
298      *  \param networkId  The Id of the network
299      */
300     static inline QString userModes(UserId user, NetworkId networkId)
301     {
302         return instance()->_storage->userModes(user, networkId);
303     }
304
305
306     //! Make our user modes persistent for session restore
307     /** \note This method is threadsafe
308      *
309      *  \param user       The Id of the networks owner
310      *  \param networkId  The Id of the network
311      *  \param userModes  The current user modes of own user
312      */
313     static inline void setUserModes(UserId user, NetworkId networkId, const QString &userModes)
314     {
315         return instance()->_storage->setUserModes(user, networkId, userModes);
316     }
317
318
319     //! Get the unique BufferInfo for the given combination of network and buffername for a user.
320     /** \note This method is threadsafe.
321      *
322      *  \param user      The core user who owns this buffername
323      *  \param networkId The network id
324      *  \param type      The type of the buffer (StatusBuffer, Channel, etc.)
325      *  \param buffer    The buffer name (if empty, the net's status buffer is returned)
326      *  \param create    Whether or not the buffer should be created if it doesnt exist
327      *  \return The BufferInfo corresponding to the given network and buffer name, or 0 if not found
328      */
329     static inline BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "", bool create = true)
330     {
331         return instance()->_storage->bufferInfo(user, networkId, type, buffer, create);
332     }
333
334
335     //! Get the unique BufferInfo for a bufferId
336     /** \note This method is threadsafe
337      *  \param user      The core user who owns this buffername
338      *  \param bufferId  The id of the buffer
339      *  \return The BufferInfo corresponding to the given buffer id, or an invalid BufferInfo if not found.
340      */
341     static inline BufferInfo getBufferInfo(UserId user, const BufferId &bufferId)
342     {
343         return instance()->_storage->getBufferInfo(user, bufferId);
344     }
345
346
347     //! Store a Message in the storage backend and set it's unique Id.
348     /** \note This method is threadsafe.
349      *
350      *  \param message The message object to be stored
351      *  \return true on success
352      */
353     static inline bool storeMessage(Message &message)
354     {
355         return instance()->_storage->logMessage(message);
356     }
357
358
359     //! Store a list of Messages in the storage backend and set their unique Id.
360     /** \note This method is threadsafe.
361      *
362      *  \param messages The list message objects to be stored
363      *  \return true on success
364      */
365     static inline bool storeMessages(MessageList &messages)
366     {
367         return instance()->_storage->logMessages(messages);
368     }
369
370
371     //! Request a certain number messages stored in a given buffer.
372     /** \param buffer   The buffer we request messages from
373      *  \param first    if != -1 return only messages with a MsgId >= first
374      *  \param last     if != -1 return only messages with a MsgId < last
375      *  \param limit    if != -1 limit the returned list to a max of \limit entries
376      *  \return The requested list of messages
377      */
378     static inline QList<Message> requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1)
379     {
380         return instance()->_storage->requestMsgs(user, bufferId, first, last, limit);
381     }
382
383
384     //! Request a certain number of messages across all buffers
385     /** \param first    if != -1 return only messages with a MsgId >= first
386      *  \param last     if != -1 return only messages with a MsgId < last
387      *  \param limit    Max amount of messages
388      *  \return The requested list of messages
389      */
390     static inline QList<Message> requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1)
391     {
392         return instance()->_storage->requestAllMsgs(user, first, last, limit);
393     }
394
395
396     //! Request a list of all buffers known to a user.
397     /** This method is used to get a list of all buffers we have stored a backlog from.
398      *  \note This method is threadsafe.
399      *
400      *  \param user  The user whose buffers we request
401      *  \return A list of the BufferInfos for all buffers as requested
402      */
403     static inline QList<BufferInfo> requestBuffers(UserId user)
404     {
405         return instance()->_storage->requestBuffers(user);
406     }
407
408
409     //! Request a list of BufferIds for a given NetworkId
410     /** \note This method is threadsafe.
411      *
412      *  \param user  The user whose buffers we request
413      *  \param networkId  The NetworkId of the network in question
414      *  \return List of BufferIds belonging to the Network
415      */
416     static inline QList<BufferId> requestBufferIdsForNetwork(UserId user, NetworkId networkId)
417     {
418         return instance()->_storage->requestBufferIdsForNetwork(user, networkId);
419     }
420
421
422     //! Remove permanently a buffer and it's content from the storage backend
423     /** This call cannot be reverted!
424      *  \note This method is threadsafe.
425      *
426      *  \param user      The user who is the owner of the buffer
427      *  \param bufferId  The bufferId
428      *  \return true if successfull
429      */
430     static inline bool removeBuffer(const UserId &user, const BufferId &bufferId)
431     {
432         return instance()->_storage->removeBuffer(user, bufferId);
433     }
434
435
436     //! Rename a Buffer
437     /** \note This method is threadsafe.
438      *  \param user      The id of the buffer owner
439      *  \param bufferId  The bufferId
440      *  \param newName   The new name of the buffer
441      *  \return true if successfull
442      */
443     static inline bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName)
444     {
445         return instance()->_storage->renameBuffer(user, bufferId, newName);
446     }
447
448
449     //! Merge the content of two Buffers permanently. This cannot be reversed!
450     /** \note This method is threadsafe.
451      *  \param user      The id of the buffer owner
452      *  \param bufferId1 The bufferId of the remaining buffer
453      *  \param bufferId2 The buffer that is about to be removed
454      *  \return true if successfulln
455      */
456     static inline bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2)
457     {
458         return instance()->_storage->mergeBuffersPermanently(user, bufferId1, bufferId2);
459     }
460
461
462     //! Update the LastSeenDate for a Buffer
463     /** This Method is used to make the LastSeenDate of a Buffer persistent
464      *  \note This method is threadsafe.
465      *
466      * \param user      The Owner of that Buffer
467      * \param bufferId  The buffer id
468      * \param MsgId     The Message id of the message that has been just seen
469      */
470     static inline void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId)
471     {
472         return instance()->_storage->setBufferLastSeenMsg(user, bufferId, msgId);
473     }
474
475
476     //! Get a Hash of all last seen message ids
477     /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds
478      *  \note This method is threadsafe.
479      *
480      * \param user      The Owner of the buffers
481      */
482     static inline QHash<BufferId, MsgId> bufferLastSeenMsgIds(UserId user)
483     {
484         return instance()->_storage->bufferLastSeenMsgIds(user);
485     }
486
487
488     //! Update the MarkerLineMsgId for a Buffer
489     /** This Method is used to make the marker line position of a Buffer persistent
490      *  \note This method is threadsafe.
491      *
492      * \param user      The Owner of that Buffer
493      * \param bufferId  The buffer id
494      * \param MsgId     The Message id where the marker line should be placed
495      */
496     static inline void setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId)
497     {
498         return instance()->_storage->setBufferMarkerLineMsg(user, bufferId, msgId);
499     }
500
501
502     //! Get a Hash of all marker line message ids
503     /** This Method is called when the Quassel Core is started to restore the MarkerLineMsgIds
504      *  \note This method is threadsafe.
505      *
506      * \param user      The Owner of the buffers
507      */
508     static inline QHash<BufferId, MsgId> bufferMarkerLineMsgIds(UserId user)
509     {
510         return instance()->_storage->bufferMarkerLineMsgIds(user);
511     }
512
513
514     static inline QDateTime startTime() { return instance()->_startTime; }
515     static inline bool isConfigured() { return instance()->_configured; }
516     static bool sslSupported();
517
518     /**
519      * Reloads SSL certificates used for connection with clients
520      *
521      * @return True if certificates reloaded successfully, otherwise false.
522      */
523     static bool reloadCerts();
524
525     static QVariantList backendInfo();
526     static QVariantList authenticatorInfo();
527
528     /**
529      * Checks if a storage backend is the default storage backend. This
530      * hardcodes this information into the core (not the client).
531      *
532      * \param backend    The backend to check.
533      *
534      * @return True if storage backend is default, false otherwise.
535      */
536     static inline bool isStorageBackendDefault(const Storage *backend)
537     {
538         return (backend->displayName() == "SQLite") ? true : false;
539     }
540
541     static QString setup(const QString &adminUser, const QString &adminPassword, const QString &backend, const QVariantMap &setupData, const QString &authBackend, const QVariantMap &authSetupMap);
542
543     static inline QTimer &syncTimer() { return instance()->_storageSyncTimer; }
544
545     inline OidentdConfigGenerator *oidentdConfigGenerator() const { return _oidentdConfigGenerator; }
546
547     static const int AddClientEventId;
548
549 public slots:
550     //! Make storage data persistent
551     /** \note This method is threadsafe.
552      */
553     void syncStorage();
554     void setupInternalClientSession(InternalPeer *clientConnection);
555     QString setupCore(const QString &adminUser, const QString &adminPassword, const QString &backend, const QVariantMap &setupData, const QString &authBackend, const QVariantMap &authSetupMap);
556
557 signals:
558     //! Sent when a BufferInfo is updated in storage.
559     void bufferInfoUpdated(UserId user, const BufferInfo &info);
560
561     //! Relay from CoreSession::sessionState(). Used for internal connection only
562     void sessionState(const Protocol::SessionState &sessionState);
563
564 protected:
565     virtual void customEvent(QEvent *event);
566
567 private slots:
568     bool startListening();
569     void stopListening(const QString &msg = QString());
570     void incomingConnection();
571     void clientDisconnected();
572
573     bool initStorage(const QString &backend, const QVariantMap &settings, bool setup = false);
574     bool initAuthenticator(const QString &backend, const QVariantMap &settings, bool setup = false);
575
576     void socketError(QAbstractSocket::SocketError err, const QString &errorString);
577     void setupClientSession(RemotePeer *, UserId);
578
579     bool changeUserPass(const QString &username);
580
581 private:
582     Core();
583     ~Core();
584     void init();
585     static Core *instanceptr;
586
587     SessionThread *sessionForUser(UserId userId, bool restoreState = false);
588     void addClientHelper(RemotePeer *peer, UserId uid);
589     //void processCoreSetup(QTcpSocket *socket, QVariantMap &msg);
590     QString setupCoreForInternalUsage();
591
592     void registerStorageBackends();
593     bool registerStorageBackend(Storage *);
594     void unregisterStorageBackends();
595     void unregisterStorageBackend(Storage *);
596
597     void registerAuthenticatorBackends();
598     bool registerAuthenticatorBackend(Authenticator *);
599     void unregisterAuthenticatorBackends();
600     void unregisterAuthenticatorBackend(Authenticator *);
601
602     bool selectBackend(const QString &backend);
603     bool createUser();
604     bool saveBackendSettings(const QString &backend, const QVariantMap &settings);
605     void saveAuthBackendSettings(const QString &backend, const QVariantMap &settings);
606     QVariantMap promptForSettings(const Storage *storage);
607
608 private:
609     QSet<CoreAuthHandler *> _connectingClients;
610     QHash<UserId, SessionThread *> _sessions;
611
612     // Have both a storage backend and an authenticator backend.
613     Storage *_storage;
614     Authenticator *_authenticator;
615     QTimer _storageSyncTimer;
616
617 #ifdef HAVE_SSL
618     SslServer _server, _v6server;
619 #else
620     QTcpServer _server, _v6server;
621 #endif
622
623     OidentdConfigGenerator *_oidentdConfigGenerator;
624
625     QHash<QString, Storage *> _storageBackends;
626     QHash<QString, Authenticator *> _authenticatorBackends;
627
628     QDateTime _startTime;
629
630     bool _configured;
631
632     static AbstractSqlMigrationReader *getMigrationReader(Storage *storage);
633     static AbstractSqlMigrationWriter *getMigrationWriter(Storage *storage);
634     static void stdInEcho(bool on);
635     static inline void enableStdInEcho() { stdInEcho(true); }
636     static inline void disableStdInEcho() { stdInEcho(false); }
637 };
638
639
640 #endif