/* * SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk */ #ifndef ACCOUNTS_ACCOUNT_H #define ACCOUNTS_ACCOUNT_H #include #include #include #include #include #include #include #include #include #include #include "keys.h" namespace accounts { using PersistenceAction = std::function; using SettingsProvider = std::function; class AccountPrivate; class Account : public QObject { Q_OBJECT public: enum Algorithm { Totp, Hotp }; Q_ENUM(Algorithm) enum Hash { Sha1, Sha256, Sha512 }; Q_ENUM(Hash) explicit Account(AccountPrivate *d, QObject *parent = nullptr); QString name(void) const; QString token(void) const; QString issuer(void) const; quint64 counter(void) const; QDateTime epoch(void) const; uint timeStep(void) const; std::optional offset(void) const; int tokenLength(void) const; bool checksum(void) const; Hash hash(void) const; Algorithm algorithm(void) const; public Q_SLOTS: void remove(void); void recompute(void); void setCounter(quint64 counter); void advanceCounter(quint64 by = 1ULL); Q_SIGNALS: void tokenChanged(const QString &otp); void removed(void); void updated(void); private: QScopedPointer m_dptr; Q_DECLARE_PRIVATE_D(m_dptr, Account) }; class AccountStoragePrivate; class AccountStorage : public QObject { Q_OBJECT public: static AccountStorage *open(const SettingsProvider &settings, AccountSecret *secret = nullptr, QObject *parent = nullptr); explicit AccountStorage(const SettingsProvider &settings, QThread *thread, AccountSecret *secret = nullptr, QObject *parent = nullptr); void removeAll(const QSet &accounts) const; bool isAccountStillAvailable(const QString &fullName) const; bool isAccountStillAvailable(const QString &name, const QString &issuer) const; bool contains(const QString &fullName) const; bool contains(const QString &name, const QString &issuer) const; Account *get(const QString &fullName) const; Account *get(const QString &name, const QString &issuer) const; AccountSecret *secret(void) const; QList accounts(void) const; void dispose(void); void addHotp(const QString &name, const QString &issuer, const QString &secret, uint tokenLength = 6U, quint64 counter = 0ULL, const std::optional offset = std::nullopt, bool addChecksum = false); void addTotp(const QString &name, const QString &issuer, const QString &secret, uint tokenLength = 6U, uint timeStep = 30U, const QDateTime &epoch = QDateTime::fromMSecsSinceEpoch(0), Account::Hash hash = Account::Hash::Sha1); void clearError(void); bool hasError(void) const; bool isLoaded(void) const; Q_SIGNALS: void added(const QString &fullName); void removed(const QString &fullName); void error(void); void loaded(void); void disposed(void); private Q_SLOTS: void unlock(void); void load(void); void accountRemoved(void); void handleDisposal(void); void handleError(void); void handleLoaded(void); void handleHotp(const QUuid id, const QString &name, const QString &issuer, const QByteArray &secret, const QByteArray &nonce, uint tokenLength, quint64 counter, bool fixedTruncation, uint offset, bool checksum); void handleTotp(const QUuid id, const QString &name, const QString &issuer, const QByteArray &secret, const QByteArray &nonce, uint tokenLength, uint timeStep, const QDateTime &epoch, Account::Hash hash); private: QScopedPointer m_dptr; Q_DECLARE_PRIVATE_D(m_dptr, AccountStorage) }; } #endif