File indexing completed on 2024-04-28 05:50:05

0001 /*
0002  * SPDX-License-Identifier: GPL-3.0-or-later
0003  * SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
0004  */
0005 #ifndef ACCOUNTS_ACCOUNT_H
0006 #define ACCOUNTS_ACCOUNT_H
0007 
0008 #include <QDateTime>
0009 #include <QObject>
0010 #include <QScopedPointer>
0011 #include <QSettings>
0012 #include <QString>
0013 #include <QThread>
0014 #include <QUuid>
0015 #include <QVector>
0016 
0017 #include <functional>
0018 #include <optional>
0019 
0020 #include "keys.h"
0021 
0022 namespace accounts
0023 {
0024     using PersistenceAction = std::function<void(QSettings&)>;
0025     using SettingsProvider = std::function<void(const PersistenceAction&)>;
0026 
0027     class AccountPrivate;
0028     class Account: public QObject
0029     {
0030         Q_OBJECT
0031     public:
0032         enum Algorithm {
0033             Totp,
0034             Hotp
0035         };
0036         Q_ENUM(Algorithm)
0037         enum Hash {
0038             Sha1, Sha256, Sha512
0039         };
0040         Q_ENUM(Hash)
0041         explicit Account(AccountPrivate *d, QObject *parent = nullptr);
0042         QString name(void) const;
0043         QString token(void) const;
0044         QString issuer(void) const;
0045         quint64 counter(void) const;
0046         QDateTime epoch(void) const;
0047         uint timeStep(void) const;
0048         std::optional<uint> offset(void) const;
0049         int tokenLength(void) const;
0050         bool checksum(void) const;
0051         Hash hash(void) const;
0052         Algorithm algorithm(void) const;
0053     public Q_SLOTS:
0054         void remove(void);
0055         void recompute(void);
0056         void setCounter(quint64 counter);
0057         void advanceCounter(quint64 by = 1ULL);
0058     Q_SIGNALS:
0059         void tokenChanged(const QString &otp);
0060         void removed(void);
0061         void updated(void);
0062     private:
0063         QScopedPointer<AccountPrivate> m_dptr;
0064         Q_DECLARE_PRIVATE_D(m_dptr, Account)
0065     };
0066 
0067     class AccountStoragePrivate;
0068     class AccountStorage: public QObject
0069     {
0070         Q_OBJECT
0071     public:
0072         static AccountStorage * open(const SettingsProvider &settings, AccountSecret *secret = nullptr,
0073                                      QObject *parent = nullptr);
0074         explicit AccountStorage(const SettingsProvider &settings, QThread *thread, AccountSecret *secret = nullptr,
0075                                 QObject *parent = nullptr);
0076         void removeAll(const QSet<Account*> &accounts) const;
0077         bool isAccountStillAvailable(const QString &fullName) const;
0078         bool isAccountStillAvailable(const QString &name, const QString &issuer) const;
0079         bool contains(const QString &fullName) const;
0080         bool contains(const QString &name, const QString &issuer) const;
0081         Account * get(const QString &fullName) const;
0082         Account * get(const QString &name, const QString &issuer) const;
0083         AccountSecret * secret(void) const;
0084         QVector<QString> accounts(void) const;
0085         void dispose(void);
0086         void addHotp(const QString &name,
0087                      const QString &issuer,
0088                      const QString &secret,
0089                      uint tokenLength = 6U,
0090                      quint64 counter = 0ULL,
0091                      const std::optional<uint> offset = std::nullopt,
0092                      bool addChecksum = false);
0093         void addTotp(const QString &name,
0094                      const QString &issuer,
0095                      const QString &secret,
0096                      uint tokenLength = 6U,
0097                      uint timeStep = 30U,
0098                      const QDateTime &epoch = QDateTime::fromMSecsSinceEpoch(0),
0099                      Account::Hash hash = Account::Hash::Sha1);
0100         void clearError(void);
0101         bool hasError(void) const;
0102         bool isLoaded(void) const;
0103     Q_SIGNALS:
0104         void added(const QString &fullName);
0105         void removed(const QString &fullName);
0106         void error(void);
0107         void loaded(void);
0108         void disposed(void);
0109     private Q_SLOTS:
0110         void unlock(void);
0111         void load(void);
0112         void accountRemoved(void);
0113         void handleDisposal(void);
0114         void handleError(void);
0115         void handleLoaded(void);
0116         void handleHotp(const QUuid id, const QString &name, const QString &issuer,
0117                         const QByteArray &secret, const QByteArray &nonce, uint tokenLength,
0118                         quint64 counter, bool fixedTruncation, uint offset, bool checksum);
0119         void handleTotp(const QUuid id, const QString &name, const QString &issuer,
0120                         const QByteArray &secret, const QByteArray &nonce, uint tokenLength,
0121                         uint timeStep, const QDateTime &epoch, Account::Hash hash);
0122     private:
0123         QScopedPointer<AccountStoragePrivate> m_dptr;
0124         Q_DECLARE_PRIVATE_D(m_dptr, AccountStorage)
0125     };
0126 }
0127 
0128 #endif