|  |  |  | @ -3,19 +3,37 @@ package alfred.web.http | 
		
	
		
			
				|  |  |  |  | import alfred.web.core.build.BuildConfig | 
		
	
		
			
				|  |  |  |  | import alfred.web.core.build.BuildId | 
		
	
		
			
				|  |  |  |  | import alfred.web.core.build.Builds | 
		
	
		
			
				|  |  |  |  | import jakarta.servlet.http.HttpServletRequest | 
		
	
		
			
				|  |  |  |  | import org.springframework.http.HttpHeaders | 
		
	
		
			
				|  |  |  |  | import org.springframework.http.HttpStatus | 
		
	
		
			
				|  |  |  |  | import org.springframework.http.ResponseEntity | 
		
	
		
			
				|  |  |  |  | import org.springframework.stereotype.Service | 
		
	
		
			
				|  |  |  |  | import java.util.Base64 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | @Service | 
		
	
		
			
				|  |  |  |  | class Security( | 
		
	
		
			
				|  |  |  |  |     val builds: Builds | 
		
	
		
			
				|  |  |  |  | ) { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     fun <T> requireKey(build: BuildId, apikey: String?, block: (BuildConfig) -> T): ResponseEntity<*> { | 
		
	
		
			
				|  |  |  |  |     private val unauthorized = ResponseEntity<Any>( | 
		
	
		
			
				|  |  |  |  |         HttpHeaders().also { | 
		
	
		
			
				|  |  |  |  |             it.add(HttpHeaders.WWW_AUTHENTICATE, "Bearer") | 
		
	
		
			
				|  |  |  |  |             it.add(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Alfred\"") | 
		
	
		
			
				|  |  |  |  |         }, | 
		
	
		
			
				|  |  |  |  |         HttpStatus.UNAUTHORIZED | 
		
	
		
			
				|  |  |  |  |     ) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     fun <T> requireAuth( | 
		
	
		
			
				|  |  |  |  |         build: BuildId, | 
		
	
		
			
				|  |  |  |  |         request: HttpServletRequest, | 
		
	
		
			
				|  |  |  |  |         block: (BuildConfig) -> T | 
		
	
		
			
				|  |  |  |  |     ): ResponseEntity<*> { | 
		
	
		
			
				|  |  |  |  |         val auth = request.getHeader("Authorization") ?: return unauthorized | 
		
	
		
			
				|  |  |  |  |         val token = bearerToken(auth) ?: basicAuthToken(auth) ?: return unauthorized | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         val buildConfig = builds.buildConfig(build) | 
		
	
		
			
				|  |  |  |  |         if (buildConfig.apikey != "" && buildConfig.apikey != apikey) { | 
		
	
		
			
				|  |  |  |  |             return ResponseEntity<T>(HttpStatus.UNAUTHORIZED) | 
		
	
		
			
				|  |  |  |  |         if (buildConfig.apikey != "" && buildConfig.apikey != token) { | 
		
	
		
			
				|  |  |  |  |             return unauthorized | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         val entity = block(buildConfig) | 
		
	
	
		
			
				
					|  |  |  | @ -26,4 +44,21 @@ class Security( | 
		
	
		
			
				|  |  |  |  |         return ResponseEntity.ok(entity) | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     private fun bearerToken(authHeader: String): String? { | 
		
	
		
			
				|  |  |  |  |         return if (authHeader.startsWith("Bearer ")) { | 
		
	
		
			
				|  |  |  |  |             authHeader.substring(7) | 
		
	
		
			
				|  |  |  |  |         } else { | 
		
	
		
			
				|  |  |  |  |             null | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     private fun basicAuthToken(authHeader: String): String? { | 
		
	
		
			
				|  |  |  |  |         return if (authHeader.startsWith("Basic ")) { | 
		
	
		
			
				|  |  |  |  |             String(Base64.getDecoder().decode(authHeader.substring(6))) | 
		
	
		
			
				|  |  |  |  |                 .split(":")[1] | 
		
	
		
			
				|  |  |  |  |         } else { | 
		
	
		
			
				|  |  |  |  |             null | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | 
 |