committed by
							
								 GitHub
								GitHub
							
						
					
				
				 22 changed files with 290 additions and 67 deletions
			
			
		| @ -0,0 +1,76 @@ | |||||
|  | package com.databasir.core.domain.app.handler; | ||||
|  | 
 | ||||
|  | import com.databasir.core.domain.DomainErrors; | ||||
|  | import com.databasir.core.domain.app.exception.DatabasirAuthenticationException; | ||||
|  | import com.databasir.core.infrastructure.remote.gitlab.GitlabRemoteService; | ||||
|  | import com.databasir.dao.enums.OAuthAppType; | ||||
|  | import com.databasir.dao.tables.pojos.OauthAppPojo; | ||||
|  | import com.fasterxml.jackson.databind.JsonNode; | ||||
|  | import lombok.RequiredArgsConstructor; | ||||
|  | import org.springframework.stereotype.Component; | ||||
|  | import org.springframework.web.util.UriComponentsBuilder; | ||||
|  | 
 | ||||
|  | import java.util.Map; | ||||
|  | 
 | ||||
|  | @Component | ||||
|  | @RequiredArgsConstructor | ||||
|  | public class GitlabOpenAuthHandler implements OpenAuthHandler { | ||||
|  | 
 | ||||
|  |     private final GitlabRemoteService gitlabRemoteService; | ||||
|  | 
 | ||||
|  |     @Override | ||||
|  |     public boolean support(OAuthAppType oauthAppType) { | ||||
|  |         return OAuthAppType.GITLAB == oauthAppType; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     @Override | ||||
|  |     public String authorizationUrl(OauthAppPojo app, Map<String, String[]> params) { | ||||
|  |         if (!params.containsKey("redirect_uri")) { | ||||
|  |             throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception("缺少参数 redirect_uri", null); | ||||
|  |         } | ||||
|  |         String authUrl = app.getAuthUrl(); | ||||
|  |         String clientId = app.getClientId(); | ||||
|  |         String authorizeUrl = authUrl + "/oauth/authorize"; | ||||
|  |         String redirectUri = params.get("redirect_uri")[0]; | ||||
|  |         String url = UriComponentsBuilder.fromUriString(authorizeUrl) | ||||
|  |                 .queryParam("client_id", clientId) | ||||
|  |                 .queryParam("redirect_uri", redirectUri) | ||||
|  |                 .queryParam("response_type", "code") | ||||
|  |                 .queryParam("state", redirectUri) | ||||
|  |                 .encode() | ||||
|  |                 .build() | ||||
|  |                 .toUriString(); | ||||
|  |         return url; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     @Override | ||||
|  |     public OAuthProcessResult process(OauthAppPojo app, Map<String, String[]> requestParams) { | ||||
|  |         if (!requestParams.containsKey("redirect_uri")) { | ||||
|  |             throw DomainErrors.MISS_REQUIRED_PARAMETERS.exception("缺少参数 redirect_uri", null); | ||||
|  |         } | ||||
|  |         String url = app.getAuthUrl(); | ||||
|  |         String code = requestParams.get("code")[0]; | ||||
|  |         String state = requestParams.get("state")[0]; | ||||
|  |         String redirectUri = requestParams.get("redirect_uri")[0]; | ||||
|  |         JsonNode accessTokenData = | ||||
|  |                 gitlabRemoteService.getAccessToken(url, code, app.getClientId(), app.getClientSecret(), redirectUri); | ||||
|  |         if (accessTokenData == null) { | ||||
|  |             throw new DatabasirAuthenticationException(DomainErrors.NETWORK_ERROR.exception()); | ||||
|  |         } | ||||
|  |         String accessToken = accessTokenData.get("access_token").asText(); | ||||
|  |         JsonNode userData = gitlabRemoteService.getUser(app.getResourceUrl(), accessToken); | ||||
|  |         if (userData == null) { | ||||
|  |             throw new DatabasirAuthenticationException(DomainErrors.NETWORK_ERROR.exception()); | ||||
|  |         } | ||||
|  |         String email = userData.get("email").asText(); | ||||
|  |         String avatar = userData.get("avatar_url").asText(); | ||||
|  |         String name = userData.get("name").asText(); | ||||
|  |         OAuthProcessResult result = new OAuthProcessResult(); | ||||
|  |         result.setAvatar(avatar); | ||||
|  |         result.setEmail(email); | ||||
|  |         result.setNickname(name); | ||||
|  |         result.setUsername(email); | ||||
|  |         return result; | ||||
|  |     } | ||||
|  | 
 | ||||
|  | } | ||||
| @ -1,10 +1,15 @@ | |||||
| package com.databasir.core.domain.app.handler; | package com.databasir.core.domain.app.handler; | ||||
| 
 | 
 | ||||
|  | import com.databasir.dao.enums.OAuthAppType; | ||||
|  | import com.databasir.dao.tables.pojos.OauthAppPojo; | ||||
|  | 
 | ||||
|  | import java.util.Map; | ||||
|  | 
 | ||||
| public interface OpenAuthHandler { | public interface OpenAuthHandler { | ||||
| 
 | 
 | ||||
|     boolean support(String oauthAppType); |     boolean support(OAuthAppType oauthAppType); | ||||
| 
 | 
 | ||||
|     String authorization(String registrationId); |     String authorizationUrl(OauthAppPojo app, Map<String, String[]> requestParams); | ||||
| 
 | 
 | ||||
|     OAuthProcessResult process(OAuthProcessContext context); |     OAuthProcessResult process(OauthAppPojo app, Map<String, String[]> requestParams); | ||||
| } | } | ||||
|  | |||||
| @ -0,0 +1,36 @@ | |||||
|  | package com.databasir.core.domain.app.handler; | ||||
|  | 
 | ||||
|  | import com.databasir.dao.impl.OauthAppDao; | ||||
|  | import com.databasir.dao.tables.pojos.OauthAppPojo; | ||||
|  | import lombok.RequiredArgsConstructor; | ||||
|  | import org.springframework.stereotype.Component; | ||||
|  | 
 | ||||
|  | import java.util.List; | ||||
|  | import java.util.Map; | ||||
|  | 
 | ||||
|  | @Component | ||||
|  | @RequiredArgsConstructor | ||||
|  | public class OpenAuthHandlers { | ||||
|  | 
 | ||||
|  |     private final List<OpenAuthHandler> handlers; | ||||
|  | 
 | ||||
|  |     private final OauthAppDao oauthAppDao; | ||||
|  | 
 | ||||
|  |     public String authorizeUrl(String registrationId, Map<String, String[]> parameters) { | ||||
|  |         OauthAppPojo app = oauthAppDao.selectByRegistrationId(registrationId); | ||||
|  |         return handlers.stream() | ||||
|  |                 .filter(handler -> handler.support(app.getAppType())) | ||||
|  |                 .findFirst() | ||||
|  |                 .map(handler -> handler.authorizationUrl(app, parameters)) | ||||
|  |                 .orElseThrow(); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     public OAuthProcessResult process(String registrationId, Map<String, String[]> parameters) { | ||||
|  |         OauthAppPojo app = oauthAppDao.selectByRegistrationId(registrationId); | ||||
|  |         return handlers.stream() | ||||
|  |                 .filter(handler -> handler.support(app.getAppType())) | ||||
|  |                 .findFirst() | ||||
|  |                 .map(handler -> handler.process(app, parameters)) | ||||
|  |                 .orElseThrow(); | ||||
|  |     } | ||||
|  | } | ||||
| @ -0,0 +1,19 @@ | |||||
|  | package com.databasir.core.infrastructure.remote.gitlab; | ||||
|  | 
 | ||||
|  | import com.fasterxml.jackson.databind.JsonNode; | ||||
|  | import retrofit2.Call; | ||||
|  | import retrofit2.http.*; | ||||
|  | 
 | ||||
|  | public interface GitlabApiClient { | ||||
|  |     @GET | ||||
|  |     @Headers(value = { | ||||
|  |             "Accept: application/json" | ||||
|  |     }) | ||||
|  |     Call<JsonNode> getUser(@Url String url, @Header("Authorization") String token); | ||||
|  | 
 | ||||
|  |     @POST | ||||
|  |     @Headers(value = { | ||||
|  |             "Accept: application/json" | ||||
|  |     }) | ||||
|  |     Call<JsonNode> getAccessToken(@Url String url); | ||||
|  | } | ||||
| @ -0,0 +1,60 @@ | |||||
|  | package com.databasir.core.infrastructure.remote.gitlab; | ||||
|  | 
 | ||||
|  | import com.databasir.common.SystemException; | ||||
|  | import com.fasterxml.jackson.databind.JsonNode; | ||||
|  | import lombok.RequiredArgsConstructor; | ||||
|  | import lombok.extern.slf4j.Slf4j; | ||||
|  | import org.springframework.stereotype.Service; | ||||
|  | import org.springframework.web.util.UriComponentsBuilder; | ||||
|  | import retrofit2.Call; | ||||
|  | import retrofit2.Response; | ||||
|  | 
 | ||||
|  | import java.io.IOException; | ||||
|  | 
 | ||||
|  | @Service | ||||
|  | @RequiredArgsConstructor | ||||
|  | @Slf4j | ||||
|  | public class GitlabRemoteService { | ||||
|  | 
 | ||||
|  |     private final GitlabApiClient gitlabApiClient; | ||||
|  | 
 | ||||
|  |     public JsonNode getAccessToken(String baseUrl, | ||||
|  |                                    String code, | ||||
|  |                                    String clientId, | ||||
|  |                                    String clientSecret, | ||||
|  |                                    String redirectUri) { | ||||
|  |         String path = "/oauth/token"; | ||||
|  |         String uri = baseUrl + path; | ||||
|  |         String uriStr = UriComponentsBuilder.fromUriString(uri) | ||||
|  |                 .queryParam("client_id", clientId) | ||||
|  |                 .queryParam("client_secret", clientSecret) | ||||
|  |                 .queryParam("code", code) | ||||
|  |                 .queryParam("grant_type", "authorization_code") | ||||
|  |                 .queryParam("redirect_uri", redirectUri) | ||||
|  |                 .encode() | ||||
|  |                 .toUriString(); | ||||
|  |         return execute(gitlabApiClient.getAccessToken(uriStr)); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     public JsonNode getUser(String baseUrl, String accessToken) { | ||||
|  |         String tokenHeaderValue = "Bearer " + accessToken; | ||||
|  |         String uri = baseUrl + "/api/v4/user"; | ||||
|  |         return execute(gitlabApiClient.getUser(uri, tokenHeaderValue)); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     private <T> T execute(Call<T> call) { | ||||
|  |         try { | ||||
|  |             Response<T> response = call.execute(); | ||||
|  |             if (!response.isSuccessful()) { | ||||
|  |                 log.error("request error: " + call.request() + ", response = " + response); | ||||
|  |                 throw new SystemException("Call Remote Error"); | ||||
|  |             } else { | ||||
|  |                 log.info("response " + response); | ||||
|  |                 T body = response.body(); | ||||
|  |                 return body; | ||||
|  |             } | ||||
|  |         } catch (IOException e) { | ||||
|  |             throw new SystemException("System Error", e); | ||||
|  |         } | ||||
|  |     } | ||||
|  | } | ||||
| @ -0,0 +1,12 @@ | |||||
|  | package com.databasir.dao.converter; | ||||
|  | 
 | ||||
|  | import com.databasir.dao.enums.OAuthAppType; | ||||
|  | import org.jooq.impl.EnumConverter; | ||||
|  | 
 | ||||
|  | public class OAuthAppTypeConverter extends EnumConverter<String, OAuthAppType> { | ||||
|  | 
 | ||||
|  |     public OAuthAppTypeConverter() { | ||||
|  |         super(String.class, OAuthAppType.class); | ||||
|  |     } | ||||
|  | 
 | ||||
|  | } | ||||
					Loading…
					
					
				
		Reference in new issue