source: main/waeup.kofa/trunk/src/waeup/kofa/students/webservices.py @ 10960

Last change on this file since 10960 was 10521, checked in by Henrik Bettermann, 11 years ago

Add webservice which can be used to update user data and enroll user in Moodle courses via webservices.

  • Property svn:keywords set to Id
File size: 8.0 KB
RevLine 
[10033]1## $Id: webservices.py 10521 2013-08-21 20:52:03Z henrik $
2##
3## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import grok
[10042]19import xmlrpclib
[10038]20from zope.component import getUtility, queryUtility
[10033]21from zope.catalog.interfaces import ICatalog
[10042]22from waeup.kofa.interfaces import IUniversity, IExtFileStore
[10033]23
[10502]24
[10041]25def get_student(students, identifier):
26    if identifier is None:
27        return None
28    student = students.get(identifier, None)
29    if student is None:
30        cat = queryUtility(ICatalog, name='students_catalog')
31        results = list(
32            cat.searchResults(matric_number=(identifier, identifier)))
33        if len(results) == 1:
34            student = results[0]
35        else:
36            results = list(
37                cat.searchResults(reg_number=(identifier, identifier)))
38            if len(results) == 1:
39                student = results[0]
40    return student
[10033]41
42#class XMLRPCPermission(grok.Permission):
43#    """Permission for using XMLRPC functions.
44#    """
45#    grok.name('waeup.xmlrpc')
46
47#class XMLRPCUsers2(grok.Role):
48#    """Usergroup 2
49#    """
50#    grok.name('waeup.xmlrpcusers2')
51#    grok.title('XMLRPC Users Group 2')
52#    grok.permissions('waeup.xmlrpc',)
53
[10502]54
[10033]55class StudentsXMLRPC(grok.XMLRPC):
56    """Student related XMLRPC webservices.
57
58    Please note, that XMLRPC does not support real keyword arguments
59    but positional arguments only.
60    """
61
62    grok.context(IUniversity)
63
64    @grok.require('waeup.xmlrpc')
65    def get_student_id(self, reg_number=None):
66        """Get the id of a student with registration number `reg_number`.
67
68        Returns the student id as string if successful, ``None`` else.
69        """
70        if reg_number is not None:
71            cat = getUtility(ICatalog, name='students_catalog')
72            result = list(
73                cat.searchResults(reg_number=(reg_number, reg_number),
74                                  _limit=1))
75            if not len(result):
76                return None
77            return result[0].student_id
78        return None
[10036]79
80    @grok.require('waeup.xmlrpc')
[10041]81    def get_courses_by_session(self, identifier=None, session=None):
[10043]82        """1. What COURSES are registered by student X in session Y?
[10036]83
84        """
[10041]85        students = self.context['students']
86        student = get_student(students, identifier)
87        if student is None:
[10036]88            return None
89        try:
90            session = int(session)
91        except (TypeError, ValueError):
92            pass
93        sessionsearch = True
94        if session in (None, ''):
95            sessionsearch = False
96        studycourse = student['studycourse']
97        coursetickets = {}
98        for level in studycourse.values():
99            if sessionsearch and level.level_session != session:
100                continue
101            for ct in level.values():
102                coursetickets.update(
103                    {"%s|%s" % (level.level, ct.code): ct.title})
104        if not coursetickets:
105            return None
106        return coursetickets
[10038]107
108    @grok.require('waeup.xmlrpc')
109    def get_students_by_course(self, course=None, session=None):
[10043]110        """2. What STUDENTS registered (student id / matric no)
[10044]111        for course Z in session Y and did they pay school fee?
[10038]112
113        """
114        try:
115            session = int(session)
116        except (TypeError, ValueError):
117            pass
118        sessionsearch = True
119        if session in (None, ''):
120            sessionsearch = False
121        cat = queryUtility(ICatalog, name='coursetickets_catalog')
122        if sessionsearch:
123            coursetickets = cat.searchResults(
124                session=(session, session),
125                code=(course, course))
126        else:
127            coursetickets = cat.searchResults(
128                code=(course, course))
129        if not coursetickets:
130            return None
131        hitlist = []
[10044]132        for c_ticket in coursetickets:
133            amount = 0
134            for p_ticket in c_ticket.student['payments'].values():
135                if p_ticket.p_state == 'paid' and \
136                    p_ticket.p_category == 'schoolfee' and \
137                    p_ticket.p_session == c_ticket.__parent__.level_session:
138                    amount = p_ticket.amount_auth
[10040]139            hitlist.append((
[10044]140                c_ticket.student.student_id,
141                c_ticket.student.matric_number,
142                c_ticket.__parent__.validated_by,
143                amount
144                ))
[10038]145        return list(set(hitlist))
[10042]146
147    @grok.require('waeup.xmlrpc')
148    def get_student_info(self, identifier=None):
[10043]149        """3a. Who is the student with matriculation number / student id
[10042]150
151        """
152        students = self.context['students']
153        student = get_student(students, identifier)
154        if student is None:
155            return None
156        return [student.display_fullname, student.certcode,
157            student.phone, student.email]
158
159    @grok.require('waeup.xmlrpc')
160    def get_student_passport(self, identifier=None):
[10043]161        """3b. Get passport picture of student with
162        matriculation number / student id.
[10042]163
164        """
165        students = self.context['students']
166        student = get_student(students, identifier)
167        if student is None:
168            return None
169        img = getUtility(IExtFileStore).getFileByContext(
170            student, attr='passport.jpg')
171        return xmlrpclib.Binary(img.read())
[10043]172
173    @grok.require('waeup.xmlrpc')
174    def get_paid_sessions(self, identifier=None):
175        """6. Get list of SESSIONS school fees paid by student X.
176
177        """
178        students = self.context['students']
179        student = get_student(students, identifier)
180        if student is None:
181            return None
182        payments_dict = {}
183        for ticket in student['payments'].values():
184            if ticket.p_state == 'paid' and \
185                ticket.p_category == 'schoolfee':
186                payments_dict[str(ticket.p_session)] = ticket.amount_auth
187        if not payments_dict:
188            return None
189        return payments_dict
[10477]190
191    @grok.require('waeup.xmlrpc')
[10505]192    def check_student_credentials(self, username, password):
[10477]193        """Returns student data if username and password are valid,
194        None else.
195
196        We only query the students authenticator plugin in order not
197        to mix up with other credentials (admins, staff, etc.).
198
199        All additional checks performed by usual student
200        authentication apply. For instance for suspended students we
201        won't get a successful response but `None`.
202
203        This method can be used by CAS to authentify students for
204        external systems like moodle.
205        """
206        from zope.pluggableauth.interfaces import IAuthenticatorPlugin
207        auth = getUtility(IAuthenticatorPlugin, name='students')
208        creds = dict(login=username, password=password)
209        principal = auth.authenticateCredentials(creds)
210        if principal is None:
211            return None
212        return dict(email=principal.email, id=principal.id,
213                    type=principal.user_type,
214                    description=principal.description)
[10508]215
216    @grok.require('waeup.xmlrpc')
[10516]217    def get_student_moodle_data(self, identifier=None):
[10521]218        """Returns student data to update user data and enroll user
219        in Moodle courses.
[10508]220
221        """
222        students = self.context['students']
223        student = get_student(students, identifier)
224        if student is None:
225            return None
226        return dict(email=student.email,
227                    firstname=student.firstname,
228                    lastname=student.lastname,
229                    )
Note: See TracBrowser for help on using the repository browser.