keysmith/src/model/accounts.h

151 lines
5.3 KiB
C++

/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
*/
#ifndef MODEL_ACCOUNTS_H
#define MODEL_ACCOUNTS_H
#include "input.h"
#include "../account/account.h"
#include "../validators/namevalidator.h"
#include <QAbstractListModel>
#include <QByteArray>
#include <QHash>
#include <QModelIndex>
#include <QObject>
#include <QSortFilterProxyModel>
#include <QString>
#include <QValidator>
#include <QVector>
#include <optional>
namespace model
{
qint64 millisecondsLeftForToken(const QDateTime &epoch, uint timeStep,
const std::function<qint64(void)> &clock = &QDateTime::currentMSecsSinceEpoch);
class AccountView : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QString issuer READ issuer CONSTANT)
Q_PROPERTY(QString token READ token NOTIFY tokenChanged)
Q_PROPERTY(quint64 counter READ counter NOTIFY tokenChanged);
Q_PROPERTY(uint timeStep READ timeStep CONSTANT);
Q_PROPERTY(bool isHotp READ isHotp CONSTANT);
Q_PROPERTY(bool isTotp READ isTotp CONSTANT);
public:
explicit AccountView(accounts::Account *model, QObject *parent = nullptr);
QString name(void) const;
QString issuer(void) const;
QString token(void) const;
uint timeStep(void) const;
quint64 counter(void) const;
bool isHotp(void) const;
bool isTotp(void) const;
Q_INVOKABLE qint64 millisecondsLeftForToken(void) const;
Q_SIGNALS:
void tokenChanged(void);
void remove(void);
void recompute(void);
void advanceCounter(quint64 by = 1ULL);
void setCounter(quint64 value);
private:
accounts::Account * const m_model;
};
class SimpleAccountListModel: public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged);
Q_PROPERTY(bool error READ error WRITE setError NOTIFY errorChanged);
public:
enum NonStandardRoles {
AccountRole = Qt::ItemDataRole::UserRole
};
Q_ENUM(NonStandardRoles)
enum TOTPAlgorithms {
Sha1, Sha256, Sha512
};
Q_ENUM(TOTPAlgorithms)
private:
static accounts::Account::Hash toHash(const TOTPAlgorithms value);
public:
explicit SimpleAccountListModel(accounts::AccountStorage *storage, QObject *parent = nullptr);
Q_INVOKABLE void addAccount(model::AccountInput *input);
Q_INVOKABLE bool isAccountStillAvailable(const QString &name, const QString &issuer) const;
Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const override;
Q_INVOKABLE QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames(void) const override;
public:
bool loaded(void) const;
bool error(void) const;
void setError(bool markAsError);
Q_SIGNALS:
void loadedChanged(void);
void errorChanged(void);
private Q_SLOTS:
void added(const QString &account);
void removed(const QString &removed);
void handleError(void);
private:
AccountView * createView(const QString &name);
void populate(const QString &name, AccountView *account);
private:
accounts::AccountStorage * const m_storage;
private:
bool m_has_error;
QVector<QString> m_index;
QHash<QString, AccountView*> m_accounts;
};
class SortedAccountsListModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit SortedAccountsListModel(QObject *parent = nullptr);
void setSourceModel(QAbstractItemModel *sourceModel) override;
protected:
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
};
class AccountNameValidator: public QValidator
{
Q_OBJECT
Q_PROPERTY(QString issuer READ issuer WRITE setIssuer NOTIFY issuerChanged)
Q_PROPERTY(model::SimpleAccountListModel * accounts READ accounts WRITE setAccounts NOTIFY accountsChanged);
Q_PROPERTY(
bool validateAvailability
READ validateAvailability
WRITE setValidateAvailability
NOTIFY validateAvailabilityChanged
);
public:
explicit AccountNameValidator(QObject *parent = nullptr);
QValidator::State validate(QString &input, int &pos) const override;
void fixup(QString &input) const override;
bool validateAvailability(void) const;
void setValidateAvailability(bool enabled);
QString issuer(void) const;
void setIssuer(const QString &issuer);
SimpleAccountListModel * accounts(void) const;
void setAccounts(SimpleAccountListModel *accounts);
Q_SIGNALS:
void issuerChanged(void);
void accountsChanged(void);
void validateAvailabilityChanged(void);
private:
bool m_validateAvailability;
std::optional<QString> m_issuer;
SimpleAccountListModel * m_accounts;
const validators::NameValidator m_delegate;
};
}
Q_DECLARE_METATYPE(model::AccountView *);
Q_DECLARE_METATYPE(model::SimpleAccountListModel *);
#endif