From 39099700fe55aace45ef2fe080ed346c26080e66 Mon Sep 17 00:00:00 2001 From: Ralph Soika Date: Fri, 25 Apr 2025 09:52:50 +0200 Subject: [PATCH] zoho token management --- .../zoho/ZohoController.java | 14 ++ .../zoho/ZohoOAuthManager.java | 151 +++++++++++------- .../src/main/webapp/pages/admin/zoho.xhtml | 65 ++++++-- 3 files changed, 162 insertions(+), 68 deletions(-) diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoController.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoController.java index d32068c..6f7675d 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoController.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoController.java @@ -71,4 +71,18 @@ public class ZohoController extends ConfigController { this.getWorkitem().setItemValue("message", message); } } + + /** + * Ruft zohoOAuhtManager.refreshToken auf + */ + public void refreshAccessToken() { + // + try { + zohoOAuthManager.refreshAccessToken(); + } catch (PluginException e) { + String message = "Failed to refresh token: " + e.getMessage(); + logger.warning(message); + this.getWorkitem().setItemValue("message", message); + } + } } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthManager.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthManager.java index 90b46b3..36d3d79 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthManager.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/zoho/ZohoOAuthManager.java @@ -8,6 +8,7 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.time.Duration; +import java.util.Date; import java.util.logging.Logger; import org.imixs.workflow.ItemCollection; @@ -56,6 +57,11 @@ public class ZohoOAuthManager { this.jsonb = JsonbBuilder.create(); } + @Lock(LockType.READ) + public String getValidAccessToken() { + return accessToken; + } + /** * Step 3: Generate Access and Refresh Token * @@ -112,19 +118,8 @@ public class ZohoOAuthManager { TokenResponse tokenResponse = jsonb.fromJson(response.body(), TokenResponse.class); + saveTokenData(zohoConfig, tokenResponse); - accessToken = tokenResponse.getAccess_token(); - - logger.info("│ ├── accessToken=" + accessToken); - refreshToken = tokenResponse.getRefresh_token(); - logger.info("│ ├── refreshToken=" + refreshToken); - logger.info("│ ├── expires_in=" + tokenResponse.getExpires_in()); - - zohoConfig.setItemValue("zoho.accessToken", accessToken); - zohoConfig.setItemValue("zoho.refreshToken", refreshToken); - zohoConfig.setItemValue("zoho.expires", tokenResponse.getExpires_in()); - zohoConfig.setItemValue("message", "Access Token OK"); - configService.save(zohoConfig); } else { throw new RuntimeException("Failed to get tokens: " + response.statusCode() + " - " + response.body()); @@ -136,65 +131,111 @@ public class ZohoOAuthManager { } } - @Lock(LockType.READ) - public String getValidAccessToken() { - - return null; - } - /** * This method updates the Access Token based on the current Refresh Token * * @throws IOException + * @throws PluginException */ - public void testRefreshAccessToken() throws IOException { + @Lock(LockType.WRITE) + public void refreshAccessToken() throws PluginException { - // logger.info("├── refresh Zoho access token"); - // refreshToken = - // "1000.cf458816e97f848df8134ce1c7e923a1.5b9dbdee317e35d7f0c619e7648d55ff"; - // try { + logger.info("├── refresh Zoho access token"); - // String requestUrl = "https://accounts.zoho.eu/oauth/v2/token" + - // "?refresh_token=" + URLEncoder.encode(refreshToken, StandardCharsets.UTF_8) + - // "&client_id=" + URLEncoder.encode(clientID.get(), StandardCharsets.UTF_8) + - // "&client_secret=" + URLEncoder.encode(clientSecret.get(), - // StandardCharsets.UTF_8) + - // "&grant_type=refresh_token"; + ItemCollection zohoConfig = configService.loadConfiguration(ZohoController.ZOHO_CONFIGURATION); - // logger.info("│ ├── Request URI=" + requestUrl); + String clientID = zohoConfig.getItemValueString("zoho.clientid"); + String clientSecret = zohoConfig.getItemValueString("zoho.clientsecret"); - // HttpRequest request = HttpRequest.newBuilder() - // .uri(URI.create(requestUrl)) - // .header("Content-Type", "application/x-www-form-urlencoded") - // .POST(HttpRequest.BodyPublishers.noBody()) // Wichtig: Kein Body! - // .build(); + refreshToken = zohoConfig.getItemValueString("zoho.refreshToken"); + try { - // HttpResponse response; + String requestUrl = "https://accounts.zoho.eu/oauth/v2/token" + + "?refresh_token=" + URLEncoder.encode(refreshToken, StandardCharsets.UTF_8) + + "&client_id=" + URLEncoder.encode(clientID, StandardCharsets.UTF_8) + + "&client_secret=" + URLEncoder.encode(clientSecret, + StandardCharsets.UTF_8) + + + "&grant_type=refresh_token"; - // response = httpClient.send(request, - // HttpResponse.BodyHandlers.ofString()); + logger.info("│ ├── Request URI=" + requestUrl); - // logger.info("│ ├── Response statusCode=" + response.statusCode()); - // if (response.statusCode() == 200) { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(requestUrl)) + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(HttpRequest.BodyPublishers.noBody()) // Wichtig: Kein Body! + .build(); - // // 1. Response-Logging für Debugging - // logger.info("│ ├── Response Body=" + response.body()); + HttpResponse response; - // TokenResponse tokenResponse = jsonb.fromJson(response.body(), - // TokenResponse.class); + response = httpClient.send(request, + HttpResponse.BodyHandlers.ofString()); - // String accessToken = tokenResponse.getAccess_token(); - // logger.info("│ ├── accessToken=" + accessToken); - // logger.info("│ ├── expires_in=" + tokenResponse.getExpires_in()); - // } else { - // throw new RuntimeException("Failed to get tokens: " + - // response.statusCode() + " - " + response.body()); - // } + logger.info("│ ├── Response statusCode=" + response.statusCode()); + if (response.statusCode() == 200) { - // } catch (IOException | InterruptedException e) { - // throw new InvalidAccessException("Unable to resolve access tokens: " + - // e.getMessage()); - // } + // 1. Response-Logging für Debugging + logger.info("│ ├── Response Body=" + response.body()); + + TokenResponse tokenResponse = jsonb.fromJson(response.body(), + TokenResponse.class); + + saveTokenData(zohoConfig, tokenResponse); + + // String accessToken = tokenResponse.getAccess_token(); + // logger.info("│ ├── accessToken=" + accessToken); + // logger.info("│ ├── expires_in=" + tokenResponse.getExpires_in()); + } else { + throw new RuntimeException("Failed to get tokens: " + + response.statusCode() + " - " + response.body()); + } + + } catch (IOException | InterruptedException e) { + throw new PluginException(ZohoOAuthManager.class.getSimpleName(), + ZohoOAuthManager.ERROR_CONFIG, "Unable to refresh access tokens: " + e.getMessage()); + } } + + /** + * Helper method to update the config itemcolleciton based on a tokenResponse + * + * @param zohoConfig + * @param tokenResponse + */ + private void saveTokenData(ItemCollection zohoConfig, TokenResponse tokenResponse) { + + String apiDomain = tokenResponse.getApi_domain(); + if (apiDomain != null && !apiDomain.isEmpty()) { + logger.info("│ ├── apiDomain=" + apiDomain); + zohoConfig.setItemValue("zoho.apiDomain", apiDomain); + } + String scope = tokenResponse.getScope(); + if (scope != null && !scope.isEmpty()) { + logger.info("│ ├── scope=" + scope); + zohoConfig.setItemValue("zoho.scope", scope); + } + + accessToken = tokenResponse.getAccess_token(); + if (accessToken != null && !accessToken.isEmpty()) { + logger.info("│ ├── accessToken=" + accessToken); + zohoConfig.setItemValue("zoho.accessToken", accessToken); + } + refreshToken = tokenResponse.getRefresh_token(); + if (refreshToken != null && !refreshToken.isEmpty()) { + logger.info("│ ├── refreshToken=" + refreshToken); + zohoConfig.setItemValue("zoho.refreshToken", refreshToken); + } + logger.info("│ ├── expires_in=" + tokenResponse.getExpires_in()); + // Expires-Zeit in Millisekunden berechnen + long expiresInSeconds = tokenResponse.getExpires_in() - 60; + long currentTimeMillis = System.currentTimeMillis(); + long expiresTimeMillis = currentTimeMillis + (expiresInSeconds * 1000); + // Expires-Zeit in ein Date-Objekt konvertieren + Date expiresDate = new Date(expiresTimeMillis); + zohoConfig.setItemValue("zoho.expires", expiresDate); + zohoConfig.setItemValue("message", "Access Token OK"); + configService.save(zohoConfig); + } + } diff --git a/office-alexander-logistics-app/src/main/webapp/pages/admin/zoho.xhtml b/office-alexander-logistics-app/src/main/webapp/pages/admin/zoho.xhtml index f137890..7e1112e 100644 --- a/office-alexander-logistics-app/src/main/webapp/pages/admin/zoho.xhtml +++ b/office-alexander-logistics-app/src/main/webapp/pages/admin/zoho.xhtml @@ -81,7 +81,6 @@

Fordern Sie einen ZOHO API COde an -

  1. Melden Sie sich auf der ZOHO API Console an
  2. @@ -94,8 +93,8 @@
  3. Generieren Sie einen neuen Access Code
    - Scope:
    - ZohoBooks.invoices.CREATE,ZohoBooks.invoices.READ,ZohoBooks.invoices.UPDATE,ZohoBooks.invoices.DELETE + Scope: + ZohoBooks.invoices.CREATE,ZohoBooks.invoices.READ,ZohoBooks.invoices.UPDATE
  4. Code über den Button "Create" anfordern und in das Feld "Access Code" @@ -107,20 +106,60 @@
+ value="Token generieren"> + + - -
- -
- AccessToken: - -
- RefreshToken: -

+ +
+

Status: + +

+ + + + + + + + + + + + + + + + + + + + + +
API Domain: + +
Scope: + +
AccessToken: + +
+ RefreshToken: + + +
+ Expires: + + +