settings.py 8.06 KB
Newer Older
1
2
3
4
"""Data Model and General Configuration of Eve.

Check out [the Eve docs for configuration](http://python-eve.org/config.html)
if you are unsure about some of the settings.
5

6
7
8
Our schema requires customized data validation. These validation rules are
implemented in `validation.py`.
Some validation rules are still missing, they are marked with TODO in the
9
schema directly.
10
"""
adietmue's avatar
adietmue committed
11

12
13
from os import environ

14
15
16
# CORS
X_DOMAINS = '*'
X_HEADERS = ['Authorization', 'If-Match', 'If-Modified-Since', 'Content-Type']
17

adietmue's avatar
adietmue committed
18
# AMIVAPI URL and Admin Group
19
20
AMIVAPI_URL = 'https://amiv-api.ethz.ch'
ADMIN_GROUP_NAME = 'PVK Admins'
21

22
# DB (can be set by env for easier CI tests)
23
MONGO_HOST = environ.get('MONGO_HOST', 'localhost')
24
25
26
27
MONGO_PORT = environ.get('MONGO_PORT', 27017)
MONGO_DBNAME = environ.get('MONGO_DBNAME', 'pvk')
MONGO_USERNAME = environ.get('MONGO_USERNAME', 'pvkuser')
MONGO_PASSWORD = environ.get('MONGO_PASSWORD', 'pvkpass')
28

29

30
31
32
# Only JSON, simplifies hooks
XML = False

adietmue's avatar
adietmue committed
33

34
RESOURCE_METHODS = ['GET', 'POST']
adietmue's avatar
adietmue committed
35
36
ITEM_METHODS = ['GET', 'PATCH', 'DELETE']

37

38
39
40
41
42
43
44
45
46
# Stripe API Key
# TODO: Not a good idea to keep this in the repo
STRIPE_API_KEY = 'sk_test_KUiZO8E2VKGMmm94u4t5YPnL'


# Price per course in "rappen"
COURSE_PRICE = 1000


adietmue's avatar
adietmue committed
47
48
# ISO 8601 time format instead of rfc1123
DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
49

adietmue's avatar
adietmue committed
50

51
52
53
54
# More Feedback when creating something: Return all fields
BANDWIDTH_SAVER = False


55
56
57
58
59
60
61
# Disable bulk insert
# They are not compatible with uniqueness constraints
# (see more here: https://github.com/pyeve/eve/issues/691)
# In our case, we need time and room uniqueness nearly everywhere => disabled
BULK_ENABLED = False


62
# A schema for required start/end time tuple
63
TIMESPAN_SCHEMA = {
64
65
66
67
68
69
70
71
72
73
74
75
76
    'type': 'dict',
    'schema': {
        'start': {
            'type': 'datetime',
            'nullable': False,
            'required': True,
        },
        'end': {
            'type': 'datetime',
            'nullable': False,
            'required': True,
        },
    },
77
    'start_before_end': True,
78
79
80
}


81
82
83
84
# Same as Eve, but include 403
STANDARD_ERRORS = [400, 401, 403, 404, 405, 406, 409, 410, 412, 422, 428]


85
86
87
# Resources
DOMAIN = {
    'lectures': {
88
89
90

        'user_methods': ['GET'],

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
        'schema': {
            'title': {
                'type': 'string',
                'maxlength': 100,
                'unique': True,
                'required': True,
                'nullable': False,
                'empty': False,
            },
            'department': {
                'type': 'string',
                'allowed': ['itet', 'mavt'],
                'required': True,
                'nullable': False,
            },
            'year': {
                'type': 'integer',
                'min': 1,
                'max': 3,
                'required': True
            },
112
113
114
115
116
117
118
119
            'assistants': {
                # List of nethz of assistants
                'type': 'list',
                'schema': {
                    'type': 'string',
                    'maxlength': 10,
                    'empty': False,
                    'nullable': False,
adietmue's avatar
adietmue committed
120
                },
121
                # TODO: Not the same nethz twice (use new nocopies validator)
122
                # TODO: Is nethz enough here?
123
            }
124
125
126
127
        },
    },

    'courses': {
128
129
130

        'user_methods': ['GET'],

131
132
133
134
135
136
137
138
        'schema': {
            'lecture': {
                'type': 'objectid',
                'data_relation': {
                    'resource': 'lectures',
                    'field': '_id',
                    'embeddable': True
                },
139
                'not_patchable': True,  # Course is tied to lecture
140
                'required': True,
141
142
            },
            'assistant': {
adietmue's avatar
adietmue committed
143
                'type': 'string',
144
                # TODO: Assistant needs to exist for lecture
145
                # TODO: assistant timeslot
146
147
            },

148
            'signup': TIMESPAN_SCHEMA,
149
150
151

            'datetimes': {
                'type': 'list',
152
                'schema': TIMESPAN_SCHEMA,
153
154
                'no_time_overlap': True,
                'unique_room_booking': True,
155
156
157
158
159
160
            },
            'room': {
                'type': 'string',
                'maxlength': 100,
                'nullable': False,
                'empty': False,
161
                'unique_room_booking': True,
162
163
164
165
166
            },
            'spots': {
                'type': 'integer',
                'min': 1,
                'required': True,
167
                'nullable': False,
168
169
170
171
172
            }
        },
    },

    'signups': {
173
174
        # Signup for a user to a course

175
176
        'user_methods': ['GET', 'POST', 'PATCH', 'DELETE'],

177
178
179
180
181
182
183
        'schema': {
            'nethz': {
                'type': 'string',
                'maxlength': 10,
                'empty': False,
                'nullable': False,
                'required': True,
adietmue's avatar
adietmue committed
184
                'only_own_nethz': True,
185
                'not_patchable': True,  # Signup is tied to user
186
187
188
189
190
191
192
193
            },
            'course': {
                'type': 'objectid',
                'data_relation': {
                    'resource': 'courses',
                    'field': '_id',
                    'embeddable': True
                },
adietmue's avatar
adietmue committed
194
                'unique_combination': ['nethz'],
195
                'required': True,
196
                'no_course_overlap': 'signups',
197
198
199
            },
            'status': {
                'type': 'string',
200
                'allowed': ['waiting', 'reserved', 'accepted'],
201
                'readonly': True,
202
                'default': 'waiting',
203
204
            },
        },
205
206
207
208
    },

    'selections': {
        # Easy way for users to safe their selections before signup is open
209
        # exactly like singups, but without status
210

211
212
        'user_methods': ['GET', 'POST', 'PATCH', 'DELETE'],

213
214
215
216
217
218
219
220
        'schema': {
            'nethz': {
                'type': 'string',
                'maxlength': 10,
                'empty': False,
                'nullable': False,
                'required': True,
                'only_own_nethz': True,
221
                'not_patchable': True,  # Signup is tied to user
222
            },
223
224
225
226
227
228
            'course': {
                'type': 'objectid',
                'data_relation': {
                    'resource': 'courses',
                    'field': '_id',
                    'embeddable': True
229
                },
230
231
                'unique_combination': ['nethz'],
                'required': True,
232
                'no_course_overlap': 'selections',
233
234
235
236
237
            },
        },
    },

    'payments': {
238
239
240
241
        # Endpoint for payments via Stripe.

        # charge_id is a unique identifier which allows us to track the payment with Stripe
        # Admins can however create payments without a charge_id
242

243
        # Only admins can delete payments
244
245
246
        # Also, there is no reason to ever change a payment.
        'user_methods': ['GET', 'POST'],

247
248
249
250
251
252
253
254
255
256
        'schema': {
            'signups': {
                'type': 'list',
                'schema': {
                    'type': 'objectid',
                    'data_relation': {
                        'resource': 'signups',
                        'field': '_id',
                        'embeddable': True
                    },
257
258
259
260
                    # No signups on waiting list
                    'no_waiting': True,
                    # No signups which have already been paid
                    'no_accepted': True,
261
                },
262
                'no_copies': True,
263
264
                'required': True,
                'nullable': False,
265
266
            },
            # Admins may leave this field empty
267
            # However, it still has to be sent, even if  empty or None
268
269
270
271
272
273
274
            'token': {
                'type': 'string',
                'unique': True,
                'required': True,
                'nullable': True,
                'only_admin_empty': True,
            },
275
            'charge_id': {  # Set by payment backend
276
277
278
279
280
                'type': 'string',
                'unique': True,
                'required': False,
                'nullable': True,
            },
281
            'amount': {  # Set by payment backend
282
283
284
                'type': 'integer',
                'required': False,
                'nullable': True,
285
286
            }
        }
287
288
    }
}