summaryrefslogtreecommitdiff
path: root/wsgi_server.py
blob: 0f70b400e820a0e8c9140310143168e127bc7e5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/python3
# coding=utf-8

import falcon
import json
import client
from errors.session import NoSuchSession, AuthenticationFailed

MAX_REQUEST_LENGTH = 1024 * 1024  # 1 MB

api = application = falcon.API()


def get_json_payload(req, session_is_optional=False):
    if not ((req.content_type == 'application/json') or (req.content_type == 'text/json')):
        raise falcon.HTTPUnsupportedMediaType('Unsupported content-type: {0}'.format(req.content_type))
    length = req.get_header('Content-Length')
    if length is None:
        raise falcon.HTTPLengthRequired('Requests without content-length are not accepted')
    try:
        l = int(length)
    except:
        raise falcon.HTTPBadRequest('Invalid Content-Length', 'The given Content-Length is not a number: {0}'.format(length))
    if l > MAX_REQUEST_LENGTH:
        raise falcon.HTTPError(falcon.HTTP_413, 'Request Entity Too Large', 'Cannot accept the request of length {0}: maximum allowed content-length is {1}'.format(length, MAX_REQUEST_LENGTH))
    try:
        txt = req.stream.read()
    except Exception as e:
        raise falcon.HTTPBadRequest('Error reading request', 'Error while reading the request body: {0}'.format(e.message))
    try:
        js = json.loads(txt, encoding="utf-8")
    except ValueError as e:
        raise falcon.HTTPBadRequest('Error parsing JSON payload', 'Error while parsing the request as JSON: {0}'.format(e.message))
    sid = js.get('sid')
    if sid is None:
        if session_is_optional:
            return js
        raise falcon.HTTPBadRequest('No Session', 'Request is missing a session-ID')
    del js['sid']
    try:
        session = client.get_session_by_id(sid)
    except NoSuchSession:
        if session_is_optional:
            return js
        raise falcon.HTTPBadRequest('Session Expired', 'This user session has expired. Please log-in again.')
    req.context['session'] = session
    return js


class Login(object):
    def on_post(self, req, resp):
        resp.cache_control = 'private, no-cache, no-store'
        js = get_json_payload(req, True)
        username = js.get('username')
        password = js.get('password')
        if username is None:
            response = {'code': 1, 'message': 'Username was not provided'}
        elif password is None:
            response = {'code': 2, 'message': 'Password was not provided'}
        else:
            try:
                session = client.authenticate_and_create_session(username, password)
            except AuthenticationFailed:
                response = {'code': 3, 'message': 'Username or password do not match'}
            else:
                response = {'code': 0, 'message': 'OK', 'sid':session.get_sid()}
                old_session = req.context.get('session')
                if old_session:
                    old_session.destroy()
        resp.body = json.dumps(response)
        resp.content_type = 'application/json'
        resp.status = falcon.HTTP_200

class Activity(object):
    def on_get(self, req, resp):
        resp.body = '{}'
        resp.status = falcon.HTTP_200

class Query(object):
    def on_post(self, req, resp):
        resp.cache_control = 'private, no-cache, no-store'
        js = get_json_payload(req)
        session = req.context['session']
        step = js.get('step')
        if step is None:
            response = {'code': 1, 'message': '"step" is not set'}
        else:
            prolog = session.get_prolog()
            if step == 'run':
                program = js.get('program')
                query = js.get('query')
                language = js.get('language')
                problem_group = js.get('problem_group')
                problem = js.get('problem')
                if program is None:
                    response = {'code': 2, 'message': 'No program specified'}
                elif query is None:
                    response = {'code': 3, 'message': 'No query specified'}
                elif language is None:
                    response = {'code': 4, 'message': 'Language identifier not given'}
                elif problem_group is None:
                    response = {'code': 5, 'message': 'Problem group identifier not given'}
                elif problem is None:
                    response = {'code': 6, 'message': 'Problem identifier not given'}
                else:
                    messages, status, have_more = prolog.run_for_user(session.get_uid(), language, problem_group, problem, program, query)
                    response = {'code': 0, 'message': 'ok', 'terminal': {'messages': messages, 'status': status, 'have_more': have_more}}
            elif step == 'next':
                messages, status, have_more = prolog.step()
                response = {'code': 0, 'message': 'ok', 'terminal': {'messages': messages, 'status': status, 'have_more': have_more}}
            elif step == 'end':
                messages, status, have_more = prolog.end()
                response = {'code': 0, 'message': 'ok', 'terminal': {'messages': messages, 'status': status, 'have_more': have_more}}
            else:
                response = {'code': 7, 'message': 'Unknown prolog step: {0}'.format(step)}

        resp.body = json.dumps(response)
        resp.content_type = 'application/json'
        resp.status = falcon.HTTP_200

login = Login()
api.add_route('/login', login)

activity = Activity()
api.add_route('/activity', activity)

query = Query()
api.add_route('/query', query)