<commit_before>package io.spacedog.services;

import io.spacedog.model.CredentialsSettings;
import io.spacedog.model.CredentialsSettings.OAuthSettings;
import io.spacedog.rest.SpaceRequest;
import io.spacedog.rest.SpaceResponse;
import io.spacedog.utils.Check;
import io.spacedog.utils.Credentials;
import io.spacedog.utils.Credentials.Level;
import io.spacedog.utils.Credentials.Session;
import io.spacedog.utils.Exceptions;
import net.codestory.http.Context;
import net.codestory.http.annotations.Post;
import net.codestory.http.payload.Payload;

public class EdfResourceV2 extends Resource {

	//
	// Routes
	//

	@Post("/1/service/oauth/v2/accessToken")
	@Post("/1/service/oauth/v2/accessToken/")
	public Payload getLoginV2(Context context) {
		Credentials credentials = login(context);

		return JsonPayload.json(//
				JsonPayload.builder()//
						.put(FIELD_ACCESS_TOKEN, credentials.accessToken()) //
						.put(FIELD_EXPIRES_IN, credentials.accessTokenExpiresIn()) //
						.node(FIELD_CREDENTIALS, credentials.toJson()));
	}

	//
	// implementation
	//

	private Credentials login(Context context) {

		OAuthSettings oauthSetting = checkOAuthSetting();
		Session session = newEdfSession(context, oauthSetting);
		String username = getEdfUsername(session, oauthSetting);
		String backendId = SpaceContext.backendId();

		CredentialsResource credentialsResource = CredentialsResource.get();
		Credentials credentials = credentialsResource.getByName(backendId, username, false)//
				.orElseGet(() -> new Credentials(backendId, username, Level.USER));

		credentials.setCurrentSession(session);

		if (credentials.id() == null)
			credentials = credentialsResource.create(credentials);
		else
			credentials = credentialsResource.update(credentials);

		return credentials;
	}

	private OAuthSettings checkOAuthSetting() {
		OAuthSettings oauthSettings = SettingsResource.get()//
				.load(CredentialsSettings.class).oauth;

		if (oauthSettings == null)
			throw Exceptions.illegalArgument("credentials OAuth settings are required");
		if (oauthSettings.clientId == null)
			throw Exceptions.illegalArgument("credentials OAuth [clientId] is required");
		if (oauthSettings.clientSecret == null)
			throw Exceptions.illegalArgument("credentials OAuth [clientSecret] is required");
		if (oauthSettings.backendUrl == null)
			throw Exceptions.illegalArgument("credentials OAuth [backend] is required");

		return oauthSettings;
	}

	String getEdfUsername(Session session, OAuthSettings oauthSetting) {
		SpaceResponse response = SpaceRequest.get("/gardian/oauth2/v2/tokeninfo")//
				.backend(oauthSetting.backendUrl)//
				.bearerAuth(session.accessToken())//
				.go();

		checkEdfOAuthError(response, "EDF OAuth v2 error fetching username");
		return response.getString("uid");
	}

	private Session newEdfSession(Context context, OAuthSettings oauthSetting) {
		String code = Check.notNullOrEmpty(context.get("code"), "code");
		String redirectUri = Check.notNullOrEmpty(context.get("redirect_uri"), "redirect_uri");

		SpaceResponse response = SpaceRequest.post("/gardian/oauth2/v2/token")//
				.backend(oauthSetting.backendUrl)//
				.basicAuth(oauthSetting.clientId, oauthSetting.clientSecret)//
				.bodyJson("grant_type", "authorization_code", "code", code, //
						"client_id", oauthSetting.clientId, "redirect_uri", redirectUri)//
				.go();

		checkEdfOAuthError(response, "EDF OAuth v2 error fetching access token");
		String accessToken = response.getString("access_token");
		long expiresIn = oauthSetting.useExpiresIn //
				? response.get("expires_in").asLong() //
				: CredentialsResource.get().getCheckSessionLifetime(context);

		return Session.newSession(accessToken, expiresIn);
	}

	private void checkEdfOAuthError(SpaceResponse response, String message) {

		if (response.status() >= 400)
			throw Exceptions.space(response.status(), message)//
					.code("edf-oauth-error").details(response.asJsonObject());
	}

	//
	// singleton
	//

	private static EdfResourceV2 singleton = new EdfResourceV2();

	static EdfResourceV2 get() {
		return singleton;
	}

	private EdfResourceV2() {
	}
}<commit_msg>Improves oauth v2 error handling for non json errors<commit_after>package io.spacedog.services;

import com.fasterxml.jackson.databind.node.ObjectNode;

import io.spacedog.core.Json8;
import io.spacedog.model.CredentialsSettings;
import io.spacedog.model.CredentialsSettings.OAuthSettings;
import io.spacedog.rest.SpaceRequest;
import io.spacedog.rest.SpaceResponse;
import io.spacedog.utils.Check;
import io.spacedog.utils.Credentials;
import io.spacedog.utils.Credentials.Level;
import io.spacedog.utils.Credentials.Session;
import io.spacedog.utils.Exceptions;
import net.codestory.http.Context;
import net.codestory.http.annotations.Post;
import net.codestory.http.payload.Payload;

public class EdfResourceV2 extends Resource {

	//
	// Routes
	//

	@Post("/1/service/oauth/v2/accessToken")
	@Post("/1/service/oauth/v2/accessToken/")
	public Payload getLoginV2(Context context) {
		Credentials credentials = login(context);

		return JsonPayload.json(//
				JsonPayload.builder()//
						.put(FIELD_ACCESS_TOKEN, credentials.accessToken()) //
						.put(FIELD_EXPIRES_IN, credentials.accessTokenExpiresIn()) //
						.node(FIELD_CREDENTIALS, credentials.toJson()));
	}

	//
	// implementation
	//

	private Credentials login(Context context) {

		OAuthSettings oauthSetting = checkOAuthSetting();
		Session session = newEdfSession(context, oauthSetting);
		String username = getEdfUsername(session, oauthSetting);
		String backendId = SpaceContext.backendId();

		CredentialsResource credentialsResource = CredentialsResource.get();
		Credentials credentials = credentialsResource.getByName(backendId, username, false)//
				.orElseGet(() -> new Credentials(backendId, username, Level.USER));

		credentials.setCurrentSession(session);

		if (credentials.id() == null)
			credentials = credentialsResource.create(credentials);
		else
			credentials = credentialsResource.update(credentials);

		return credentials;
	}

	private OAuthSettings checkOAuthSetting() {
		OAuthSettings oauthSettings = SettingsResource.get()//
				.load(CredentialsSettings.class).oauth;

		if (oauthSettings == null)
			throw Exceptions.illegalArgument("credentials OAuth settings are required");
		if (oauthSettings.clientId == null)
			throw Exceptions.illegalArgument("credentials OAuth [clientId] is required");
		if (oauthSettings.clientSecret == null)
			throw Exceptions.illegalArgument("credentials OAuth [clientSecret] is required");
		if (oauthSettings.backendUrl == null)
			throw Exceptions.illegalArgument("credentials OAuth [backend] is required");

		return oauthSettings;
	}

	String getEdfUsername(Session session, OAuthSettings oauthSetting) {
		SpaceResponse response = SpaceRequest.get("/gardian/oauth2/v2/tokeninfo")//
				.backend(oauthSetting.backendUrl)//
				.bearerAuth(session.accessToken())//
				.go();

		checkEdfOAuthError(response, "EDF OAuth v2 error fetching username");
		return response.getString("uid");
	}

	private Session newEdfSession(Context context, OAuthSettings oauthSetting) {
		String code = Check.notNullOrEmpty(context.get("code"), "code");
		String redirectUri = Check.notNullOrEmpty(context.get("redirect_uri"), "redirect_uri");

		SpaceResponse response = SpaceRequest.post("/gardian/oauth2/v2/token")//
				.backend(oauthSetting.backendUrl)//
				.basicAuth(oauthSetting.clientId, oauthSetting.clientSecret)//
				.bodyJson("grant_type", "authorization_code", "code", code, //
						"client_id", oauthSetting.clientId, "redirect_uri", redirectUri)//
				.go();

		checkEdfOAuthError(response, "EDF OAuth v2 error fetching access token");
		String accessToken = response.getString("access_token");
		long expiresIn = oauthSetting.useExpiresIn //
				? response.get("expires_in").asLong() //
				: CredentialsResource.get().getCheckSessionLifetime(context);

		return Session.newSession(accessToken, expiresIn);
	}

	private void checkEdfOAuthError(SpaceResponse response, String message) {

		if (response.status() >= 400) {

			ObjectNode details = response.isJson() ? response.asJsonObject() //
					: Json8.object("description", response.asString());

			throw Exceptions.space(response.status(), message)//
					.code("edf-oauth-error").details(details);
		}
	}

	//
	// singleton
	//

	private static EdfResourceV2 singleton = new EdfResourceV2();

	static EdfResourceV2 get() {
		return singleton;
	}

	private EdfResourceV2() {
	}
}
{'fraction_non_alphanumeric': 0.12185368148670901, 'fraction_numerical': 0.004822394730651611, 'mean_word_length': 5.017692852087756, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 1}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7588797', 'n_tokens_mistral': 2836, 'n_tokens_neox': 2552, 'n_words': 484}