[squeak-dev] The Inbox: Monticello-ct.785.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Sep 8 13:19:14 UTC 2022


A new version of Monticello was added to project The Inbox:
http://source.squeak.org/inbox/Monticello-ct.785.mcz

==================== Summary ====================

Name: Monticello-ct.785
Author: ct
Time: 8 September 2022, 3:19:07.385836 pm
UUID: 9c69102f-1dd8-294a-acde-d8a3052b4e82
Ancestors: Monticello-mt.782

Proposal: When loading/saving a HTTP repository with insufficient authorization (no credentials/wrong password), allow the user to re-authenticate through a dialog window instead of displaying an unhandled NetworkError (401). Also adds support for nil as username/password.

Details: Slightly refactor #webClientDo: and senders. Only create authorization header if any credentials have been specified, which avoids two useless re-attempts for each insufficiently authorized requests. Handle WebAuthRequired exceptions by asking for the credentials again. Slightly improves multilingual support.

=============== Diff against Monticello-mt.782 ===============

Item was added:
+ ----- Method: MCHttpRepository>>authorizeRequest:forClient: (in category 'private') -----
+ authorizeRequest: aWebRequest forClient: aWebClient
+ 
+ 	(aWebClient username isNil and: [aWebClient password isNil]) ifFalse: [
+ 		aWebRequest headerAt: 'Authorization' put: 'Basic ',
+ 			((aWebClient username ifNil: ['']), ':', (aWebClient password ifNil: [''])) base64Encoded].!

Item was changed:
  ----- Method: MCHttpRepository>>httpGet:arguments: (in category 'private') -----
  httpGet: url arguments: arguments
  
  	| urlString |
  	urlString := arguments
  		ifNil: [ url ]
  		ifNotNil: [ 
  			| queryString |
  			queryString := WebUtils encodeUrlEncodedForm: arguments.
  			(url includes: $?)
  				ifTrue: [ url, '&', queryString ]
  				ifFalse: [ url, '?', queryString ] ].
  	urlString := self class rewriteUrl: urlString forDownload: true.
+ 	^self webClientDo: [ :client :requestBlock |
+ 		client httpGet: urlString do: requestBlock ]!
- 	^self webClientDo: [ :client | 
- 		client
- 			username: self user;
- 			password: self password;
- 			httpGet: urlString do: [ :request |
- 				request
- 					headerAt: 'Authorization' put: 'Basic ', (self user, ':', self password) base64Encoded;
- 					headerAt: 'Connection' put: 'Keep-Alive';
- 					headerAt: 'Accept' put: '*/*' ] ]!

Item was changed:
  ----- Method: MCHttpRepository>>password (in category 'accessing') -----
  password
  	self userAndPasswordFromSettingsDo: [:usr :pwd | ^pwd].
  
+ 	self user isEmptyOrNil ifTrue: [^password].
- 	self user isEmpty ifTrue: [^password ifNil: ['']].
  
  	password isEmptyOrNil ifTrue: [
+ 		self requestUserAndPassword].
- 		| answer |
- 		"Give the user a chance to change the login"
- 		answer := UIManager default request: 'User name for ', String cr, location
- 			initialAnswer: self user.
- 		answer isEmpty
- 			ifTrue: [^password]
- 			ifFalse: [self user: answer].
- 		
- 		password := UIManager default requestPassword: 'Password for "', self user, '" at ', String cr, location.
- 	].
  
  	^ password!

Item was added:
+ ----- Method: MCHttpRepository>>requestUserAndPassword (in category 'accessing') -----
+ requestUserAndPassword
+ 	"Give the user a chance to change the login"
+ 
+ 	| answer |
+ 	answer := Project uiManager
+ 		request: ('User name for\{1}' withCRs translated format: {location})
+ 		initialAnswer: (self user ifNil: ['']).
+ 	answer isEmpty
+ 		ifTrue: [^ false]
+ 		ifFalse: [self user: answer].
+ 	
+ 	password := Project uiManager
+ 		requestPassword: ('Password for "{1}" at\{2}' withCRs translated format: {self user. location}).
+ 	^ true!

Item was changed:
  ----- Method: MCHttpRepository>>user (in category 'accessing') -----
+ user 
- user
  	self userAndPasswordFromSettingsDo: [:usr :pwd | ^usr].
  	"not in settings"
+ 	^user!
- 	^user ifNil: ['']!

Item was changed:
  ----- Method: MCHttpRepository>>webClientDo: (in category 'private') -----
  webClientDo: aBlock
  
  	| client attemptsLeft response result |
  	self class useSharedWebClientInstance ifTrue: [
  		"Acquire webClient by atomically storing it in the client variable and setting its value to nil."
  		client := webClient.
  		webClient := nil ].
  	
  	client 
  		ifNil: [ client := WebClient new ]
  		ifNotNil: [ 
  			"Attempt to avoid an error by recreating the underlying stream."
  			client isConnected ifFalse: [ client close ] ].
  		
  	attemptsLeft := 3.
  	response := nil.
  	[ response isNil and: [ attemptsLeft > 0 ] ] whileTrue: [
+ 		client
+ 			username: self user;
+ 			password: self password.
+ 		response := [ aBlock value: client value: [:request |
+ 				self authorizeRequest: request forClient: client.
+ 				request
+ 					headerAt: 'Connection' put: 'Keep-Alive';
+ 					headerAt: 'Accept' put: '*/*' ] ]
+ 			on: WebAuthRequired do: [ :ex |
+ 				self requestUserAndPassword ifTrue: [
+ 					ex client
+ 						username: self user;
+ 						password: self password.
+ 					self authorizeRequest: ex request forClient: ex client.
+ 					ex resume: true ].
+ 				ex pass ]
+ 			on: NetworkError do: [ :error |
- 		response := [ aBlock value: client ]
- 			on: NetworkError
- 			do: [ :error |
  				attemptsLeft = 0 ifTrue: [ error pass ].
  				(3 - attemptsLeft) seconds asDelay wait.
  				attemptsLeft := attemptsLeft - 1.
  				nil "The response" ] ].	
  	
  	result := (response code between: 200 and: 299) 
  		ifFalse: [
  			response content. "Make sure content is read."
  			nil ]
  		ifTrue: [ 
  			(RWBinaryOrTextStream with: (
  				response contentWithProgress:  [ :total :amount |
  					HTTPProgress new 
  						total: total;
  						amount: amount;
  						signal ])) reset ].
  
  	self class useSharedWebClientInstance
  		ifTrue: [
  			"Save the WebClient instance for reuse, but only if there is no client cached."
  			webClient  
  				ifNil: [ webClient := client ]
  				ifNotNil: [ client close ] ]
  		ifFalse: [ client close ].
  
  	(response code = 404 "Not Found" or: [response code = 410 "Gone"]) ifTrue: [
  		"Need to distinguish between lookup errors and connection errors. Lookup errors will be handled by some senders following the EAFP principle. See #versionNamed:."
  		(NotFound object: response url) signal ].
  	result ifNil: [ NetworkError signal: 'Could not access ', location ].
  	^result!

Item was changed:
  ----- Method: MCHttpRepository>>writeStreamForFileNamed:replace:do: (in category 'private') -----
  writeStreamForFileNamed: aString replace: ignoreBoolean do: aBlock
  
  	| stream urlString |
  	stream := RWBinaryOrTextStream on: String new.
  	aBlock value: stream.
  	urlString := self urlForFileNamed: aString.
  	urlString := self class rewriteUrl: urlString forDownload: false.
+ 	^self displayProgress: ('Uploading {1}' translated format: {aString}) during: [
+ 		self webClientDo: [ :client :requestBlock |
+ 			client httpPut: urlString
+ 				content: stream contents
+ 				type: nil
+ 				do: requestBlock ] ]!
- 	^self displayProgress: 'Uploading ', aString during: [
- 		self webClientDo: [ :client |
- 			client
- 				username: self user;
- 				password: self password;
- 				httpPut: urlString
- 					content: stream contents
- 					type: nil
- 					do: [ :request |
- 						request
- 							headerAt: 'Authorization' put: 'Basic ', (self user, ':', self password) base64Encoded;
- 							headerAt: 'Connection' put: 'Keep-Alive';
- 							headerAt: 'Accept' put: '*/*'  ] ] ]!



More information about the Squeak-dev mailing list