blob: 1895f94eac58d0386ce59baa86295d27a8a79ec3 [file] [log] [blame]
Joe Gregorio20a5aa92011-04-01 17:44:25 -04001# 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.
Joe Gregorio695fdc12011-01-16 16:46:55 -050014
15"""Utilities for OAuth.
16
17Utilities for making it easier to work with OAuth 2.0
18credentials.
19"""
20
21__author__ = 'jcgregorio@google.com (Joe Gregorio)'
22
Joe Gregorio9b8bec62012-01-17 11:35:32 -050023import os
24import stat
Joe Gregorio560b5322011-02-22 11:09:24 -050025import threading
Joe Gregorio695fdc12011-01-16 16:46:55 -050026
Joe Gregorio549230c2012-01-11 10:38:05 -050027from anyjson import simplejson
Joe Gregoriodeeb0202011-02-15 14:49:57 -050028from client import Storage as BaseStorage
Joe Gregorio562b7312011-09-15 09:06:38 -040029from client import Credentials
Joe Gregorio695fdc12011-01-16 16:46:55 -050030
Joe Gregoriodeeb0202011-02-15 14:49:57 -050031
Joe Gregorio0fd18532012-08-24 15:54:40 -040032class CredentialsFileSymbolicLinkError(Exception):
33 """Credentials files must not be symbolic links."""
34
35
Joe Gregoriodeeb0202011-02-15 14:49:57 -050036class Storage(BaseStorage):
Joe Gregorio695fdc12011-01-16 16:46:55 -050037 """Store and retrieve a single credential to and from a file."""
38
39 def __init__(self, filename):
Joe Gregorio7c22ab22011-02-16 15:32:39 -050040 self._filename = filename
Joe Gregorio560b5322011-02-22 11:09:24 -050041 self._lock = threading.Lock()
Joe Gregorio695fdc12011-01-16 16:46:55 -050042
Joe Gregorio0fd18532012-08-24 15:54:40 -040043 def _validate_file(self):
44 if os.path.islink(self._filename):
45 raise CredentialsFileSymbolicLinkError(
46 'File: %s is a symbolic link.' % self._filename)
47
Joe Gregoriod2ee4d82011-09-15 14:32:45 -040048 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):
Joe Gregorio695fdc12011-01-16 16:46:55 -050063 """Retrieve Credential from file.
64
65 Returns:
Joe Gregorio7c22ab22011-02-16 15:32:39 -050066 oauth2client.client.Credentials
Joe Gregorio0fd18532012-08-24 15:54:40 -040067
68 Raises:
69 CredentialsFileSymbolicLinkError if the file is a symbolic link.
Joe Gregorio695fdc12011-01-16 16:46:55 -050070 """
Joe Gregorio562b7312011-09-15 09:06:38 -040071 credentials = None
Joe Gregorio0fd18532012-08-24 15:54:40 -040072 self._validate_file()
Joe Gregoriodeeb0202011-02-15 14:49:57 -050073 try:
Joe Gregorio9b8bec62012-01-17 11:35:32 -050074 f = open(self._filename, 'rb')
Joe Gregorio562b7312011-09-15 09:06:38 -040075 content = f.read()
Joe Gregoriodeeb0202011-02-15 14:49:57 -050076 f.close()
Joe Gregorio562b7312011-09-15 09:06:38 -040077 except IOError:
Joe Gregorio562b7312011-09-15 09:06:38 -040078 return credentials
79
Joe Gregorio562b7312011-09-15 09:06:38 -040080 try:
81 credentials = Credentials.new_from_json(content)
Joe Gregorio9da2ad82011-09-11 14:04:44 -040082 credentials.set_store(self)
Joe Gregorio562b7312011-09-15 09:06:38 -040083 except ValueError:
Joe Gregorioec555842011-10-27 11:10:39 -040084 pass
Joe Gregorio7c22ab22011-02-16 15:32:39 -050085
Joe Gregorio695fdc12011-01-16 16:46:55 -050086 return credentials
87
Joe Gregorio9b8bec62012-01-17 11:35:32 -050088 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
Joe Gregoriod2ee4d82011-09-15 14:32:45 -0400101 def locked_put(self, credentials):
Joe Gregorio562b7312011-09-15 09:06:38 -0400102 """Write Credentials to file.
Joe Gregorio695fdc12011-01-16 16:46:55 -0500103
104 Args:
105 credentials: Credentials, the credentials to store.
Joe Gregorio0fd18532012-08-24 15:54:40 -0400106
107 Raises:
108 CredentialsFileSymbolicLinkError if the file is a symbolic link.
Joe Gregorio695fdc12011-01-16 16:46:55 -0500109 """
Joe Gregorio9b8bec62012-01-17 11:35:32 -0500110
111 self._create_file_if_needed()
Joe Gregorio0fd18532012-08-24 15:54:40 -0400112 self._validate_file()
Joe Gregorio9b8bec62012-01-17 11:35:32 -0500113 f = open(self._filename, 'wb')
Joe Gregorio562b7312011-09-15 09:06:38 -0400114 f.write(credentials.to_json())
Joe Gregorio695fdc12011-01-16 16:46:55 -0500115 f.close()
Joe Gregorioec75dc12012-02-06 13:40:42 -0500116
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)