This repository has been archived by the owner on Sep 9, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 57
/
models.py
106 lines (81 loc) · 3.59 KB
/
models.py
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
#!/usr/bin/python
# Copyright (C) 2010-2013 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Helper model class for TicTacToe API.
Defines models for persisting and querying score data on a per user basis and
provides a method for returning a 401 Unauthorized when no current user can be
determined.
"""
from google.appengine.ext import endpoints
from google.appengine.ext import ndb
from tictactoe_api_messages import ScoreResponseMessage
TIME_FORMAT_STRING = '%b %d, %Y %I:%M:%S %p'
def get_endpoints_current_user(raise_unauthorized=True):
"""Returns a current user and (optionally) causes an HTTP 401 if no user.
Args:
raise_unauthorized: Boolean; defaults to True. If True, this method
raises an exception which causes an HTTP 401 Unauthorized to be
returned with the request.
Returns:
The signed in user if there is one, else None if there is no signed in
user and raise_unauthorized is False.
"""
current_user = endpoints.get_current_user()
if raise_unauthorized and current_user is None:
raise endpoints.UnauthorizedException('Invalid token.')
return current_user
class Score(ndb.Model):
"""Model to store scores that have been inserted by users.
Since the played property is auto_now_add=True, Scores will document when
they were inserted immediately after being stored.
"""
outcome = ndb.StringProperty(required=True)
played = ndb.DateTimeProperty(auto_now_add=True)
player = ndb.UserProperty(required=True)
@property
def timestamp(self):
"""Property to format a datetime object to string."""
return self.played.strftime(TIME_FORMAT_STRING)
def to_message(self):
"""Turns the Score entity into a ProtoRPC object.
This is necessary so the entity can be returned in an API request.
Returns:
An instance of ScoreResponseMessage with the ID set to the datastore
ID of the current entity, the outcome simply the entity's outcome
value and the played value equal to the string version of played
from the property 'timestamp'.
"""
return ScoreResponseMessage(id=self.key.id(),
outcome=self.outcome,
played=self.timestamp)
@classmethod
def put_from_message(cls, message):
"""Gets the current user and inserts a score.
Args:
message: A ScoreRequestMessage instance to be inserted.
Returns:
The Score entity that was inserted.
"""
current_user = get_endpoints_current_user()
entity = cls(outcome=message.outcome, player=current_user)
entity.put()
return entity
@classmethod
def query_current_user(cls):
"""Creates a query for the scores of the current user.
Returns:
An ndb.Query object bound to the current user. This can be used
to filter for other properties or order by them.
"""
current_user = get_endpoints_current_user()
return cls.query(cls.player == current_user)