Skip to content

Commit 07d8ae0

Browse files
committed
[FIX] gmail: circular dependencies and string refs
There are a few circular dependencies in the code which can result in functions being called before they are actually defined in ES/6 import order. Lots of models just use the state to get a global property. We replace these with access to the property directly, as the models don't actually need to access the state otherwise. The circular dependencies inside views are less problematic as the view builders should only be called from the index in the first place. And because we do not refer to any static data in the view builders. As actions cannot accept anything but strings as parameter, the only fix for these circular imports is to have a registry and reference the index from the registry. However this introduce otherwise pointless indirection so we leave things as they are for now. ---------------------------- Additionally, this commit replaces hard-coded strings for function references inside actions with a reference to the name of the function object. This helps avoid issues when functions are modified, ensure the import order is correct and helps with avoiding these functions from being marked as unused by linters and compilers. task-3329768
1 parent bb405e0 commit 07d8ae0

24 files changed

+128
-116
lines changed

gmail/src/models/lead.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { postJsonRpc } from "../utils/http";
22
import { isTrue } from "../utils/format";
33
import { URLS } from "../const";
4-
import { State } from "../models/state";
4+
import { getAccessToken } from "src/services/odoo_auth";
55

66
/**
77
* Represent a "crm.lead" record.
@@ -19,8 +19,8 @@ export class Lead {
1919
* and return the ID of the newly created record.
2020
*/
2121
static createLead(partnerId: number, emailBody: string, emailSubject: string): number {
22-
const url = State.odooServerUrl + URLS.CREATE_LEAD;
23-
const accessToken = State.accessToken;
22+
const url = PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL") + URLS.CREATE_LEAD;
23+
const accessToken = getAccessToken();
2424

2525
const response = postJsonRpc(
2626
url,

gmail/src/models/partner.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import { Task } from "./task";
44
import { Ticket } from "./ticket";
55
import { postJsonRpc, postJsonRpcCached } from "../utils/http";
66
import { URLS } from "../const";
7-
import { State } from "../models/state";
87
import { ErrorMessage } from "../models/error_message";
8+
import { getAccessToken } from "src/services/odoo_auth";
9+
import { getOdooServerUrl } from "src/services/app_properties";
910

1011
/**
1112
* Represent the current partner and all the information about him.
@@ -88,8 +89,8 @@ export class Partner {
8889
* See `getPartner`
8990
*/
9091
static enrichPartner(email: string, name: string): [Partner, number[], boolean, boolean, ErrorMessage] {
91-
const odooServerUrl = State.odooServerUrl;
92-
const odooAccessToken = State.accessToken;
92+
const odooServerUrl = getOdooServerUrl();
93+
const odooAccessToken = getAccessToken();
9394

9495
if (odooServerUrl && odooAccessToken) {
9596
return this.getPartner(email, name);
@@ -104,7 +105,7 @@ export class Partner {
104105
* to find information about the company.
105106
*/
106107
static _enrichFromIap(email: string, name: string): [Partner, ErrorMessage] {
107-
const odooSharedSecret = State.odooSharedSecret;
108+
const odooSharedSecret = PropertiesService.getScriptProperties().getProperty("ODOO_SHARED_SECRET");
108109
const userEmail = Session.getEffectiveUser().getEmail();
109110

110111
const senderDomain = email.split("@").pop();
@@ -137,11 +138,11 @@ export class Partner {
137138
* Create a "res.partner" with the given values in the Odoo database.
138139
*/
139140
static savePartner(partnerValues: any): number {
140-
const url = State.odooServerUrl + URLS.PARTNER_CREATE;
141-
const accessToken = State.accessToken;
141+
const url = PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL") + URLS.PARTNER_CREATE;
142+
const odooAccessToken = getAccessToken();
142143

143144
const response = postJsonRpc(url, partnerValues, {
144-
Authorization: "Bearer " + accessToken,
145+
Authorization: "Bearer " + odooAccessToken,
145146
});
146147

147148
return response && response.id;
@@ -162,13 +163,13 @@ export class Partner {
162163
name: string,
163164
partnerId: number = null,
164165
): [Partner, number[], boolean, boolean, ErrorMessage] {
165-
const url = State.odooServerUrl + URLS.GET_PARTNER;
166-
const accessToken = State.accessToken;
166+
const url = PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL") + URLS.GET_PARTNER;
167+
const odooAccessToken = getAccessToken();
167168

168169
const response = postJsonRpc(
169170
url,
170171
{ email: email, name: name, partner_id: partnerId },
171-
{ Authorization: "Bearer " + accessToken },
172+
{ Authorization: "Bearer " + odooAccessToken },
172173
);
173174

174175
if (!response || !response.partner) {
@@ -214,10 +215,10 @@ export class Partner {
214215
* Perform a search on the Odoo database and return the list of matched partners.
215216
*/
216217
static searchPartner(query: string): [Partner[], ErrorMessage] {
217-
const url = State.odooServerUrl + URLS.SEARCH_PARTNER;
218-
const accessToken = State.accessToken;
218+
const url = PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL") + URLS.SEARCH_PARTNER;
219+
const odooAccessToken = getAccessToken();
219220

220-
const response = postJsonRpc(url, { search_term: query }, { Authorization: "Bearer " + accessToken });
221+
const response = postJsonRpc(url, { search_term: query }, { Authorization: "Bearer " + odooAccessToken });
221222

222223
if (!response || !response.partners) {
223224
return [[], new ErrorMessage("http_error_odoo")];
@@ -241,10 +242,10 @@ export class Partner {
241242
}
242243

243244
static _enrichOrCreateCompany(partnerId: number, endpoint: string): [Company, ErrorMessage] {
244-
const url = State.odooServerUrl + endpoint;
245-
const accessToken = State.accessToken;
245+
const url = PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL") + endpoint;
246+
const odooAccessToken = getAccessToken();
246247

247-
const response = postJsonRpc(url, { partner_id: partnerId }, { Authorization: "Bearer " + accessToken });
248+
const response = postJsonRpc(url, { partner_id: partnerId }, { Authorization: "Bearer " + odooAccessToken });
248249

249250
if (!response) {
250251
return [null, new ErrorMessage("http_error_odoo")];

gmail/src/models/project.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { postJsonRpc } from "../utils/http";
22
import { URLS } from "../const";
33
import { ErrorMessage } from "../models/error_message";
4-
import { State } from "../models/state";
4+
import { getAccessToken } from "src/services/odoo_auth";
55

66
/**
77
* Represent a "project.project" record.
@@ -37,10 +37,10 @@ export class Project {
3737
* Make a RPC call to the Odoo database to search a project.
3838
*/
3939
static searchProject(query: string): [Project[], ErrorMessage] {
40-
const url = State.odooServerUrl + URLS.SEARCH_PROJECT;
41-
const accessToken = State.accessToken;
40+
const url = PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL") + URLS.SEARCH_PROJECT;
41+
const odooAccessToken = getAccessToken();
4242

43-
const response = postJsonRpc(url, { search_term: query }, { Authorization: "Bearer " + accessToken });
43+
const response = postJsonRpc(url, { search_term: query }, { Authorization: "Bearer " + odooAccessToken });
4444

4545
if (!response) {
4646
return [[], new ErrorMessage("http_error_odoo")];
@@ -54,10 +54,10 @@ export class Project {
5454
* and return the newly created record.
5555
*/
5656
static createProject(name: string): Project {
57-
const url = State.odooServerUrl + URLS.CREATE_PROJECT;
58-
const accessToken = State.accessToken;
57+
const url = PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL") + URLS.CREATE_PROJECT;
58+
const odooAccessToken = getAccessToken();
5959

60-
const response = postJsonRpc(url, { name: name }, { Authorization: "Bearer " + accessToken });
60+
const response = postJsonRpc(url, { name: name }, { Authorization: "Bearer " + odooAccessToken });
6161

6262
const projectId = response ? response.project_id || null : null;
6363
if (!projectId) {

gmail/src/models/state.ts

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Project } from "./project";
55
import { Lead } from "./lead";
66
import { ErrorMessage } from "./error_message";
77
import { getAccessToken, getOdooAuthUrl } from "../services/odoo_auth";
8+
import { getOdooServerUrl } from "src/services/app_properties";
89

910
/**
1011
* Object which contains all data for the application.
@@ -136,24 +137,6 @@ export class State {
136137
const loginUrl = getOdooAuthUrl();
137138
return isTrue(loginUrl);
138139
}
139-
140-
/**
141-
* Return the base URL of the Odoo database.
142-
*/
143-
static get odooServerUrl(): string {
144-
const userProperties = PropertiesService.getUserProperties();
145-
const serverUrl = userProperties.getProperty("ODOO_SERVER_URL");
146-
return isTrue(serverUrl);
147-
}
148-
149-
/**
150-
* Change the base URL of the Odoo database.
151-
*/
152-
static set odooServerUrl(value: string) {
153-
const userProperties = PropertiesService.getUserProperties();
154-
userProperties.setProperty("ODOO_SERVER_URL", value);
155-
}
156-
157140
/**
158141
* Return the shared secret between the add-on and IAP
159142
* (which is used to authenticate the add-on to IAP).
@@ -179,7 +162,7 @@ export class State {
179162
*/
180163
static getLoggingState(messageId: string) {
181164
const cache = CacheService.getUserCache();
182-
const loggingStateStr = cache.get("ODOO_LOGGING_STATE_" + this.odooServerUrl + "_" + messageId);
165+
const loggingStateStr = cache.get("ODOO_LOGGING_STATE_" + getOdooServerUrl() + "_" + messageId);
183166

184167
const defaultValues: Record<string, number[]> = {
185168
partners: [],
@@ -208,7 +191,7 @@ export class State {
208191
const cache = CacheService.getUserCache();
209192

210193
// The cache key depend on the current email open and on the Odoo database
211-
const cacheKey = "ODOO_LOGGING_STATE_" + this.odooServerUrl + "_" + messageId;
194+
const cacheKey = "ODOO_LOGGING_STATE_" + getOdooServerUrl() + "_" + messageId;
212195

213196
cache.put(
214197
cacheKey,

gmail/src/models/task.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { postJsonRpc } from "../utils/http";
22
import { URLS } from "../const";
3-
import { State } from "../models/state";
3+
import { getAccessToken } from "src/services/odoo_auth";
44

55
/**
66
* Represent a "project.task" record.
@@ -37,13 +37,13 @@ export class Task {
3737
* and return the ID of the newly created record.
3838
*/
3939
static createTask(partnerId: number, projectId: number, emailBody: string, emailSubject: string): Task {
40-
const url = State.odooServerUrl + URLS.CREATE_TASK;
41-
const accessToken = State.accessToken;
40+
const url = PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL") + URLS.CREATE_TASK;
41+
const odooAccessToken = getAccessToken();
4242

4343
const response = postJsonRpc(
4444
url,
4545
{ email_subject: emailSubject, email_body: emailBody, project_id: projectId, partner_id: partnerId },
46-
{ Authorization: "Bearer " + accessToken },
46+
{ Authorization: "Bearer " + odooAccessToken },
4747
);
4848

4949
const taskId = response ? response.task_id || null : null;

gmail/src/models/ticket.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { postJsonRpc } from "../utils/http";
22
import { URLS } from "../const";
3-
import { State } from "../models/state";
3+
import { getAccessToken } from "src/services/odoo_auth";
44

55
/**
66
* Represent a "helpdesk.ticket" record.
@@ -14,13 +14,13 @@ export class Ticket {
1414
* and return the ID of the newly created record.
1515
*/
1616
static createTicket(partnerId: number, emailBody: string, emailSubject: string): number {
17-
const url = State.odooServerUrl + URLS.CREATE_TICKET;
18-
const accessToken = State.accessToken;
17+
const url = PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL") + URLS.CREATE_TICKET;
18+
const odooAccessToken = getAccessToken();
1919

2020
const response = postJsonRpc(
2121
url,
2222
{ email_body: emailBody, email_subject: emailSubject, partner_id: partnerId },
23-
{ Authorization: "Bearer " + accessToken },
23+
{ Authorization: "Bearer " + odooAccessToken },
2424
);
2525

2626
return response ? response.ticket_id || null : null;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export function getOdooServerUrl() {
2+
return PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL");
3+
}
4+
export function setOdooServerUrl(url: string) {
5+
PropertiesService.getUserProperties().setProperty("ODOO_SERVER_URL", url);
6+
}

gmail/src/services/log_email.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { postJsonRpc } from "../utils/http";
22
import { escapeHtml } from "../utils/html";
33
import { URLS } from "../const";
44
import { Email } from "../models/email";
5-
import { State } from "../models/state";
65
import { ErrorMessage } from "../models/error_message";
76
import { _t } from "../services/translation";
7+
import { getAccessToken } from "./odoo_auth";
88

99
/**
1010
* Format the email body before sending it to Odoo.
@@ -37,15 +37,15 @@ function _formatEmailBody(email: Email, error: ErrorMessage): string {
3737
* Log the given email body in the chatter of the given record.
3838
*/
3939
export function logEmail(recordId: number, recordModel: string, email: Email): ErrorMessage {
40-
const accessToken = State.accessToken;
40+
const odooAccessToken = getAccessToken();
4141
const [attachments, error] = email.getAttachments();
4242
const body = _formatEmailBody(email, error);
43-
const url = State.odooServerUrl + URLS.LOG_EMAIL;
43+
const url = PropertiesService.getUserProperties().getProperty("ODOO_SERVER_URL") + URLS.LOG_EMAIL;
4444

4545
const response = postJsonRpc(
4646
url,
4747
{ message: body, res_id: recordId, model: recordModel, attachments: attachments },
48-
{ Authorization: "Bearer " + accessToken },
48+
{ Authorization: "Bearer " + odooAccessToken },
4949
);
5050

5151
if (!response) {

gmail/src/services/odoo_auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export function getOdooAuthUrl() {
9393
throw new Error("Can not retrieve the script ID.");
9494
}
9595

96-
const stateToken = ScriptApp.newStateToken().withMethod("odooAuthCallback").withTimeout(3600).createToken();
96+
const stateToken = ScriptApp.newStateToken().withMethod(odooAuthCallback.name).withTimeout(3600).createToken();
9797

9898
const redirectToAddon = `https://script.google.com/macros/d/${scriptId}/usercallback`;
9999
const scope = ODOO_AUTH_URLS.SCOPE;

gmail/src/services/translation.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { postJsonRpc } from "../utils/http";
2-
import { State } from "../models/state";
32
import { URLS } from "../const";
3+
import { getAccessToken } from "./odoo_auth";
4+
import { getOdooServerUrl } from "./app_properties";
45

56
/**
67
* Object which fetchs the translations on the Odoo database, puts them in cache.
@@ -17,15 +18,17 @@ export class Translate {
1718

1819
const translationsStr = cache.get(cacheKey);
1920

21+
const odooServerUrl = getOdooServerUrl();
22+
const odooAccessToken = getAccessToken();
2023
if (translationsStr) {
2124
this.translations = JSON.parse(translationsStr);
22-
} else if (State.odooServerUrl && State.accessToken) {
25+
} else if (odooServerUrl && odooAccessToken) {
2326
Logger.log("Download translations...");
2427

2528
this.translations = postJsonRpc(
26-
State.odooServerUrl + URLS.GET_TRANSLATIONS,
29+
odooServerUrl + URLS.GET_TRANSLATIONS,
2730
{},
28-
{ Authorization: "Bearer " + State.accessToken },
31+
{ Authorization: "Bearer " + odooAccessToken },
2932
);
3033

3134
if (this.translations) {

0 commit comments

Comments
 (0)