3333use OCP \ILogger ;
3434use OpenStack \Common \Error \BadResponseError ;
3535use OpenStack \Common \Auth \Token ;
36+ use OpenStack \Identity \v2 \Models \Catalog ;
3637use OpenStack \Identity \v2 \Service as IdentityV2Service ;
3738use OpenStack \Identity \v3 \Service as IdentityV3Service ;
3839use OpenStack \OpenStack ;
@@ -47,6 +48,13 @@ class SwiftFactory {
4748 private $ container = null ;
4849 private $ logger ;
4950
51+ const DEFAULT_OPTIONS = [
52+ 'autocreate ' => false ,
53+ 'urlType ' => 'publicURL ' ,
54+ 'catalogName ' => 'swift ' ,
55+ 'catalogType ' => 'object-store '
56+ ];
57+
5058 public function __construct (ICache $ cache , array $ params , ILogger $ logger ) {
5159 $ this ->cache = $ cache ;
5260 $ this ->params = $ params ;
@@ -62,11 +70,21 @@ private function getCachedToken(string $cacheKey) {
6270 }
6371 }
6472
65- private function cacheToken (Token $ token , string $ cacheKey ) {
73+ private function cacheToken (Token $ token , string $ serviceUrl , string $ cacheKey ) {
6674 if ($ token instanceof \OpenStack \Identity \v3 \Models \Token) {
75+ // for v3 the catalog is cached as part of the token, so no need to cache $serviceUrl separately
6776 $ value = json_encode ($ token ->export ());
6877 } else {
69- $ value = json_encode ($ token );
78+ /** @var \OpenStack\Identity\v2\Models\Token $token */
79+ $ value = json_encode ([
80+ 'serviceUrl ' => $ serviceUrl ,
81+ 'token ' => [
82+ 'issued_at ' => $ token ->issuedAt ->format ('c ' ),
83+ 'expires ' => $ token ->expires ->format ('c ' ),
84+ 'id ' => $ token ->id ,
85+ 'tenant ' => $ token ->tenant
86+ ]
87+ ]);
7088 }
7189 $ this ->cache ->set ($ cacheKey . '/token ' , $ value );
7290 }
@@ -82,10 +100,6 @@ private function getClient() {
82100 if (!isset ($ this ->params ['container ' ])) {
83101 $ this ->params ['container ' ] = 'nextcloud ' ;
84102 }
85- if (!isset ($ this ->params ['autocreate ' ])) {
86- // should only be true for tests
87- $ this ->params ['autocreate ' ] = false ;
88- }
89103 if (isset ($ this ->params ['user ' ]) && is_array ($ this ->params ['user ' ])) {
90104 $ userName = $ this ->params ['user ' ]['name ' ];
91105 } else {
@@ -97,6 +111,7 @@ private function getClient() {
97111 if (!isset ($ this ->params ['tenantName ' ]) && isset ($ this ->params ['tenant ' ])) {
98112 $ this ->params ['tenantName ' ] = $ this ->params ['tenant ' ];
99113 }
114+ $ this ->params = array_merge (self ::DEFAULT_OPTIONS , $ this ->params );
100115
101116 $ cacheKey = $ userName . '@ ' . $ this ->params ['url ' ] . '/ ' . $ this ->params ['container ' ];
102117 $ token = $ this ->getCachedToken ($ cacheKey );
@@ -114,7 +129,7 @@ private function getClient() {
114129
115130 return $ this ->auth (IdentityV3Service::factory ($ httpClient ), $ cacheKey );
116131 } else {
117- return $ this ->auth (IdentityV2Service ::factory ($ httpClient ), $ cacheKey );
132+ return $ this ->auth (SwiftV2CachingAuthService ::factory ($ httpClient ), $ cacheKey );
118133 }
119134 }
120135
@@ -127,25 +142,41 @@ private function getClient() {
127142 private function auth ($ authService , string $ cacheKey ) {
128143 $ this ->params ['identityService ' ] = $ authService ;
129144 $ this ->params ['authUrl ' ] = $ this ->params ['url ' ];
130- $ client = new OpenStack ($ this ->params );
131145
132146 $ cachedToken = $ this ->params ['cachedToken ' ];
133147 $ hasValidCachedToken = false ;
134- if (\is_array ($ cachedToken ) && ($ authService instanceof IdentityV3Service)) {
135- $ token = $ authService ->generateTokenFromCache ($ cachedToken );
136- if (\is_null ($ token ->catalog )) {
137- $ this ->logger ->warning ('Invalid cached token for swift, no catalog set: ' . json_encode ($ cachedToken ));
138- } else if ($ token ->hasExpired ()) {
139- $ this ->logger ->debug ('Cached token for swift expired ' );
148+ if (\is_array ($ cachedToken )) {
149+ if ($ authService instanceof IdentityV3Service) {
150+ $ token = $ authService ->generateTokenFromCache ($ cachedToken );
151+ if (\is_null ($ token ->catalog )) {
152+ $ this ->logger ->warning ('Invalid cached token for swift, no catalog set: ' . json_encode ($ cachedToken ));
153+ } else if ($ token ->hasExpired ()) {
154+ $ this ->logger ->debug ('Cached token for swift expired ' );
155+ } else {
156+ $ hasValidCachedToken = true ;
157+ }
140158 } else {
141- $ hasValidCachedToken = true ;
159+ try {
160+ /** @var \OpenStack\Identity\v2\Models\Token $token */
161+ $ token = $ authService ->model (\OpenStack \Identity \v2 \Models \Token::class, $ cachedToken ['token ' ]);
162+ $ now = new \DateTimeImmutable ("now " );
163+ if ($ token ->expires > $ now ) {
164+ $ hasValidCachedToken = true ;
165+ $ this ->params ['v2cachedToken ' ] = $ token ;
166+ $ this ->params ['v2serviceUrl ' ] = $ cachedToken ['serviceUrl ' ];
167+ } else {
168+ $ this ->logger ->debug ('Cached token for swift expired ' );
169+ }
170+ } catch (\Exception $ e ) {
171+ $ this ->logger ->logException ($ e );
172+ }
142173 }
143174 }
144175
145176 if (!$ hasValidCachedToken ) {
146177 try {
147- $ token = $ authService ->generateToken ($ this ->params );
148- $ this ->cacheToken ($ token , $ cacheKey );
178+ list ( $ token, $ serviceUrl ) = $ authService ->authenticate ($ this ->params );
179+ $ this ->cacheToken ($ token , $ serviceUrl , $ cacheKey );
149180 } catch (ConnectException $ e ) {
150181 throw new StorageAuthException ('Failed to connect to keystone, verify the keystone url ' , $ e );
151182 } catch (ClientException $ e ) {
@@ -164,6 +195,9 @@ private function auth($authService, string $cacheKey) {
164195 }
165196 }
166197
198+
199+ $ client = new OpenStack ($ this ->params );
200+
167201 return $ client ;
168202 }
169203
0 commit comments