root / lib / pyzinn / zone / client.py @ a899390a2a8aca3b3b4617dd7cd96a19e64b489c

View | Annotate | Download (9.2 KB)

1
# Copyright (c) 2009 Lost Oasis, IELO <info@ielo.net>
2
#
3
# This file is part of ZINN.
4
# 
5
# ZINN is free software: you can redistribute it and/or modify it under
6
# the terms of the GNU General Public License as published by the Free
7
# Software Foundation, either version 3 of the License, or (at your
8
# option) any later version.
9
# 
10
# ZINN is distributed in the hope that it will be useful, but WITHOUT
11
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13
# for more details.
14
# 
15
# You should have received a copy of the GNU General Public License
16
# along with ZINN.  If not, see <http://www.gnu.org/licenses/>.
17
18
import copy
19
import md5
20
from datetime import datetime, timedelta
21
import time
22
import formencode
23
import sqlobject
24
from sqlobject import *
25
from twisted.web import xmlrpc
26
from twisted.web.xmlrpc import *
27
28
import gettext
29
_ = gettext.gettext
30
31
import pyzinn.database as db
32
33
import role as site_role
34
35
from pysinn.site.abstract import service
36
from pyzinn.zone.abstract import client
37
38
class ClientInvitation(service.AService, object):
39
40
    def __init__(self, client):
41
        self.name = self.__class__.__name__
42
        self.db = db
43
        self.client = client
44
        super(ClientInvitation, self).__init__()
45
46
    def xmlrpc_create(self, label):
47
        # TODO: make it go in config file
48
        MAGIC_MD5 = 'this is a very magic string'
49
        self.client.user.raise_can_client(label)
50
        client = self.client.byLabel(label)
51
        m = md5.new(client.label)
52
        m.update(str(datetime.now()))
53
        m.update(MAGIC_MD5)
54
        key = m.hexdigest()
55
56
        try:
57
            db.Invitation(client=client, md5key=key)
58
        except formencode.Invalid, e:
59
            raise Fault(self.INVALID_ATTR, str(e))
60
        except dberrors.DuplicateEntryError:
61
            msg = _('Key already exists, try again')
62
            raise Fault(self.ALREADY_EXIST_ERROR, msg)
63
        else:
64
            try:
65
                i = db.Invitation.selectBy(md5key=key, client=client).getOne()
66
            except main.SQLObjectNotFound:
67
                raise Fault(self.INTERNAL_ERROR,
68
                        _('Key generation failed, try again'))
69
            else:
70
                return {'key': i.md5key, 'expiration':
71
                    time.mktime(i.expiration.timetuple())}
72
73
    xmlrpc_create.help = _("""
74
        Generate an invitation key for a given client.
75
76
        Invitation key principle is :
77
        1. One User U1 attached to a Client C create an invitation Key for this
78
        Client.
79
        2. U1 sends this generated Key to a User U2 (eg via email).
80
        3. U2 aknowledge the invitation whith the Key.
81
        4. Client C users can now see User U2. U2 has no rights at this time so
82
        U1 or another Client C user whith right permissions can give some
83
        credentials to U2.
84
85
        Returned array contains a struct compound of :
86
         - key : a md5 style string.
87
         - expiration : expiration date of the key.
88
89
        @param label: string label of the client.
90
91
        @see: client.invitation.acknowledge
92
        @see: client.invitation.list
93
94
        @return: array
95
    """)
96
    xmlrpc_create.signature = ['string', 'array']
97
98
    def xmlrpc_list(self, label):
99
        self.client.user.raise_can_client(label)
100
        client = self.client.byLabel(label)
101
        return [{'key' : i.md5key, 'expiration':
102
            time.mktime(i.expiration.timetuple())} for i in
103
            db.Invitation.select(sqlobject.AND(db.Invitation.q.clientID==client.id,
104
                        db.Invitation.q.expiration>datetime.now()))]
105
106
    xmlrpc_list.help = _("""
107
        List all invitation keys for a given client.
108
109
        Returned array contains a struct compound of :
110
         - key : a md5 style string.
111
         - expiration : expiration date of the key.
112
113
        @param label: string label of the client.
114
115
        @return: array
116
    """)
117
    xmlrpc_list.signature = ['string', 'array']
118
119
    def xmlrpc_acknowledge(self, key):
120
        try:
121
            i = db.Invitation.select(sqlobject.AND(db.Invitation.q.md5key==key,
122
                        db.Invitation.q.expiration>datetime.now())).getOne()
123
        except main.SQLObjectNotFound:
124
            raise Fault(self.NOT_FOUND, _('Key not found'))
125
126
        client = i.client
127
        for u, cu in client.users:
128
            if u.label == self.client.user.me.label:
129
                msg = _('User with %s already exist in client\'s user list')
130
                raise Fault(self.ALREADY_EXIST_ERROR, msg
131
                                                  % self.client.user.me.label)
132
        client.addUser(self.client.user.me)
133
        i.destroySelf()
134
135
        return client.label
136
137
    xmlrpc_acknowledge.help = _("""
138
        Acknowlegde an invitation with a key.
139
140
        Return the label of the client.
141
142
        @param key: string the invitation key.
143
144
        @return: string
145
    """)
146
    xmlrpc_acknowledge.signature = ['string', 'string']
147
148
class Client(client.AClient, object):
149
    def __init__(self):
150
        self.name = self.__class__.__name__
151
        self.db = db
152
        self.clientinvitation = ClientInvitation(self)
153
        super(Client, self).__init__()
154
        self.putSubHandler('invitation', self.clientinvitation)
155
156
    def xmlrpc_create(self, label, attributes=None):
157
        sg = None
158
        default = {
159
            'label' : label,
160
        }
161
        args = self.AttributesFilter(attributes, default)
162
        try:
163
            import pprint
164
            pprint.pprint(args)
165
            client = db.Client(**args)
166
            raise Fault(self.INTERNAL_ERROR, 'haaaaaaaaaaaaaaaaaaaaaaaaaaa')
167
            clientLabel = client.label
168
        except formencode.Invalid, e:
169
            raise Fault(self.INVALID_ATTR, str(e))
170
        except dberrors.DuplicateEntryError:
171
            msg = _('Client %s already exists.') % label
172
            raise Fault(self.ALREADY_EXIST_ERROR, msg)
173
174
        client = self.byLabel(clientLabel)
175
        try:
176
            role = site_role.Role().byLabel('%s,%s' % (client.label, 'owner'))
177
        except Fault, f:
178
            client.destroySelf()
179
            raise
180
        else:
181
            role.addUser(self.user.me)
182
            try:
183
                userrole = db.RoleUser.selectBy(role=role,
184
                        user=self.user.me).getOne()
185
            except main.SQLObjectNotFound:
186
                client.destroySelf()
187
                msg = _('Error creating client %s.') % label
188
                raise Fault(self.INTERNAL_ERROR, msg)
189
            else:
190
                userrole.isAdmin = True
191
192
    xmlrpc_create.__dict__ = copy.deepcopy(
193
            client.AClient.xmlrpc_create.__dict__
194
            )
195
196
    def xmlrpc_list(self, label=None):
197
        if not label:
198
            return [v.label for v in self.getAll() if (self.user.is_member_client(v)
199
                    or self.user.can_client(v))]
200
        else:
201
            self.user.raise_can_client(label)
202
            client = self.byLabel(label)
203
            d = {
204
                'vsites' : {},
205
                'roles'  : {},
206
                'users'  : [],
207
            }
208
            if client.vsites:
209
                for i in client.vsites:
210
                    d['vsites'][i.label] = {
211
                        'siteGroup' :   i.siteGroup.label
212
                    }
213
214
            if client.roles:
215
                for i in client.roles:
216
                    d['roles'][i.label] = {
217
                        'public' : i.public
218
                    }
219
            if client.users:
220
                for u, cu in client.users:
221
                    d['users'].append(u.label)
222
223
        for a in self.getAttributes(onlyMutables=False):
224
                d[a] = getattr(client, a)
225
        return [d]
226
227
    xmlrpc_list.__dict__ = copy.deepcopy(
228
            client.AClient.xmlrpc_list.__dict__
229
            )
230
231
    def xmlrpc_delete(self, label):
232
        self.user.raise_can_client(label)
233
        client = self.byLabel(label)
234
        if client.vsites:
235
            msg = _('Client %s in use by one or more vsite!')
236
            raise Fault(self.ALREADY_ATTACHED_ERROR, msg % label)
237
        for r in client.roles:
238
            if r.label != 'owner':
239
                msg = _('Client %s in use by one or more role!')
240
                raise Fault(self.ALREADY_ATTACHED_ERROR, msg % label)
241
        else:
242
            role = site_role.Role().byLabel('%s,%s' % (client.label, 'owner'))
243
            role.destroySelf()
244
            client.destroySelf()
245
246
    xmlrpc_delete.__dict__ = copy.deepcopy(
247
            client.AClient.xmlrpc_delete.__dict__
248
            )
249
250
    def xmlrpc_update(self, label, attributes=None):
251
        self.user.raise_can_client(label)
252
        client = self.byLabel(label)
253
        args = self.AttributesFilter(attributes)
254
        try:
255
            if args:
256
                client.set(**args)
257
        except formencode.Invalid, e:
258
            raise Fault(self.INVALID_ATTR, str(e))
259
        except Exception, e:
260
            raise Fault(self.UPDATE_EXCEPTION, str(e))
261
262
    xmlrpc_update.__dict__ = copy.deepcopy(
263
            client.AClient.xmlrpc_update.__dict__
264
            )
265
266
    def xmlrpc_attributes(self, onlyMutables=False):
267
        return self.getAttributes(onlyMutables)
268
    xmlrpc_attributes.__dict__ = copy.deepcopy(
269
            client.AClient.xmlrpc_attributes.__dict__
270
            )
271
272
# vim: tabstop=4 expandtab shiftwidth=4 textwidth=79