1 /*
2 
3  * SPDX-FileCopyrightText: 2020 Alessandro Ambrosano <alessandro.ambrosano@gmail.com>
4  *
5  * SPDX-License-Identifier: LGPL-2.0-or-later
6  *
7  */
8 
9 #pragma once
10 
11 #include "ddpapi/ddpmanager.h"
12 #include "libruqolacore_export.h"
13 
14 #include <QJsonObject>
15 
16 class LIBRUQOLACORE_EXPORT DDPAuthenticationManager : public DDPManager
17 {
18     Q_OBJECT
19 
20     enum class Method {
21         Login,
22         SendOtp,
23         Logout,
24         LogoutCleanUp,
25     };
26 
27     static QString METHOD_LOGIN;
28     static QString METHOD_SEND_OTP;
29     static QString METHOD_LOGOUT;
30     static QString METHOD_LOGOUT_CLEAN_UP;
31 
32 public:
33     // state == LoginOngoing for all the time since the login request until a response
34     //   comes back, then it may result in
35     //   - LoggedIn
36     //   - LoginOtpRequired
37     //   - LoginFailedInvalidUserOrPassword
38     //   - GenericError
39     // state == LoginOtpAuthOngoing since when the otp code is sent to the server until
40     //  a response comes back, then it may become:
41     //   - LoggedIn
42     //   - LoginFailedInvalidOtp
43     //   - GenericError
44     // state == LogoutOngoing since the logout requet is sent until a response is received,
45     //   next states could be
46     //   - LoggedOut
47     //   - GenericError
48     // state == LogoutCleanUpOngoing since the clean up request is sent until a response is
49     //   received, resulting in one of these states:
50     //   - LoggedOutAndCleanedUp
51     //   - GenericError
52     // GenericError is used when the class doesn't know what else to do, and is irreversible
53     enum LoginStatus {
54         Connecting,
55         LoginOngoing,
56         LoggedIn,
57         LoginFailedInvalidUserOrPassword,
58         LoginOtpRequired,
59         LoginOtpAuthOngoing,
60         LoginFailedInvalidOtp,
61         LogoutOngoing,
62         LoggedOut,
63         LogoutCleanUpOngoing,
64         LoggedOutAndCleanedUp,
65         FailedToLoginPluginProblem,
66         GenericError,
67     };
68     Q_ENUM(LoginStatus)
69 
70     explicit DDPAuthenticationManager(DDPClient *ddpClient, QObject *parent = nullptr);
71     ~DDPAuthenticationManager() override;
72 
73     void login();
74     void login(const QString &user, const QString &password);
75     void loginLDAP(const QString &user, const QString &password); // TODO: LDAP options?
76     void loginOAuth(const QString &credentialToken, const QString &credentialSecret);
77     void sendOTP(const QString &otp);
78     void logout();
79 
80     void setAuthToken(const QString &authToken);
81 
82     Q_REQUIRED_RESULT QString userId() const;
83     Q_REQUIRED_RESULT QString authToken() const;
84     Q_REQUIRED_RESULT bool isLoggedIn() const;
85     Q_REQUIRED_RESULT bool isLoggedOut() const;
86     Q_REQUIRED_RESULT LoginStatus loginStatus() const;
87     void setLoginStatus(LoginStatus newStatus);
88 
89     Q_REQUIRED_RESULT qint64 tokenExpires() const;
90 
91 Q_SIGNALS:
92     void loginStatusChanged();
93 
94 private:
95     QString mUserId;
96     QString mAuthToken;
97     qint64 mTokenExpires;
98     LoginStatus mLoginStatus = LoggedOut;
99     // Used when sending OTP
100     QJsonObject mLastLoginPayload;
101 
102     void processMethodResponseImpl(int operationId, const QJsonObject &response) override;
103 
104     // Authentication doesn't involve any subscriptions
processSubscriptionResultImpl(int subscriptionId,const QJsonObject & result)105     void processSubscriptionResultImpl(int subscriptionId, const QJsonObject &result) override
106     {
107         Q_UNUSED(subscriptionId)
108         Q_UNUSED(result)
109     }
110 
111     void loginImpl(const QJsonArray &params);
112     void clientConnectedChangedSlot();
113     Q_REQUIRED_RESULT bool checkGenericError() const;
114 };
115