-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmanager.py
More file actions
202 lines (189 loc) · 7.49 KB
/
manager.py
File metadata and controls
202 lines (189 loc) · 7.49 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
"""CfP Manager functionality"""
import endpoints
from datetime import datetime
from google.appengine.ext import ndb
from google.appengine.api import oauth
from protorpc import messages
from protorpc import message_types
from protorpc import remote
from models import Conference
from models import ConferenceForm
from models import ConferencePublicForm
from models import ConferencePublicForms
from models import Speaker
from models import SpeakerForm
from models import SpeakerKeyForm
from models import Proposal
from models import ProposalForm
from models import ProposalKeyForm
from settings import *
PROPOSAL_SUBMIT_REQUEST = endpoints.ResourceContainer(
ProposalForm,
conferenceId=messages.StringField(1),
)
SPEAKER_BY_EMAIL_REQUEST = endpoints.ResourceContainer(
message_types.VoidMessage,
email=messages.StringField(1),
)
@endpoints.api(
name='manager', version='v1', audiences=[ANDROID_AUDIENCE],
allowed_client_ids=[
WEB_CLIENT_ID, ANDROID_CLIENT_ID,
endpoints.API_EXPLORER_CLIENT_ID,
IOS_CLIENT_ID],
scopes=[endpoints.EMAIL_SCOPE]
)
class CfpManagerApi(remote.Service):
"""Call for Papers Manager"""
def _copyToForm(self, src, trg):
"""Copy from an entity to a form"""
for field in trg.all_fields():
if hasattr(src, field.name):
value = getattr(src, field.name)
# does it contain 'Date'?
if "Date" in field.name:
setattr(trg, field.name, str(value))
# does it ask for a key?
elif field.name == "key":
setattr(trg, field.name, value.urlsafe())
else:
setattr(trg, field.name, value)
else:
if field.name == "id":
setattr(trg, "id", src.key.id())
# check if all is OK
trg.check_initialized()
return trg
@endpoints.method(
message_types.VoidMessage, ConferencePublicForms,
path='conference', http_method='GET',
name='listConferences')
def listConferences(self, request):
"""List all conferences with open CfP"""
nowDate = datetime.now().date()
confs = Conference.query(Conference.cfpDateTo >= nowDate)
# further filter down the conferences
confs = [c for c in confs if c.cfpDateFrom <= nowDate]
return ConferencePublicForms(
items=[self._copyToForm(conf, ConferencePublicForm())
for conf in confs]
)
@endpoints.method(
ConferenceForm, ConferenceForm, path='conference',
http_method='POST', name='createConference')
def createConference(self, request):
"""Create a new Conference object"""
user = endpoints.get_current_user()
if user.email() and oauth.is_current_user_admin():
# we only allow an admin user to create a conference
if not request.name or not request.id:
raise endpoints.BadRequestException(
"Required field (name and/or id) missing"
)
data = {field.name: getattr(request, field.name)
for field in request.all_fields()}
# convert start/end dates
if data['cfpDateFrom']:
data['cfpDateFrom'] = datetime.strptime(
data['cfpDateFrom'][:10], "%Y-%m-%d").date()
if data['cfpDateTo']:
data['cfpDateTo'] = datetime.strptime(
data['cfpDateTo'][:10], "%Y-%m-%d").date()
# set the created date/time stamp
data['created'] = datetime.now()
data['modified'] = data['created']
# store in DataStore
Conference(**data).put()
return request
else:
raise endpoints.ForbiddenException(
"Only administrators can create a conference"
)
@endpoints.method(
SpeakerForm, SpeakerKeyForm, path='speaker',
http_method='POST', name='createSpeaker')
def createSpeaker(self, request):
"""Create a new speaker object"""
if not request.email or not request.name or not request.surname:
raise endpoints.BadRequestException(
"Required field (name, surname and/or email) missing"
)
data = {field.name: getattr(request, field.name)
for field in request.all_fields()}
# set the created date/time stamp
data['created'] = datetime.now()
data['modified'] = data['created']
# store in Datastore
speakerKey = Speaker(**data).put()
speakerKeyForm = SpeakerKeyForm()
speakerKeyForm.key = speakerKey.urlsafe()
speakerKeyForm.email = request.email
return speakerKeyForm
@endpoints.method(
SPEAKER_BY_EMAIL_REQUEST, SpeakerKeyForm,
path='speaker/by_email/{email}',
http_method='GET', name='speakerByEmail')
def speakerByEmail(self, request):
"""Return speaker key for email"""
if not request.email:
raise endpoints.BadRequestException(
"Missing email parameter"
)
# get speakers for email
speakers = Speaker.query(Speaker.email == request.email)
# and order by modified-date (reverse) to get the last one
speakers = speakers.order(-Speaker.modified).iter()
if speakers.has_next():
lastSpeaker = speakers.next()
retVal = SpeakerKeyForm()
retVal.email = lastSpeaker.email
retVal.key = lastSpeaker.key.urlsafe()
return retVal
raise endpoints.NotFoundException(
"No speaker for this email found"
)
@endpoints.method(
PROPOSAL_SUBMIT_REQUEST, ProposalKeyForm,
path='conference/{conferenceId}/proposal',
http_method='POST', name='submitProposal')
def submitProposal(self, request):
"""Submit a new talk proposal"""
if not request.title or not request.speaker:
raise endpoints.BadRequestException(
"Required field (title and/or speaker key) missing"
)
# get the speaker (check if it exists)
speaker = ndb.Key(urlsafe=request.speaker).get()
if not speaker:
raise endpoints.BadRequestException(
"Speaker entity not found"
)
if speaker.key.kind() != "Speaker":
raise endpoints.BadRequestException(
"Invalid key kind for speaker specified"
)
# get the conference (check if it exists)
conf = Conference.get_by_id(request.conferenceId)
if not conf:
raise endpoints.BadRequestException(
"Invalid conference identifier specified"
)
# TODO: check if call for papers is still open
# fill the data structure for creating the entity
data = {field.name: getattr(request, field.name)
for field in request.all_fields()}
# delete conference id, link to parent
del data['conferenceId']
data['parent'] = conf.key
# update the speaker reference
data['speaker'] = speaker.key
# set the created date/time stamp
data['created'] = datetime.now()
data['modified'] = data['created']
# store in Datastore - with correct parent
proposalKey = Proposal(**data).put()
# return value
retVal = ProposalKeyForm()
retVal.key = proposalKey.urlsafe()
retVal.title = request.title
return retVal