3 # Copyright 2007 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 """Python datastore class User to be used as a datastore data type.
21 User: object representing a user.
22 Error: base exception type
23 UserNotFoundError: UserService exception
24 RedirectTooLongError: UserService exception
25 NotAllowedError: UserService exception
34 from google
.appengine
.api
import apiproxy_stub_map
35 from google
.appengine
.api
import user_service_pb
36 from google
.appengine
.runtime
import apiproxy_errors
39 class Error(Exception):
40 """Base User error type."""
43 class UserNotFoundError(Error
):
44 """Raised by User.__init__() when there's no email argument and no user is
48 class RedirectTooLongError(Error
):
49 """Raised by UserService calls if the generated redirect URL was too long.
53 class NotAllowedError(Error
):
54 """Raised by UserService calls if the requested redirect URL is not allowed.
61 We provide the email address, nickname, auth domain, and id for a user.
63 A nickname is a human-readable string which uniquely identifies a Google
64 user, akin to a username. It will be an email address for some users, but
71 def __init__(self
, email
=None, _auth_domain
=None, _user_id
=None):
75 email: An optional string of the user's email address. It defaults to
76 the current user's email address.
79 UserNotFoundError: Raised if the user is not logged in and the email
82 if _auth_domain
is None:
83 _auth_domain
= os
.environ
.get('AUTH_DOMAIN')
85 assert email
is not None
90 assert 'USER_EMAIL' in os
.environ
91 email
= os
.environ
['USER_EMAIL']
92 if _user_id
is None and 'USER_ID' in os
.environ
:
93 _user_id
= os
.environ
['USER_ID']
96 raise UserNotFoundError
99 self
.__auth
_domain
= _auth_domain
100 self
.__user
_id
= _user_id
or None
103 """Return this user's nickname.
105 The nickname will be a unique, human readable identifier for this user
106 with respect to this application. It will be an email address for some
109 if (self
.__email
and self
.__auth
_domain
and
110 self
.__email
.endswith('@' + self
.__auth
_domain
)):
111 suffix_len
= len(self
.__auth
_domain
) + 1
112 return self
.__email
[:-suffix_len
]
117 """Return this user's email address."""
121 """Return either a permanent unique identifying string or None.
123 If the email address was set explicity, this will return None.
125 return self
.__user
_id
127 def auth_domain(self
):
128 """Return this user's auth domain."""
129 return self
.__auth
_domain
131 def __unicode__(self
):
132 return unicode(self
.nickname())
135 return str(self
.nickname())
139 return "users.User(email='%s',_user_id='%s')" % (self
.email(),
142 return "users.User(email='%s')" % self
.email()
145 return hash((self
.__email
, self
.__auth
_domain
))
147 def __cmp__(self
, other
):
148 if not isinstance(other
, User
):
149 return NotImplemented
150 return cmp((self
.__email
, self
.__auth
_domain
),
151 (other
.__email
, other
.__auth
_domain
))
154 def create_login_url(dest_url
):
155 """Computes the login URL for this request and specified destination URL.
158 dest_url: String that is the desired final destination URL for the user
159 once login is complete. If 'dest_url' does not have a host
160 specified, we will use the host from the current request.
165 req
= user_service_pb
.StringProto()
166 resp
= user_service_pb
.StringProto()
167 req
.set_value(dest_url
)
169 apiproxy_stub_map
.MakeSyncCall('user', 'CreateLoginURL', req
, resp
)
170 except apiproxy_errors
.ApplicationError
, e
:
171 if (e
.application_error
==
172 user_service_pb
.UserServiceError
.REDIRECT_URL_TOO_LONG
):
173 raise RedirectTooLongError
174 elif (e
.application_error
==
175 user_service_pb
.UserServiceError
.NOT_ALLOWED
):
176 raise NotAllowedError
181 CreateLoginURL
= create_login_url
184 def create_logout_url(dest_url
):
185 """Computes the logout URL for this request and specified destination URL.
188 dest_url: String that is the desired final destination URL for the user
189 once logout is complete. If 'dest_url' does not have a host
190 specified, we will use the host from the current request.
195 req
= user_service_pb
.StringProto()
196 resp
= user_service_pb
.StringProto()
197 req
.set_value(dest_url
)
199 apiproxy_stub_map
.MakeSyncCall('user', 'CreateLogoutURL', req
, resp
)
200 except apiproxy_errors
.ApplicationError
, e
:
201 if (e
.application_error
==
202 user_service_pb
.UserServiceError
.REDIRECT_URL_TOO_LONG
):
203 raise RedirectTooLongError
208 CreateLogoutURL
= create_logout_url
211 def get_current_user():
214 except UserNotFoundError
:
217 GetCurrentUser
= get_current_user
220 def is_current_user_admin():
221 """Return true if the user making this request is an admin for this
222 application, false otherwise.
224 We specifically make this a separate function, and not a member function of
225 the User class, because admin status is not persisted in the datastore. It
226 only exists for the user making this request right now.
228 return (os
.environ
.get('USER_IS_ADMIN', '0')) == '1'
230 IsCurrentUserAdmin
= is_current_user_admin