File indexing completed on 2024-04-28 05:50:08
0001 /* 0002 * SPDX-License-Identifier: GPL-3.0-or-later 0003 * SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com> 0004 */ 0005 #ifndef MODEL_ACCOUNTS_H 0006 #define MODEL_ACCOUNTS_H 0007 0008 #include "input.h" 0009 #include "../account/account.h" 0010 #include "../validators/namevalidator.h" 0011 0012 #include <QAbstractListModel> 0013 #include <QByteArray> 0014 #include <QHash> 0015 #include <QModelIndex> 0016 #include <QObject> 0017 #include <QSortFilterProxyModel> 0018 #include <QString> 0019 #include <QValidator> 0020 #include <QVector> 0021 0022 #include <optional> 0023 0024 namespace model 0025 { 0026 qint64 millisecondsLeftForToken(const QDateTime &epoch, uint timeStep, 0027 const std::function<qint64(void)> &clock = &QDateTime::currentMSecsSinceEpoch); 0028 0029 class AccountView : public QObject 0030 { 0031 Q_OBJECT 0032 Q_PROPERTY(bool isHotp READ isHotp CONSTANT) 0033 Q_PROPERTY(bool isTotp READ isTotp CONSTANT) 0034 Q_PROPERTY(QString name READ name CONSTANT) 0035 Q_PROPERTY(QString token READ token NOTIFY tokenChanged) 0036 Q_PROPERTY(QString issuer READ issuer CONSTANT) 0037 Q_PROPERTY(quint64 counter READ counter NOTIFY tokenChanged) 0038 Q_PROPERTY(QDateTime epoch READ epoch CONSTANT) 0039 Q_PROPERTY(uint timeStep READ timeStep CONSTANT) 0040 Q_PROPERTY(uint offset READ offset CONSTANT) 0041 Q_PROPERTY(int tokenLength READ tokenLength CONSTANT) 0042 Q_PROPERTY(QString hash READ hash CONSTANT) 0043 public: 0044 explicit AccountView(accounts::Account *model, QObject *parent = nullptr); 0045 bool isHotp(void) const; 0046 bool isTotp(void) const; 0047 QString name(void) const; 0048 QString token(void) const; 0049 QString issuer(void) const; 0050 quint64 counter(void) const; 0051 QDateTime epoch(void) const; 0052 uint timeStep(void) const; 0053 uint offset(void) const; 0054 int tokenLength(void) const; 0055 QString hash(void) const; 0056 Q_INVOKABLE qint64 millisecondsLeftForToken(void) const; 0057 Q_SIGNALS: 0058 void tokenChanged(void); 0059 void remove(void); 0060 void recompute(void); 0061 void advanceCounter(quint64 by = 1ULL); 0062 void setCounter(quint64 value); 0063 private: 0064 accounts::Account * const m_model; 0065 }; 0066 0067 class SimpleAccountListModel: public QAbstractListModel 0068 { 0069 Q_OBJECT 0070 Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged) 0071 Q_PROPERTY(bool error READ error WRITE setError NOTIFY errorChanged) 0072 public: 0073 enum NonStandardRoles { 0074 AccountRole = Qt::ItemDataRole::UserRole 0075 }; 0076 Q_ENUM(NonStandardRoles) 0077 enum TOTPAlgorithms { 0078 Sha1, Sha256, Sha512 0079 }; 0080 Q_ENUM(TOTPAlgorithms) 0081 private: 0082 static accounts::Account::Hash toHash(const TOTPAlgorithms value); 0083 public: 0084 explicit SimpleAccountListModel(accounts::AccountStorage *storage, QObject *parent = nullptr); 0085 Q_INVOKABLE void addAccount(model::AccountInput *input); 0086 Q_INVOKABLE bool isAccountStillAvailable(const QString &name, const QString &issuer) const; 0087 Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const override; 0088 Q_INVOKABLE QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 0089 QHash<int, QByteArray> roleNames(void) const override; 0090 public: 0091 bool loaded(void) const; 0092 bool error(void) const; 0093 void setError(bool markAsError); 0094 Q_SIGNALS: 0095 void loadedChanged(void); 0096 void errorChanged(void); 0097 private Q_SLOTS: 0098 void added(const QString &account); 0099 void removed(const QString &removed); 0100 void handleError(void); 0101 private: 0102 AccountView * createView(const QString &name); 0103 void populate(const QString &name, AccountView *account); 0104 private: 0105 accounts::AccountStorage * const m_storage; 0106 private: 0107 bool m_has_error; 0108 QVector<QString> m_index; 0109 QHash<QString, AccountView*> m_accounts; 0110 }; 0111 0112 class SortedAccountsListModel: public QSortFilterProxyModel 0113 { 0114 Q_OBJECT 0115 public: 0116 explicit SortedAccountsListModel(QObject *parent = nullptr); 0117 void setSourceModel(QAbstractItemModel *sourceModel) override; 0118 protected: 0119 bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; 0120 }; 0121 0122 class AccountNameValidator: public QValidator 0123 { 0124 Q_OBJECT 0125 Q_PROPERTY(QString issuer READ issuer WRITE setIssuer NOTIFY issuerChanged) 0126 Q_PROPERTY(model::SimpleAccountListModel * accounts READ accounts WRITE setAccounts NOTIFY accountsChanged) 0127 Q_PROPERTY( 0128 bool validateAvailability 0129 READ validateAvailability 0130 WRITE setValidateAvailability 0131 NOTIFY validateAvailabilityChanged 0132 ) 0133 public: 0134 explicit AccountNameValidator(QObject *parent = nullptr); 0135 QValidator::State validate(QString &input, int &pos) const override; 0136 void fixup(QString &input) const override; 0137 bool validateAvailability(void) const; 0138 void setValidateAvailability(bool enabled); 0139 QString issuer(void) const; 0140 void setIssuer(const QString &issuer); 0141 SimpleAccountListModel * accounts(void) const; 0142 void setAccounts(SimpleAccountListModel *accounts); 0143 Q_SIGNALS: 0144 void issuerChanged(void); 0145 void accountsChanged(void); 0146 void validateAvailabilityChanged(void); 0147 private: 0148 bool m_validateAvailability; 0149 std::optional<QString> m_issuer; 0150 SimpleAccountListModel * m_accounts; 0151 const validators::NameValidator m_delegate; 0152 }; 0153 } 0154 0155 Q_DECLARE_METATYPE(model::AccountView *); 0156 Q_DECLARE_METATYPE(model::SimpleAccountListModel *); 0157 0158 #endif