import { Injectable, Inject } from "@angular/core"; import { Http, Response, Headers } from "@angular/http"; import "rxjs/add/operator/toPromise"; class Cookies { // cookies doesn't work with Android default browser / Ionic private session_id: string = null; delete_sessionId() { this.session_id = null; document.cookie = "session_id=; expires=Wed, 29 Jun 2016 00:00:00 UTC"; } get_sessionId() { return document .cookie.split("; ") .filter(x => { return x.indexOf("session_id") === 0; }) .map(x => { return x.split("=")[1]; }) .pop() || this.session_id || ""; } set_sessionId(val: string) { document.cookie = `session_id=${val}`; this.session_id = val; } } @Injectable() export class OdooRPCService { private odoo_server: string; private http_auth: string; private cookies: Cookies; private uniq_id_counter: number = 0; private shouldManageSessionId: boolean = false; // try without first private context: Object = JSON.parse(localStorage.getItem("user_context")) || {"lang": "en_US"}; private headers: Headers; constructor( @Inject(Http) private http: Http) { this.cookies = new Cookies(); } private buildRequest(url: string, params: any) { this.uniq_id_counter += 1; if (this.shouldManageSessionId) { params.session_id = this.cookies.get_sessionId(); } let json_data = { jsonrpc: "2.0", method: "call", params: params, // payload }; this.headers = new Headers({ "Content-Type": "application/json", "X-Openerp-Session-Id": this.cookies.get_sessionId(), "Authorization": "Basic " + btoa(`${this.http_auth}`) }); return JSON.stringify({ jsonrpc: "2.0", method: "call", params: params, // payload }); } private handleOdooErrors(response: any) { response = response.json(); if (!response.error) { return response.result; } let error = response.error; let errorObj = { title: " ", message: "", fullTrace: error }; if (error.code === 200 && error.message === "Odoo Server Error" && error.data.name === "werkzeug.exceptions.NotFound") { errorObj.title = "page_not_found"; errorObj.message = "HTTP Error"; } else if ( (error.code === 100 && error.message === "Odoo Session Expired") || // v8 (error.code === 300 && error.message === "OpenERP WebClient Error" && error.data.debug.match("SessionExpiredException")) // v7 ) { errorObj.title = "session_expired"; this.cookies.delete_sessionId(); } else if ( (error.message === "Odoo Server Error" && /FATAL: database "(.+)" does not exist/.test(error.data.message))) { errorObj.title = "database_not_found"; errorObj.message = error.data.message; } else if ( (error.data.name === "openerp.exceptions.AccessError")) { errorObj.title = "AccessError"; errorObj.message = error.data.message; } else { let split = ("" + error.data.fault_code).split("\n")[0].split(" -- "); if (split.length > 1) { error.type = split.shift(); error.data.fault_code = error.data.fault_code.substr(error.type.length + 4); } if (error.code === 200 && error.type) { errorObj.title = error.type; errorObj.message = error.data.fault_code.replace(/\n/g, "
"); } else { errorObj.title = error.message; errorObj.message = error.data.debug.replace(/\n/g, "
"); } } return Promise.reject(errorObj); } private handleHttpErrors(error: any) { return Promise.reject(error.message || error); } public init(configs: any) { this.odoo_server = configs.odoo_server; this.http_auth = configs.http_auth || null; } public setOdooServer(odoo_server: string) { this.odoo_server = odoo_server; } public setHttpAuth(http_auth: string) { this.http_auth = http_auth; } public sendRequest(url: string, params: Object): Promise { let options = this.buildRequest(url, params); return this.http.post(this.odoo_server + url, options, {headers: this.headers}) .toPromise() .then(this.handleOdooErrors) .catch(this.handleHttpErrors); } public getServerInfo() { return this.sendRequest("/web/webclient/version_info", {}); } public getSessionInfo() { return this.sendRequest("/web/session/get_session_info", {}); } public login(db: string, login: string, password: string) { let params = { db : db, login : login, password : password }; let $this = this; return this.sendRequest("/web/session/authenticate", params).then(function(result: any) { if (!result.uid) { $this.cookies.delete_sessionId(); return Promise.reject({ title: "wrong_login", message: "Username and password don't match", fullTrace: result }); } $this.context = result.user_context; localStorage.setItem("user_context", JSON.stringify($this.context)); $this.cookies.set_sessionId(result.session_id); return result; }); } public isLoggedIn(force: boolean = true) { if (!force) { return Promise.resolve(this.cookies.get_sessionId().length > 0); } return this.getSessionInfo().then((result: any) => { this.cookies.set_sessionId(result.session_id); return !!(result.uid); }); } public logout(force: boolean = true) { this.cookies.delete_sessionId(); if (force) { return this.getSessionInfo().then((r: any) => { // get db from sessionInfo if (r.db) return this.login(r.db, "", ""); }); }else { return Promise.resolve(); } } public getDbList() { // only use for odoo < 9.0 return this.sendRequest("/web/database/get_list", {}); } public searchRead(model: string, domain: any, fields: any) { let params = { model: model, domain: domain, fields: fields, context: this.context }; return this.sendRequest("/web/dataset/search_read", params); } public updateContext(context: any) { localStorage.setItem("user_context", JSON.stringify(context)); let args = [[(this.context).uid], context]; this.call("res.users", "write", args, {}) .then(()=>this.context = context) .catch((err: any) => this.context = context); } public getContext() { return this.context; } public call(model: string, method: string, args: any, kwargs: any) { kwargs = kwargs || {}; kwargs.context = kwargs.context || {}; Object.assign(kwargs.context, this.context); let params = { model: model, method: method, args: args, kwargs: kwargs, }; return this.sendRequest("/web/dataset/call_kw", params); } }