OLD | NEW |
| (Empty) |
1 # Copyright (C) 2010 Google Inc. | |
2 # | |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | |
4 # you may not use this file except in compliance with the License. | |
5 # You may obtain a copy of the License at | |
6 # | |
7 # http://www.apache.org/licenses/LICENSE-2.0 | |
8 # | |
9 # Unless required by applicable law or agreed to in writing, software | |
10 # distributed under the License is distributed on an "AS IS" BASIS, | |
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 # See the License for the specific language governing permissions and | |
13 # limitations under the License. | |
14 | |
15 """Utilities for OAuth. | |
16 | |
17 Utilities for making it easier to work with OAuth 2.0 | |
18 credentials. | |
19 """ | |
20 | |
21 __author__ = 'jcgregorio@google.com (Joe Gregorio)' | |
22 | |
23 import os | |
24 import stat | |
25 import threading | |
26 | |
27 from anyjson import simplejson | |
28 from client import Storage as BaseStorage | |
29 from client import Credentials | |
30 | |
31 | |
32 class CredentialsFileSymbolicLinkError(Exception): | |
33 """Credentials files must not be symbolic links.""" | |
34 | |
35 | |
36 class Storage(BaseStorage): | |
37 """Store and retrieve a single credential to and from a file.""" | |
38 | |
39 def __init__(self, filename): | |
40 self._filename = filename | |
41 self._lock = threading.Lock() | |
42 | |
43 def _validate_file(self): | |
44 if os.path.islink(self._filename): | |
45 raise CredentialsFileSymbolicLinkError( | |
46 'File: %s is a symbolic link.' % self._filename) | |
47 | |
48 def acquire_lock(self): | |
49 """Acquires any lock necessary to access this Storage. | |
50 | |
51 This lock is not reentrant.""" | |
52 self._lock.acquire() | |
53 | |
54 def release_lock(self): | |
55 """Release the Storage lock. | |
56 | |
57 Trying to release a lock that isn't held will result in a | |
58 RuntimeError. | |
59 """ | |
60 self._lock.release() | |
61 | |
62 def locked_get(self): | |
63 """Retrieve Credential from file. | |
64 | |
65 Returns: | |
66 oauth2client.client.Credentials | |
67 | |
68 Raises: | |
69 CredentialsFileSymbolicLinkError if the file is a symbolic link. | |
70 """ | |
71 credentials = None | |
72 self._validate_file() | |
73 try: | |
74 f = open(self._filename, 'rb') | |
75 content = f.read() | |
76 f.close() | |
77 except IOError: | |
78 return credentials | |
79 | |
80 try: | |
81 credentials = Credentials.new_from_json(content) | |
82 credentials.set_store(self) | |
83 except ValueError: | |
84 pass | |
85 | |
86 return credentials | |
87 | |
88 def _create_file_if_needed(self): | |
89 """Create an empty file if necessary. | |
90 | |
91 This method will not initialize the file. Instead it implements a | |
92 simple version of "touch" to ensure the file has been created. | |
93 """ | |
94 if not os.path.exists(self._filename): | |
95 old_umask = os.umask(0177) | |
96 try: | |
97 open(self._filename, 'a+b').close() | |
98 finally: | |
99 os.umask(old_umask) | |
100 | |
101 def locked_put(self, credentials): | |
102 """Write Credentials to file. | |
103 | |
104 Args: | |
105 credentials: Credentials, the credentials to store. | |
106 | |
107 Raises: | |
108 CredentialsFileSymbolicLinkError if the file is a symbolic link. | |
109 """ | |
110 | |
111 self._create_file_if_needed() | |
112 self._validate_file() | |
113 f = open(self._filename, 'wb') | |
114 f.write(credentials.to_json()) | |
115 f.close() | |
116 | |
117 def locked_delete(self): | |
118 """Delete Credentials file. | |
119 | |
120 Args: | |
121 credentials: Credentials, the credentials to store. | |
122 """ | |
123 | |
124 os.unlink(self._filename) | |
OLD | NEW |