11using System ;
22using System . Collections . Generic ;
3+ using System . Linq ;
34using Newtonsoft . Json ;
45using Newtonsoft . Json . Linq ;
56using SimpleRestServices . Client ;
67using SimpleRestServices . Client . Json ;
7- using net . openstack . Core ;
88using net . openstack . Core . Domain ;
99using net . openstack . Core . Exceptions ;
1010using net . openstack . Providers . Rackspace . Objects . Request ;
1111using net . openstack . Providers . Rackspace . Objects . Response ;
1212
1313namespace net . openstack . Providers . Rackspace
1414{
15- internal class GeographicalIdentityProvider : IIdentityProvider
15+ internal class GeographicalIdentityProvider : IExtendedIdentityProvider
1616 {
1717 private readonly IRestService _restService ;
1818 private readonly ICache < UserAccess > _userAccessCache ;
@@ -97,24 +97,40 @@ public bool DeleteRoleFromUser(CloudIdentity identity, string userId, string rol
9797
9898 public bool SetUserPassword ( CloudIdentity identity , string userId , string password )
9999 {
100- var urlPath = string . Format ( "v2.0/users/{0}/OS-KSADM/credentials" , userId ) ;
101- var response = ExecuteRESTRequest < RoleResponse > ( identity , urlPath , HttpMethod . GET ) ;
100+ var user = GetUser ( identity , userId ) ;
102101
103- if ( response == null || response . StatusCode != 201 )
102+ var urlPath = string . Format ( "v2.0/users/{0}/OS-KSADM/credentials" , userId ) ;
103+ var request = new SetPasswordRequest
104+ {
105+ PasswordCredencial =
106+ new PasswordCredencial { Username = user . Username , Password = password }
107+ } ;
108+ var response = ExecuteRESTRequest < PasswordCredencialResponse > ( identity , urlPath , HttpMethod . POST , request ) ;
109+
110+ if ( response == null || response . StatusCode != 201 || response . Data == null )
104111 return false ;
105112
106- return true ;
113+ return response . Data . PasswordCredencial . Password . Equals ( password ) ;
107114 }
108115
109116 public UserCredential [ ] ListUserCredentials ( CloudIdentity identity , string userId )
110117 {
111- throw new NotImplementedException ( ) ;
118+ var urlPath = string . Format ( "v2.0/users/{0}/OS-KSADM/credentials" , userId ) ;
119+ var response = ExecuteRESTRequest < UserCredentialsResponse > ( identity , urlPath , HttpMethod . GET ) ;
120+
121+ if ( response == null || response . Data == null )
122+ return null ;
123+
124+ return response . Data . Credentials . Select ( c => c . UserCredential ) . ToArray ( ) ;
112125 }
113126
114- public UserCredential UpdateUserCredentials ( CloudIdentity identity , string userId )
127+ public UserCredential UpdateUserCredentials ( CloudIdentity identity , string userId , string apiKey )
115128 {
129+ var user = GetUser ( identity , userId ) ;
130+
116131 var urlPath = string . Format ( "v2.0/users/{0}/OS-KSADM/credentials/RAX-KSKEY:apiKeyCredentials" , userId ) ;
117- var response = ExecuteRESTRequest < UserCredentialResponse > ( identity , urlPath , HttpMethod . POST ) ;
132+ var request = new UpdateUserCredencialRequest { UserCredential = new UserCredential { Username = user . Username , APIKey = apiKey } } ;
133+ var response = ExecuteRESTRequest < UserCredentialResponse > ( identity , urlPath , HttpMethod . POST , request ) ;
118134
119135 if ( response == null || response . Data == null )
120136 return null ;
@@ -144,6 +160,18 @@ public User[] ListUsers(CloudIdentity identity)
144160 if ( response == null || response . Data == null )
145161 return null ;
146162
163+ // Due to the fact the sometimes the API returns a JSON array of users and sometimes it returns a single JSON user object.
164+ // Therefore if we get a null data object (which indicates that the deserializer could not parse to an array) we need to try and parse as a single User object.
165+ if ( response . Data . Users == null )
166+ {
167+ var userResponse = JsonConvert . DeserializeObject < UserResponse > ( response . RawBody ) ;
168+
169+ if ( response == null || response . Data == null )
170+ return null ;
171+
172+ return new [ ] { userResponse . User } ;
173+ }
174+
147175 return response . Data . Users ;
148176 }
149177
@@ -222,7 +250,7 @@ public Tenant[] ListTenants(CloudIdentity identity)
222250
223251 public string GetToken ( CloudIdentity idenity , bool forceCacheRefresh = false )
224252 {
225- var auth = Authenticate ( idenity , forceCacheRefresh ) ;
253+ var auth = GetUserAccess ( idenity , forceCacheRefresh ) ;
226254
227255 if ( auth == null || auth . Token == null )
228256 return null ;
@@ -232,7 +260,7 @@ public string GetToken(CloudIdentity idenity, bool forceCacheRefresh = false)
232260
233261 public string GetToken ( RackspaceImpersonationIdentity identity , bool forceCacheRefresh = false )
234262 {
235- var auth = Authenticate ( identity , forceCacheRefresh ) ;
263+ var auth = GetUserAccess ( identity , forceCacheRefresh ) ;
236264
237265 if ( auth == null || auth . Token == null )
238266 return null ;
@@ -242,31 +270,34 @@ public string GetToken(RackspaceImpersonationIdentity identity, bool forceCacheR
242270
243271 public IdentityToken GetTokenInfo ( CloudIdentity identity , bool forceCacheRefresh = false )
244272 {
245- var auth = Authenticate ( identity , forceCacheRefresh ) ;
273+ var auth = GetUserAccess ( identity , forceCacheRefresh ) ;
246274
247275 if ( auth == null )
248276 return null ;
249277
250278 return auth . Token ;
251279 }
252280
253- public UserAccess Authenticate ( CloudIdentity identity , bool forceCacheRefresh = false )
281+ public UserAccess Authenticate ( CloudIdentity identity )
254282 {
255- var usIdentity = identity as RackspaceCloudIdentity ;
283+ var auth = AuthRequest . FromCloudIdentity ( identity ) ;
284+ var response = ExecuteRESTRequest < AuthenticationResponse > ( identity , "/v2.0/tokens" , HttpMethod . POST , auth , isTokenRequest : true ) ;
256285
257- if ( usIdentity == null )
258- throw new InvalidCloudIdentityException ( string . Format ( "Invalid Identity object. Rackspace Identity service requires an instance of type: {0}" , typeof ( RackspaceCloudIdentity ) ) ) ;
259286
260- var userAccess = _userAccessCache . Get ( string . Format ( "{0}/{1}" , usIdentity . CloudInstance , usIdentity . Username ) , ( ) => {
261- var auth = AuthRequest . FromCloudIdentity ( usIdentity ) ;
262- var response = ExecuteRESTRequest < AuthenticationResponse > ( usIdentity , "/v2.0/tokens" , HttpMethod . POST , auth , isTokenRequest : true ) ;
287+ if ( response == null || response . Data == null || response . Data . UserAccess == null || response . Data . UserAccess . Token == null )
288+ return null ;
263289
290+ return response . Data . UserAccess ;
291+ }
264292
265- if ( response == null || response . Data == null || response . Data . UserAccess == null || response . Data . UserAccess . Token == null )
266- return null ;
293+ private UserAccess GetUserAccess ( CloudIdentity identity , bool forceCacheRefresh = false )
294+ {
295+ var rackspaceCloudIdentity = identity as RackspaceCloudIdentity ;
267296
268- return response . Data . UserAccess ;
269- } , forceCacheRefresh ) ;
297+ if ( rackspaceCloudIdentity == null )
298+ throw new InvalidCloudIdentityException ( string . Format ( "Invalid Identity object. Rackspace Identity service requires an instance of type: {0}" , typeof ( RackspaceCloudIdentity ) ) ) ;
299+
300+ var userAccess = _userAccessCache . Get ( string . Format ( "{0}/{1}" , rackspaceCloudIdentity . CloudInstance , rackspaceCloudIdentity . Username ) , ( ) => Authenticate ( rackspaceCloudIdentity ) , forceCacheRefresh ) ;
270301
271302 return userAccess ;
272303 }
@@ -332,6 +363,8 @@ protected virtual Response ExecuteRESTRequest(CloudIdentity identity, string url
332363 return ExecuteRESTRequest < T > ( identity , urlPath , method , body , queryStringParameter , true , isTokenRequest , GetToken ( identity ) ) ;
333364 }
334365
366+ ProviderBase . CheckResponse ( response ) ;
367+
335368 return response ;
336369 }
337370 }
0 commit comments