feature: added functionality to revoke api configs

This commit is contained in:
vladimir.kuznetsov 2025-02-20 13:44:19 +07:00
parent c2b17c128d
commit 95121c06e2
5 changed files with 234 additions and 25 deletions

View file

@ -73,7 +73,7 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode,
QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData);
apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode);
apiPayload[configKey::serverCountryCode] = apiConfigObject.value(configKey::serverCountryCode);
apiPayload[configKey::serverCountryCode] = serverCountryCode;
apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType);
apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData);
apiPayload[configKey::uuid] = m_settings->getInstallationUuid(true);
@ -92,6 +92,31 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode,
return true;
}
bool ApiConfigsController::revokeNativeConfig(const QString &serverCountryCode)
{
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString();
ApiPayloadData apiPayloadData = generateApiPayloadData(protocol);
QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData);
apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode);
apiPayload[configKey::serverCountryCode] = serverCountryCode;
apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType);
apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData);
QByteArray responseBody;
ErrorCode errorCode = gatewayController.post(QString("%1v1/revoke_native_config"), apiPayload, responseBody);
if (errorCode != ErrorCode::NoError) {
emit errorOccurred(errorCode);
return false;
}
return true;
}
void ApiConfigsController::prepareVpnKeyExport()
{
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
@ -285,6 +310,32 @@ bool ApiConfigsController::updateServiceFromTelegram(const int serverIndex)
return true;
}
bool ApiConfigsController::deactivateDevice()
{
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString();
ApiPayloadData apiPayloadData = generateApiPayloadData(protocol);
QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData);
apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode);
apiPayload[configKey::serverCountryCode] = apiConfigObject.value(configKey::serverCountryCode);
apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType);
apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData);
apiPayload[configKey::uuid] = m_settings->getInstallationUuid(true);
QByteArray responseBody;
ErrorCode errorCode = gatewayController.post(QString("%1v1/revoke_config"), apiPayload, responseBody);
if (errorCode != ErrorCode::NoError) {
emit errorOccurred(errorCode);
return false;
}
return true;
}
bool ApiConfigsController::isConfigValid()
{
int serverIndex = m_serversModel->getDefaultServerIndex();

View file

@ -19,6 +19,7 @@ public:
public slots:
bool exportNativeConfig(const QString &serverCountryCode, const QString &fileName);
bool revokeNativeConfig(const QString &serverCountryCode);
// bool exportVpnKey(const QString &fileName);
void prepareVpnKeyExport();
@ -27,6 +28,7 @@ public slots:
bool updateServiceFromGateway(const int serverIndex, const QString &newCountryCode, const QString &newCountryName,
bool reloadServiceConfig = false);
bool updateServiceFromTelegram(const int serverIndex);
bool deactivateDevice();
bool isConfigValid();

View file

@ -39,6 +39,9 @@ QVariant ApiCountryModel::data(const QModelIndex &index, int role) const
case CountryImageCodeRole: {
return countryInfo.countryCode.toUpper();
}
case IsIssuedRole: {
return isIssued;
}
}
return QVariant();
@ -103,5 +106,6 @@ QHash<int, QByteArray> ApiCountryModel::roleNames() const
roles[CountryNameRole] = "countryName";
roles[CountryCodeRole] = "countryCode";
roles[CountryImageCodeRole] = "countryImageCode";
roles[IsIssuedRole] = "isIssued";
return roles;
}

View file

@ -60,32 +60,152 @@ PageType {
text: countryName
leftImageSource: "qrc:/countriesFlags/images/flagKit/" + countryImageCode + ".svg"
rightImageSource: "qrc:/images/controls/download.svg"
rightImageSource: isIssued ? "qrc:/images/controls/more-vertical.svg" : "qrc:/images/controls/download.svg"
clickedFunction: function() {
var fileName = ""
if (GC.isMobile()) {
fileName = countryCode + configExtension
} else {
fileName = SystemController.getFileName(configCaption,
qsTr("Config files (*" + configExtension + ")"),
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/" + countryCode,
true,
configExtension)
}
if (fileName !== "") {
PageController.showBusyIndicator(true)
let result = ApiConfigsController.exportNativeConfig(countryCode, fileName)
PageController.showBusyIndicator(false)
if (result) {
PageController.showNotificationMessage(qsTr("Config file saved"))
}
if (isIssued) {
moreOptionsDrawer.countryName = countryName
moreOptionsDrawer.countryCode = countryCode
moreOptionsDrawer.openTriggered()
}
issueConfig(countryCode)
}
}
DividerType {}
}
}
DrawerType2 {
id: moreOptionsDrawer
property string countryName
property string countryCode
anchors.fill: parent
expandedHeight: parent.height * 0.4375
expandedStateContent: Item {
implicitHeight: moreOptionsDrawer.expandedHeight
BackButtonType {
id: moreOptionsDrawerBackButton
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 16
backButtonFunction: function() {
moreOptionsDrawer.closeTriggered()
}
}
FlickableType {
anchors.top: moreOptionsDrawerBackButton.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
contentHeight: moreOptionsDrawerContent.height
ColumnLayout {
id: moreOptionsDrawerContent
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
Header2Type {
Layout.fillWidth: true
Layout.margins: 16
headerText: qsTr("Configuration file ") + moreOptionsDrawer.countryName
}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Create a new")
descriptionText: qsTr("The previously created one will stop working")
clickedFunction: function() {
showQuestion(true, moreOptionsDrawer.countryCode, moreOptionsDrawer.countryName)
}
}
DividerType {}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Revoke the current configuration file")
clickedFunction: function() {
showQuestion(false, moreOptionsDrawer.countryCode, moreOptionsDrawer.countryName)
}
}
DividerType {}
}
}
}
}
function issueConfig(countryCode) {
var fileName = ""
if (GC.isMobile()) {
fileName = countryCode + configExtension
} else {
fileName = SystemController.getFileName(configCaption,
qsTr("Config files (*" + configExtension + ")"),
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/" + countryCode,
true,
configExtension)
}
if (fileName !== "") {
PageController.showBusyIndicator(true)
let result = ApiConfigsController.exportNativeConfig(countryCode, fileName)
if (result) {
ApiSettingsController.getAccountInfo()
}
PageController.showBusyIndicator(false)
if (result) {
PageController.showNotificationMessage(qsTr("Config file saved"))
}
}
}
function revokeConfig(countryCode) {
PageController.showBusyIndicator(true)
let result = ApiConfigsController.revokeNativeConfig(countryCode)
if (result) {
ApiSettingsController.getAccountInfo()
}
PageController.showBusyIndicator(false)
if (result) {
PageController.showNotificationMessage(qsTr("The config has been revoked"))
}
}
function showQuestion(isConfigIssue, countryCode, countryName) {
var headerText = qsTr("Revoke the actual %1 configuration file?").arg(countryName)
var descriptionText = qsTr("The previously created file will no longer be valid. It will not be possible to connect using it.")
var yesButtonText = qsTr("Continue")
var noButtonText = qsTr("Cancel")
var yesButtonFunction = function() {
if (isConfigIssue) {
issueConfig(countryCode)
} else {
revokeConfig(countryCode)
}
}
var noButtonFunction = function() {
}
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
}
}

View file

@ -257,10 +257,45 @@ PageType {
}
}
var noButtonFunction = function() {
if (!GC.isMobile()) {
removeButton.forceActiveFocus()
}
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
}
}
BasicButtonType {
id: revokeButton
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 24
Layout.bottomMargin: 16
Layout.leftMargin: 8
implicitHeight: 32
defaultColor: "transparent"
hoveredColor: AmneziaStyle.color.translucentWhite
pressedColor: AmneziaStyle.color.sheerWhite
textColor: AmneziaStyle.color.vibrantRed
text: qsTr("Deactivate the subscription on this device")
clickedFunc: function() {
var headerText = qsTr("Deactivate the subscription on this device?")
var yesButtonText = qsTr("Continue")
var noButtonText = qsTr("Cancel")
var yesButtonFunction = function() {
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
PageController.showNotificationMessage(qsTr("The next time the “Connect” button is pressed, the device will be activated again"))
} else {
PageController.showBusyIndicator(true)
if (ApiConfigsController.deactivateDevice()) {
ApiSettingsController.getAccountInfo()
}
PageController.showBusyIndicator(false)
}
}
var noButtonFunction = function() {
}
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
}
@ -295,9 +330,6 @@ PageType {
}
}
var noButtonFunction = function() {
if (!GC.isMobile()) {
removeButton.forceActiveFocus()
}
}
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)