From 8f33049f2fbe2e109a4f75d3e33953abd4e506c9 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 26 Aug 2013 10:45:54 +0200 Subject: [PATCH 1/4] Changed user field to user_id and added unique constraint bzr revid: nicolas.vanhoren@openerp.com-20130826084554-221ts80q8c5jvqv1 --- addons/im/im.py | 25 +++++++++++++++---------- addons/im/static/src/js/im.js | 2 +- addons/im/static/src/js/im_common.js | 4 ++-- addons/im_livechat/im_livechat.py | 16 ++++++++-------- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/addons/im/im.py b/addons/im/im.py index 97860d33e0a..710fd1760fe 100644 --- a/addons/im/im.py +++ b/addons/im/im.py @@ -230,12 +230,12 @@ class im_user(osv.osv): def get_by_user_ids(self, cr, uid, ids, context=None): user_ids = [x for x in ids if isinstance(x, int)] uuids = [x for x in ids if isinstance(x, (str, unicode))] - users = self.search(cr, openerp.SUPERUSER_ID, ["|", ["user", "in", user_ids], ["uuid", "in", uuids]], context=None) - records = self.read(cr, openerp.SUPERUSER_ID, users, ["user", "uuid"], context=None) + users = self.search(cr, openerp.SUPERUSER_ID, ["|", ["user_id", "in", user_ids], ["uuid", "in", uuids]], context=None) + records = self.read(cr, openerp.SUPERUSER_ID, users, ["user_id", "uuid"], context=None) inside = {} for i in records: - if i["user"]: - inside[i["user"][0]] = True + if i["user_id"]: + inside[i["user_id"][0]] = True elif ["uuid"]: inside[i["uuid"]] = True not_inside = {} @@ -244,8 +244,8 @@ class im_user(osv.osv): not_inside[i] = True for to_create in not_inside.keys(): if isinstance(to_create, int): - created = self.create(cr, openerp.SUPERUSER_ID, {"user": to_create}, context=context) - records.append({"id": created, "user": [to_create, ""]}) + created = self.create(cr, openerp.SUPERUSER_ID, {"user_id": to_create}, context=context) + records.append({"id": created, "user_id": [to_create, ""]}) else: created = self.create(cr, openerp.SUPERUSER_ID, {"uuid": to_create}, context=context) records.append({"id": created, "uuid": to_create}) @@ -261,16 +261,16 @@ class im_user(osv.osv): res = {} for record in self.browse(cr, uid, ids, context=context): res[record.id] = record.assigned_name - if record.user: - res[record.id] = record.user.name + if record.user_id: + res[record.id] = record.user_id.name continue return res _columns = { 'name': fields.function(_get_name, type='char', size=200, string="Name", store=True, readonly=True), 'assigned_name': fields.char(string="Assigned Name", size=200, required=False), - 'image': fields.related('user', 'image_small', type='binary', string="Image", readonly=True), - 'user': fields.many2one("res.users", string="User", select=True, ondelete='cascade'), + 'image': fields.related('user_id', 'image_small', type='binary', string="Image", readonly=True), + 'user_id': fields.many2one("res.users", string="User", select=True, ondelete='cascade'), 'uuid': fields.char(string="UUID", size=50, select=True), 'im_last_received': fields.integer(string="Instant Messaging Last Received Message"), 'im_last_status': fields.boolean(strint="Instant Messaging Last Status"), @@ -283,3 +283,8 @@ class im_user(osv.osv): 'im_last_status': False, 'im_last_status_update': lambda *args: datetime.datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT), } + + _sql_constraints = [ + ('user_uniq', 'unique (user_id)', 'Only one chat user per OpenERP user.'), + ('uuid_uniq', 'unique (uuid)', 'Chat identifier already used.'), + ] diff --git a/addons/im/static/src/js/im.js b/addons/im/static/src/js/im.js index 9af04bf4f43..6af9b27c804 100644 --- a/addons/im/static/src/js/im.js +++ b/addons/im/static/src/js/im.js @@ -87,7 +87,7 @@ var self = this; return this.user_search_dm.add(users.call("search_users", [[["name", "ilike", this.get("current_search")], ["id", "<>", instance.session.uid]], - ["name", "user", "uuid", "im_status"], USERS_LIMIT], {context:new instance.web.CompoundContext()})).then(function(result) { + ["name", "user_id", "uuid", "im_status"], USERS_LIMIT], {context:new instance.web.CompoundContext()})).then(function(result) { self.c_manager.add_to_user_cache(result); self.$(".oe_im_input").val(""); var old_users = self.users; diff --git a/addons/im/static/src/js/im_common.js b/addons/im/static/src/js/im_common.js index a6314a978e2..bf89bccddcb 100644 --- a/addons/im/static/src/js/im_common.js +++ b/addons/im/static/src/js/im_common.js @@ -35,8 +35,8 @@ function declare($, _, openerp) { user_rec.image_url = im_common.connection.url("/im/static/src/img/avatar/avatar.jpeg"); // TODO : check it works correctly - if (user_rec.user) - user_rec.image_url = im_common.connection.url('/web/binary/image', {model:'res.users', field: 'image_small', id: user_rec.user[0]}); + if (user_rec.user_id) + user_rec.image_url = im_common.connection.url('/web/binary/image', {model:'res.users', field: 'image_small', id: user_rec.user_id[0]}); /*if (user_rec.image) user_rec.image_url = "data:image/png;base64," + user_rec.image;*/ diff --git a/addons/im_livechat/im_livechat.py b/addons/im_livechat/im_livechat.py index b68a0079c3a..cce8f49e84b 100644 --- a/addons/im_livechat/im_livechat.py +++ b/addons/im_livechat/im_livechat.py @@ -206,12 +206,12 @@ class im_message(osv.osv): res = {} for record in self.browse(cr, uid, ids, context=context): res[record.id] = False - if record.to_id.user and record.from_id.user: + if record.to_id.user_id and record.from_id.user_id: continue - elif record.to_id.user: - res[record.id] = record.to_id.user.id - elif record.from_id.user: - res[record.id] = record.from_id.user.id + elif record.to_id.user_id: + res[record.id] = record.to_id.user_id.id + elif record.from_id.user_id: + res[record.id] = record.from_id.user_id.id return res def _customer(self, cr, uid, ids, name, arg, context=None): @@ -230,11 +230,11 @@ class im_message(osv.osv): res = {} for record in self.browse(cr, uid, ids, context=context): res[record.id] = False - if not not record.to_id.user and not not record.from_id.user: + if not not record.to_id.user_id and not not record.from_id.user_id: continue - elif not not record.to_id.user: + elif not not record.to_id.user_id: res[record.id] = "c2s" - elif not not record.from_id.user: + elif not not record.from_id.user_id: res[record.id] = "s2c" return res From 7bce27c528f4c5aaf9838eff2803d3ecd68228b0 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 26 Aug 2013 10:52:12 +0200 Subject: [PATCH 2/4] Now uses im.user's images bzr revid: nicolas.vanhoren@openerp.com-20130826085212-od9oxv6h4jtkd6nf --- addons/im/static/src/js/im_common.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/addons/im/static/src/js/im_common.js b/addons/im/static/src/js/im_common.js index bf89bccddcb..6cfad3538ca 100644 --- a/addons/im/static/src/js/im_common.js +++ b/addons/im/static/src/js/im_common.js @@ -32,13 +32,8 @@ function declare($, _, openerp) { im_common.ImUser = openerp.Class.extend(openerp.PropertiesMixin, { init: function(parent, user_rec) { openerp.PropertiesMixin.init.call(this, parent); - user_rec.image_url = im_common.connection.url("/im/static/src/img/avatar/avatar.jpeg"); - - // TODO : check it works correctly - if (user_rec.user_id) - user_rec.image_url = im_common.connection.url('/web/binary/image', {model:'res.users', field: 'image_small', id: user_rec.user_id[0]}); - /*if (user_rec.image) - user_rec.image_url = "data:image/png;base64," + user_rec.image;*/ + + user_rec.image_url = im_common.connection.url('/web/binary/image', {model:'im.user', field: 'image', id: user_rec.id}); this.set(user_rec); this.set("watcher_count", 0); From 8ee25f9856880ed981f223dde6f2f30c8b5eb73e Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 26 Aug 2013 14:39:47 +0200 Subject: [PATCH 3/4] Refactored to avoid user duplication problem bzr revid: nicolas.vanhoren@openerp.com-20130826123947-alcsov647beqge0c --- addons/im/im.py | 54 +++++++------------ addons/im/security/im_security.xml | 8 +-- addons/im/static/src/js/im.js | 5 +- addons/im/static/src/js/im_common.js | 33 +++++------- addons/im_livechat/im_livechat.py | 4 +- addons/im_livechat/im_livechat_view.xml | 2 +- .../security/im_livechat_security.xml | 2 +- 7 files changed, 40 insertions(+), 68 deletions(-) diff --git a/addons/im/im.py b/addons/im/im.py index 710fd1760fe..261905c0dcc 100644 --- a/addons/im/im.py +++ b/addons/im/im.py @@ -109,7 +109,7 @@ class LongPollingController(http.Controller): registry = openerp.modules.registry.RegistryManager.get(db) with registry.cursor() as cr: registry.get('im.user').im_connect(cr, uid, uuid=uuid, context=request.context) - my_id = registry.get('im.user').get_by_user_id(cr, uid, uuid or uid, request.context)["id"] + my_id = registry.get('im.user').get_my_id(cr, uid, uuid, request.context) num = 0 while True: with registry.cursor() as cr: @@ -156,7 +156,7 @@ class im_message(osv.osv): # complex stuff to determine the last message to show users = self.pool.get("im.user") - my_id = users.get_by_user_id(cr, uid, uuid or uid, context=context)["id"] + my_id = users.get_my_id(cr, uid, uuid, context=context) c_user = users.browse(cr, openerp.SUPERUSER_ID, my_id, context=context) if last: if c_user.im_last_received < last: @@ -181,7 +181,7 @@ class im_message(osv.osv): def post(self, cr, uid, message, to_user_id, uuid=None, context=None): assert_uuid(uuid) - my_id = self.pool.get('im.user').get_by_user_id(cr, uid, uuid or uid)["id"] + my_id = self.pool.get('im.user').get_my_id(cr, uid, uuid) self.create(cr, openerp.SUPERUSER_ID, {"message": message, 'from_id': my_id, 'to_id': to_user_id}, context=context) notify_channel(cr, "im_channel", {'type': 'message', 'receiver': to_user_id}) return False @@ -199,10 +199,9 @@ class im_user(osv.osv): res[obj["id"]] = obj["im_last_status"] and (last_update + delta) > current return res - def search_users(self, cr, uid, domain, fields, limit, context=None): - # do not user openerp.SUPERUSER_ID, reserved to normal users - found = self.pool.get('res.users').search(cr, uid, domain, limit=limit, context=context) - found = self.get_by_user_ids(cr, uid, found, context=context) + def search_users(self, cr, uid, text_search, fields, limit, context=None): + my_id = self.get_my_id(cr, uid, None, context) + found = self.search(cr, uid, [["name", "ilike", text_search], ["id", "<>", my_id]], limit=limit, context=context) return self.read(cr, uid, found, fields, context=context) def im_connect(self, cr, uid, uuid=None, context=None): @@ -215,7 +214,7 @@ class im_user(osv.osv): def _im_change_status(self, cr, uid, new_one, uuid=None, context=None): assert_uuid(uuid) - id = self.get_by_user_id(cr, uid, uuid or uid, context=context)["id"] + id = self.get_my_id(cr, uid, uuid, context=context) current_status = self.read(cr, openerp.SUPERUSER_ID, id, ["im_status"], context=None)["im_status"] self.write(cr, openerp.SUPERUSER_ID, id, {"im_last_status": new_one, "im_last_status_update": datetime.datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)}, context=context) @@ -223,37 +222,20 @@ class im_user(osv.osv): notify_channel(cr, "im_channel", {'type': 'status', 'user': id}) return True - def get_by_user_id(self, cr, uid, id, context=None): - ids = self.get_by_user_ids(cr, uid, [id], context=context) - return ids[0] - - def get_by_user_ids(self, cr, uid, ids, context=None): - user_ids = [x for x in ids if isinstance(x, int)] - uuids = [x for x in ids if isinstance(x, (str, unicode))] - users = self.search(cr, openerp.SUPERUSER_ID, ["|", ["user_id", "in", user_ids], ["uuid", "in", uuids]], context=None) - records = self.read(cr, openerp.SUPERUSER_ID, users, ["user_id", "uuid"], context=None) - inside = {} - for i in records: - if i["user_id"]: - inside[i["user_id"][0]] = True - elif ["uuid"]: - inside[i["uuid"]] = True - not_inside = {} - for i in ids: - if not (i in inside): - not_inside[i] = True - for to_create in not_inside.keys(): - if isinstance(to_create, int): - created = self.create(cr, openerp.SUPERUSER_ID, {"user_id": to_create}, context=context) - records.append({"id": created, "user_id": [to_create, ""]}) - else: - created = self.create(cr, openerp.SUPERUSER_ID, {"uuid": to_create}, context=context) - records.append({"id": created, "uuid": to_create}) - return records + def get_my_id(self, cr, uid, uuid=None, context=None): + assert_uuid(uuid) + if uuid: + users = self.search(cr, openerp.SUPERUSER_ID, [["uuid", "=", uuid]], context=None) + else: + users = self.search(cr, openerp.SUPERUSER_ID, [["user_id", "=", uid]], context=None) + my_id = users[0] if len(users) >= 1 else False + if not my_id: + my_id = self.create(cr, openerp.SUPERUSER_ID, {"user_id": uid if not uuid else False, "uuid": uuid if uuid else False}, context=context) + return my_id def assign_name(self, cr, uid, uuid, name, context=None): assert_uuid(uuid) - id = self.get_by_user_id(cr, uid, uuid or uid, context=context)["id"] + id = self.get_my_id(cr, uid, uuid, context=context) self.write(cr, openerp.SUPERUSER_ID, id, {"assigned_name": name}, context=context) return True diff --git a/addons/im/security/im_security.xml b/addons/im/security/im_security.xml index 10297ac0669..a964855ccf9 100644 --- a/addons/im/security/im_security.xml +++ b/addons/im/security/im_security.xml @@ -5,7 +5,7 @@ Can only read messages that you sent or messages sent to you - ["|", ('to_id.user', '=', user.id), ('from_id.user', '=', user.id)] + ["|", ('to_id.user_id', '=', user.id), ('from_id.user_id', '=', user.id)] @@ -16,11 +16,11 @@ Can only modify your user - [('user', '=', user.id)] - + [('user_id', '=', user.id)] + - + diff --git a/addons/im/static/src/js/im.js b/addons/im/static/src/js/im.js index 6af9b27c804..63ab694a723 100644 --- a/addons/im/static/src/js/im.js +++ b/addons/im/static/src/js/im.js @@ -85,9 +85,8 @@ search_changed: function(e) { var users = new instance.web.Model("im.user"); var self = this; - return this.user_search_dm.add(users.call("search_users", - [[["name", "ilike", this.get("current_search")], ["id", "<>", instance.session.uid]], - ["name", "user_id", "uuid", "im_status"], USERS_LIMIT], {context:new instance.web.CompoundContext()})).then(function(result) { + return this.user_search_dm.add(users.call("search_users", [this.get("current_search"), ["name", "user_id", "uuid", "im_status"], + USERS_LIMIT], {context:new instance.web.CompoundContext()})).then(function(result) { self.c_manager.add_to_user_cache(result); self.$(".oe_im_input").val(""); var old_users = self.users; diff --git a/addons/im/static/src/js/im_common.js b/addons/im/static/src/js/im_common.js index 6cfad3538ca..a2b7683d324 100644 --- a/addons/im/static/src/js/im_common.js +++ b/addons/im/static/src/js/im_common.js @@ -92,34 +92,25 @@ function declare($, _, openerp) { }, start_polling: function() { var self = this; - - var auth_def = null; - var user_id = null; + var def = $.when(); + var uuid = false; if (this.options.anonymous_mode) { - var uuid = localStorage["oe_livesupport_uuid"]; - var def = $.when(uuid); + uuid = localStorage["oe_livesupport_uuid"] || false; if (! uuid) { - def = im_common.connection.rpc("/longpolling/im/gen_uuid", {}); + def = im_common.connection.rpc("/longpolling/im/gen_uuid", {}).then(function(my_uuid) { + uuid = my_uuid; + localStorage["oe_livesupport_uuid"] = uuid; + return im_common.connection.model("im.user").call("assign_name", [uuid, self.options.userName]); + }); } - var anonymous_user_id = null; - auth_def = def.then(function(uuid) { - localStorage["oe_livesupport_uuid"] = uuid; - return im_common.connection.model("im.user").call("get_by_user_id", [uuid]); - }).then(function(my_id) { - user_id = my_id["id"]; - return im_common.connection.model("im.user").call("assign_name", [uuid, self.options.userName]); - }); - } else { - auth_def = im_common.connection.model("im.user").call("get_by_user_id", - [im_common.connection.uid]).then(function(my_id) { - user_id = my_id["id"]; - }); } - return auth_def.then(function() { - self.my_id = user_id; + return def.then(function() { + return im_common.connection.model("im.user").call("get_my_id", [uuid]); + }).then(function(my_user_id) { + self.my_id = my_user_id; return self.ensure_users([self.my_id]); }).then(function() { var me = self.users_cache[self.my_id]; diff --git a/addons/im_livechat/im_livechat.py b/addons/im_livechat/im_livechat.py index cce8f49e84b..a47f87a9fd2 100644 --- a/addons/im_livechat/im_livechat.py +++ b/addons/im_livechat/im_livechat.py @@ -161,9 +161,9 @@ class im_livechat_channel(osv.osv): def get_available_user(self, cr, uid, channel_id, context=None): channel = self.browse(cr, openerp.SUPERUSER_ID, channel_id, context=context) + im_user_ids = self.pool.get("im.user").search(cr, uid, [["user_id", "in", [user.id for user in channel.user_ids]]], context=context) users = [] - for user in channel.user_ids: - iuid = self.pool.get("im.user").get_by_user_id(cr, uid, user.id, context=context)["id"] + for iuid in im_user_ids: imuser = self.pool.get("im.user").browse(cr, uid, iuid, context=context) if imuser.im_status: users.append(imuser) diff --git a/addons/im_livechat/im_livechat_view.xml b/addons/im_livechat/im_livechat_view.xml index f684fd561fc..65401f3b88f 100644 --- a/addons/im_livechat/im_livechat_view.xml +++ b/addons/im_livechat/im_livechat_view.xml @@ -124,7 +124,7 @@ History im.message list - ["|", ('to_id.user', '=', None), ('from_id.user', '=', None)] + ["|", ('to_id.user_id', '=', None), ('from_id.user_id', '=', None)] diff --git a/addons/im_livechat/security/im_livechat_security.xml b/addons/im_livechat/security/im_livechat_security.xml index 5ad020a8a78..9088d0ed3db 100644 --- a/addons/im_livechat/security/im_livechat_security.xml +++ b/addons/im_livechat/security/im_livechat_security.xml @@ -25,7 +25,7 @@ Live Support Managers can read messages from live support - ["|", ('to_id.user', '=', None), ('from_id.user', '=', None)] + ["|", ('to_id.user_id', '=', None), ('from_id.user_id', '=', None)] From 5e8315730b98ac42ffb454fe494628023a91eb4a Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 26 Aug 2013 14:52:54 +0200 Subject: [PATCH 4/4] Solved a few bugs bzr revid: nicolas.vanhoren@openerp.com-20130826125254-smlkkh5m3n36cklw --- addons/im/im.py | 2 +- addons/im/static/src/js/im_common.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/im/im.py b/addons/im/im.py index 261905c0dcc..534991b8fc8 100644 --- a/addons/im/im.py +++ b/addons/im/im.py @@ -201,7 +201,7 @@ class im_user(osv.osv): def search_users(self, cr, uid, text_search, fields, limit, context=None): my_id = self.get_my_id(cr, uid, None, context) - found = self.search(cr, uid, [["name", "ilike", text_search], ["id", "<>", my_id]], limit=limit, context=context) + found = self.search(cr, uid, [["name", "ilike", text_search], ["id", "<>", my_id], ["uuid", "=", False]], limit=limit, context=context) return self.read(cr, uid, found, fields, context=context) def im_connect(self, cr, uid, uuid=None, context=None): diff --git a/addons/im/static/src/js/im_common.js b/addons/im/static/src/js/im_common.js index a2b7683d324..9e5e13a9099 100644 --- a/addons/im/static/src/js/im_common.js +++ b/addons/im/static/src/js/im_common.js @@ -102,9 +102,11 @@ function declare($, _, openerp) { def = im_common.connection.rpc("/longpolling/im/gen_uuid", {}).then(function(my_uuid) { uuid = my_uuid; localStorage["oe_livesupport_uuid"] = uuid; - return im_common.connection.model("im.user").call("assign_name", [uuid, self.options.userName]); }); } + def = def.then(function() { + return im_common.connection.model("im.user").call("assign_name", [uuid, self.options.userName]); + }); } return def.then(function() {