package org.mian.gitnex.activities; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.os.Handler; import android.widget.ArrayAdapter; import androidx.annotation.NonNull; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import io.mikael.urlbuilder.UrlBuilder; import java.net.URI; import java.util.Objects; import org.gitnex.tea4j.v2.models.GeneralAPISettings; import org.gitnex.tea4j.v2.models.ServerVersion; import org.gitnex.tea4j.v2.models.User; import org.mian.gitnex.R; import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.database.api.BaseApi; import org.mian.gitnex.database.api.UserAccountsApi; import org.mian.gitnex.database.models.UserAccount; import org.mian.gitnex.databinding.ActivityAddNewAccountBinding; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.PathsHelper; import org.mian.gitnex.helpers.SnackBar; import org.mian.gitnex.helpers.UrlHelper; import org.mian.gitnex.helpers.Version; import org.mian.gitnex.structs.Protocol; import retrofit2.Call; import retrofit2.Callback; /** * @author M M Arif */ public class AddNewAccountActivity extends BaseActivity { private ActivityAddNewAccountBinding viewBinding; private String spinnerSelectedValue; private Version giteaVersion; private int maxResponseItems = 50; private int defaultPagingNumber = 30; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); viewBinding = ActivityAddNewAccountBinding.inflate(getLayoutInflater()); setContentView(viewBinding.getRoot()); getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT)); viewBinding.instanceUrl.setText(getIntent().getStringExtra("instanceUrl")); viewBinding.loginToken.setText(getIntent().getStringExtra("token")); String scheme = getIntent().getStringExtra("scheme"); if (scheme != null && scheme.equals("http")) { viewBinding.protocolSpinner.setText(Protocol.HTTP.toString()); spinnerSelectedValue = Protocol.HTTP.toString(); } else { // default is https viewBinding.protocolSpinner.setText(Protocol.HTTPS.toString()); spinnerSelectedValue = Protocol.HTTPS.toString(); } ArrayAdapter adapterProtocols = new ArrayAdapter<>(ctx, R.layout.list_spinner_items, Protocol.values()); viewBinding.topAppBar.setNavigationOnClickListener(v -> finish()); viewBinding.protocolSpinner.setAdapter(adapterProtocols); viewBinding.protocolSpinner.setOnItemClickListener( (parent, view1, position, id) -> spinnerSelectedValue = String.valueOf(parent.getItemAtPosition(position))); viewBinding.topAppBar.setOnMenuItemClickListener( menuItem -> { int id = menuItem.getItemId(); if (id == R.id.addAccount) { processLogin(); return true; } else { return super.onOptionsItemSelected(menuItem); } }); } private void processLogin() { try { String instanceUrlET = String.valueOf(viewBinding.instanceUrl.getText()) .replaceAll("[\\uFEFF|#]", "") .trim(); String loginToken = String.valueOf(viewBinding.loginToken.getText()) .replaceAll("[\\uFEFF|#]", "") .trim(); String protocol = spinnerSelectedValue; if (protocol == null) { SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.protocolEmptyError)); return; } if (instanceUrlET.isEmpty()) { SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.emptyFieldURL)); return; } if (loginToken.isEmpty()) { SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.loginTokenError)); return; } URI rawInstanceUrl = UrlBuilder.fromString(UrlHelper.fixScheme(instanceUrlET, "http")).toUri(); URI instanceUrl = UrlBuilder.fromUri(rawInstanceUrl) .withScheme(protocol.toLowerCase()) .withPath(PathsHelper.join(rawInstanceUrl.getPath(), "/api/v1/")) .toUri(); versionCheck(instanceUrl.toString(), loginToken); serverPageLimitSettings(); } catch (Exception e) { SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.malformedUrl)); } } private void versionCheck(final String instanceUrl, final String loginToken) { Call callVersion = RetrofitClient.getApiInterface(ctx, instanceUrl, "token " + loginToken, null) .getVersion(); callVersion.enqueue( new Callback<>() { @Override public void onResponse( @NonNull final Call callVersion, @NonNull retrofit2.Response responseVersion) { if (responseVersion.code() == 200) { ServerVersion version = responseVersion.body(); assert version != null; if (!Version.valid(version.getVersion())) { SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.versionUnknown)); return; } giteaVersion = new Version(version.getVersion()); if (giteaVersion.less(getString(R.string.versionLow))) { MaterialAlertDialogBuilder materialAlertDialogBuilder = new MaterialAlertDialogBuilder(ctx) .setTitle( getString( R.string.versionAlertDialogHeader)) .setMessage( getResources() .getString( R.string .versionUnsupportedOld, version.getVersion())) .setNeutralButton( getString(R.string.cancelButton), null) .setPositiveButton( getString(R.string.textContinue), (dialog, which) -> { dialog.dismiss(); login(instanceUrl, loginToken); }); materialAlertDialogBuilder.create().show(); } else if (giteaVersion.lessOrEqual(getString(R.string.versionHigh))) { login(instanceUrl, loginToken); } else { SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.versionUnsupportedNew)); login(instanceUrl, loginToken); } } else if (responseVersion.code() == 401) { SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.unauthorizedApiError)); } else if (responseVersion.code() == 403) { login(instanceUrl, loginToken); } } private void login(String instanceUrl, String loginToken) { setupNewAccountWithToken(instanceUrl, loginToken); } @Override public void onFailure( @NonNull Call callVersion, @NonNull Throwable t) { SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.genericServerResponseError)); } }); } private void serverPageLimitSettings() { Call generalAPISettings = RetrofitClient.getApiInterface(ctx).getGeneralAPISettings(); generalAPISettings.enqueue( new Callback<>() { @Override public void onResponse( @NonNull final Call generalAPISettings, @NonNull retrofit2.Response response) { if (response.code() == 200 && response.body() != null) { if (response.body().getMaxResponseItems() != null) { maxResponseItems = Math.toIntExact(response.body().getMaxResponseItems()); } if (response.body().getDefaultPagingNum() != null) { defaultPagingNumber = Math.toIntExact(response.body().getDefaultPagingNum()); } } } @Override public void onFailure( @NonNull Call generalAPISettings, @NonNull Throwable t) {} }); } private void setupNewAccountWithToken(String instanceUrl, final String loginToken) { Call call = RetrofitClient.getApiInterface(ctx, instanceUrl, "token " + loginToken, null) .userGetCurrent(); call.enqueue( new Callback<>() { @Override public void onResponse( @NonNull Call call, @NonNull retrofit2.Response response) { User userDetails = response.body(); switch (response.code()) { case 200: assert userDetails != null; // insert new account to db if does not exist String accountName = userDetails.getLogin() + "@" + instanceUrl; UserAccountsApi userAccountsApi = BaseApi.getInstance(ctx, UserAccountsApi.class); boolean userAccountExists = Objects.requireNonNull(userAccountsApi) .userAccountExists(accountName); if (!userAccountExists) { long id = userAccountsApi.createNewAccount( accountName, instanceUrl, userDetails.getLogin(), loginToken, giteaVersion.toString(), maxResponseItems, defaultPagingNumber); UserAccount account = userAccountsApi.getAccountById((int) id); AppUtil.switchToAccount(AddNewAccountActivity.this, account); SnackBar.success( ctx, findViewById(android.R.id.content), getString(R.string.accountAddedMessage)); MainActivity.refActivity = true; new Handler().postDelayed(() -> finish(), 3000); } else { UserAccount account = userAccountsApi.getAccountByName(accountName); if (account.isLoggedIn()) { SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.accountAlreadyExistsError)); AppUtil.switchToAccount(ctx, account); } else { userAccountsApi.updateTokenByAccountName( accountName, loginToken); userAccountsApi.login(account.getAccountId()); AppUtil.switchToAccount( AddNewAccountActivity.this, account); } } break; case 401: SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.unauthorizedApiError)); break; default: SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.genericApiError, response.code())); } } @Override public void onFailure(@NonNull Call call, @NonNull Throwable t) { SnackBar.error( ctx, findViewById(android.R.id.content), getString(R.string.genericError)); } }); } }