diff --git a/zengine/messaging/model.py b/zengine/messaging/model.py index 9fe3a1fa..2bbbc7d6 100644 --- a/zengine/messaging/model.py +++ b/zengine/messaging/model.py @@ -56,32 +56,32 @@ class Channel(Model): code_name = field.String("Internal name") description = field.String("Description") owner = UserModel(reverse_name='created_channels', null=True) - - class Managers(ListNode): - user = UserModel() + # + # class Managers(ListNode): + # user = UserModel() @classmethod - def get_or_create_direct_channel(cls, initiator, receiver): + def get_or_create_direct_channel(cls, initiator_key, receiver_key): """ Creates a direct messaging channel between two user Args: - initiator: User, who sent the first message + initiator: User, who want's to make first contact receiver: User, other party Returns: Channel """ existing = cls.objects.OR().filter( - code_name='%s_%s' % (initiator.key, receiver.key)).filter( - code_name='%s_%s' % (receiver.key, initiator.key)) + code_name='%s_%s' % (initiator_key, receiver_key)).filter( + code_name='%s_%s' % (receiver_key, initiator_key)) if existing: return existing[0] else: - channel_name = '%s_%s' % (initiator.key, receiver.key) + channel_name = '%s_%s' % (initiator_key, receiver_key) channel = cls(is_direct=True, code_name=channel_name).save() - Subscriber(channel=channel, user=initiator).save() - Subscriber(channel=channel, user=receiver).save() + Subscriber(channel=channel, user_id=initiator_key).save() + Subscriber(channel=channel, user_id=receiver_key).save() return channel @classmethod @@ -151,6 +151,7 @@ class Subscriber(Model): is_muted = field.Boolean("Mute the channel", default=False) inform_me = field.Boolean("Inform when I'm mentioned", default=True) is_visible = field.Boolean("Show under user's channel list", default=True) + can_manage = field.Boolean("Can manage this channel", default=False) can_leave = field.Boolean("Membership is not obligatory", default=True) last_seen_msg_time = field.DateTime("Last seen message's time") diff --git a/zengine/messaging/views.py b/zengine/messaging/views.py index 9e392641..dd93f10d 100644 --- a/zengine/messaging/views.py +++ b/zengine/messaging/views.py @@ -12,6 +12,7 @@ from zengine.views.base import BaseView UserModel = get_object_from_path(settings.USER_MODEL) +UnitModel = get_object_from_path(settings.UNIT_MODEL) def create_message(current): @@ -42,7 +43,7 @@ def create_message(current): """ msg = current.input['message'] - ch = Channel.objects.get(msg['channel']) + ch = Channel(current).objects.get(msg['channel']) msg_obj = ch.add_message(body=msg['body'], typ=msg['typ'], sender=current.user, title=msg['title'], receiver=msg['receiver'] or None) if 'attachment' in msg: @@ -95,7 +96,7 @@ def show_channel(current): }] } """ - ch = Channel.objects.get(current.input['channel_key']) + ch = Channel(current).objects.get(current.input['channel_key']) current.output = {'channel_key': current.input['channel_key'], 'description': ch.description, 'no_of_members': len(ch.subscriber_set), @@ -129,7 +130,7 @@ def last_seen_msg(current): 'code': 200, } """ - Subscriber.objects.filter(channel_id=current.input['channel_key'], + Subscriber(current).objects.filter(channel_id=current.input['channel_key'], user_id=current.user_id ).update(last_seen_msg_time=current.input['timestamp']) @@ -167,9 +168,9 @@ def list_channels(current): current.user.subscriptions if sbs.is_visible] -def create_public_channel(current): +def create_channel(current): """ - Create a public chat room + Create a public channel. Can be a broadcast channel or normal chat room. .. code-block:: python @@ -200,7 +201,7 @@ def create_public_channel(current): def add_members(current): """ - Add member(s) to a public chat room + Add member(s) to a channel .. code-block:: python @@ -221,7 +222,44 @@ def add_members(current): """ newly_added, existing = [], [] for member_key in current.input['members']: - sb, new = Subscriber.objects.get_or_create(user_id=member_key, + sb, new = Subscriber(current).objects.get_or_create(user_id=member_key, + channel_id=current.input['channel_key']) + if new: + newly_added.append(member_key) + else: + existing.append(member_key) + + current.output = { + 'existing': existing, + 'newly_added': newly_added, + 'status': 'OK', + 'code': 201 + } + + +def add_unit_to_channel(current): + """ + Subscribe users of a given unit to a channel + + .. code-block:: python + + # request: + { + 'view':'_zops_add_unit_to_channel, + 'unit_key': key, + } + + # response: + { + 'existing': [key,], # existing members + 'newly_added': [key,], # newly added members + 'status': 'Created', + 'code': 201 + } + """ + newly_added, existing = [], [] + for member_key in current.input['members']: + sb, new = Subscriber(current).objects.get_or_create(user_id=member_key, channel_id=current.input['channel_key']) if new: newly_added.append(member_key) @@ -260,26 +298,67 @@ def search_user(current): 'status': 'OK', 'code': 201 } - for user in UserModel.objects.search_on(settings.MESSAGING_USER_SEARCH_FIELDS, + for user in UserModel(current).objects.search_on(settings.MESSAGING_USER_SEARCH_FIELDS, contains=current.input['query']): current.input['results'].append((user.full_name, user.key, user.avatar)) +def search_unit(current): + """ + Search units for subscribing it's users to a channel + .. code-block:: python -def create_direct_channel(current): - """ - Create a One-To-One channel for current user and selected user. + # request: + { + 'view':'_zops_search_unit, + 'query': string, + } + # response: + { + 'results': [('name', 'key'), ], + 'status': 'OK', + 'code': 200 + } """ - pass + current.output = { + 'results': [], + 'status': 'OK', + 'code': 201 + } + for user in UnitModel(current).objects.search_on(settings.MESSAGING_UNIT_SEARCH_FIELDS, + contains=current.input['query']): + current.input['results'].append((user.name, user.key)) + + -def create_broadcast_channel(current): +def create_direct_channel(current): """ - Create a One-To-One channel for current user and selected user. + Create a One-To-One channel between current and selected user. + + .. code-block:: python + + # request: + { + 'view':'_zops_create_direct_channel, + 'user_key': key, + } + + # response: + { + 'status': 'Created', + 'code': 201, + 'channel_key': key, # of just created channel + } """ - pass + channel = Channel.get_or_create_direct_channel(current.user_id, current.input['user_key']) + current.output = { + 'channel_key': channel.key, + 'status': 'OK', + 'code': 201 + } def find_message(current): diff --git a/zengine/models/auth.py b/zengine/models/auth.py index 986595da..4c83051c 100644 --- a/zengine/models/auth.py +++ b/zengine/models/auth.py @@ -7,11 +7,35 @@ # This file is licensed under the GNU General Public License v3 # (GPLv3). See LICENSE.txt for details. -from pyoko import Model, field, ListNode +from pyoko import Model, field, ListNode, LinkProxy from passlib.hash import pbkdf2_sha512 from zengine.messaging.lib import BaseUser +class Unit(Model): + """Unit model + + Can be used do group users according to their physical or organizational position + + """ + name = field.String("İsim", index=True) + parent = LinkProxy('Unit', verbose_name='Parent Unit', reverse_name='sub_units') + + class Meta: + verbose_name = "Unit" + verbose_name_plural = "Units" + search_fields = ['name'] + list_fields = ['name',] + + def __unicode__(self): + return '%s' % self.name + + @classmethod + def get_user_keys(cls, current, unit_key): + return User(current).objects.filter(unit_id=unit_key).values_list('key', flatten=True) + + + class Permission(Model): """ Permission model @@ -50,6 +74,7 @@ class User(Model, BaseUser): password = field.String("Password") superuser = field.Boolean("Super user", default=False) avatar = field.File("Avatar", random_name=True, required=False) + unit = Unit() class Meta: """ meta class @@ -72,7 +97,6 @@ def get_permissions(self): users_primary_role = self.role_set[0].role return users_primary_role.get_permissions() - class Role(Model): """ This model binds group of Permissions with a certain User. diff --git a/zengine/settings.py b/zengine/settings.py index b7c1cbbd..9d8d7547 100644 --- a/zengine/settings.py +++ b/zengine/settings.py @@ -36,6 +36,9 @@ #: Role model ROLE_MODEL = 'zengine.models.Role' +#: Unit model +UNIT_MODEL = 'zengine.models.Unit' + MQ_HOST = os.getenv('MQ_HOST', 'localhost') MQ_PORT = int(os.getenv('MQ_PORT', '5672')) MQ_USER = os.getenv('MQ_USER', 'guest') @@ -198,3 +201,6 @@ #: User search method of messaging subsystem will work on these fields MESSAGING_USER_SEARCH_FIELDS = ['username', 'name', 'surname'] +#: Unit search method of messaging subsystem will work on these fields +MESSAGING_UNIT_SEARCH_FIELDS = ['name',] +