package app.fedilab.fedilabtube; /* Copyright 2020 Thomas Schneider * * This file is a part of TubeLab * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * TubeLab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with TubeLab; if not, * see . */ import android.content.Intent; import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.Bundle; import android.text.SpannableString; import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.text.style.UnderlineSpan; import android.view.MenuItem; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import com.google.android.material.textfield.TextInputLayout; import org.json.JSONException; import org.json.JSONObject; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Arrays; import java.util.HashMap; import app.fedilab.fedilabtube.asynctasks.UpdateAccountInfoAsyncTask; import app.fedilab.fedilabtube.client.HttpsConnection; import app.fedilab.fedilabtube.helper.Helper; import es.dmoral.toasty.Toasty; public class LoginActivity extends AppCompatActivity { //Peertube notification type public static int NEW_VIDEO_FROM_SUBSCRIPTION = 1; // public static int NEW_COMMENT_ON_MY_VIDEO = 2; // public static int NEW_VIDEO_ABUSE_FOR_MODERATORS = 3; public static int BLACKLIST_ON_MY_VIDEO = 4; public static int UNBLACKLIST_ON_MY_VIDEO = 5; public static int MY_VIDEO_PUBLISHED = 6; public static int MY_VIDEO_IMPORT_SUCCESS = 7; public static int MY_VIDEO_IMPORT_ERROR = 8; private static String client_id; private static String client_secret; private EditText login_uid; private EditText login_passwd; private Button connectionButton; private String actionToken; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); if (getSupportActionBar() != null) getSupportActionBar().setDisplayHomeAsUpEnabled(true); TextView create_an_account_peertube = findViewById(R.id.create_an_account_peertube); SpannableString content_create = new SpannableString(getString(R.string.join_peertube)); content_create.setSpan(new UnderlineSpan(), 0, content_create.length(), 0); content_create.setSpan(new ForegroundColorSpan(ContextCompat.getColor(LoginActivity.this, R.color.colorAccent)), 0, content_create.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); create_an_account_peertube.setText(content_create); create_an_account_peertube.setOnClickListener(v -> { Intent mainActivity = new Intent(LoginActivity.this, PeertubeRegisterActivity.class); Bundle b = new Bundle(); mainActivity.putExtras(b); startActivity(mainActivity); }); login_uid = findViewById(R.id.login_uid); login_passwd = findViewById(R.id.login_passwd); if (Helper.isTablet(LoginActivity.this)) { TextInputLayout login_uid_container = findViewById(R.id.login_uid_container); ViewGroup.LayoutParams layoutParamsU = login_uid_container.getLayoutParams(); layoutParamsU.width = (int) Helper.convertDpToPixel(300, LoginActivity.this); login_uid_container.setLayoutParams(layoutParamsU); TextInputLayout login_passwd_container = findViewById(R.id.login_passwd_container); ViewGroup.LayoutParams layoutParamsP = login_passwd_container.getLayoutParams(); layoutParamsP.width = (int) Helper.convertDpToPixel(300, LoginActivity.this); login_passwd_container.setLayoutParams(layoutParamsP); } connectionButton = findViewById(R.id.login_button); login_uid.setOnFocusChangeListener((v, hasFocus) -> { if (!hasFocus) { if (android.util.Patterns.EMAIL_ADDRESS.matcher(login_uid.getText().toString().trim()).matches()) { String[] emailArray = login_uid.getText().toString().split("@"); if (emailArray.length > 1 && Arrays.asList(Helper.openid).contains(emailArray[1])) { connectionButton.callOnClick(); } } } }); connectionButton.setOnClickListener(v -> { if (!android.util.Patterns.EMAIL_ADDRESS.matcher(login_uid.getText().toString().trim()).matches()) { Toasty.error(LoginActivity.this, getString(R.string.email_error)).show(); return; } String[] emailArray = login_uid.getText().toString().split("@"); if (emailArray.length > 1 && !Arrays.asList(Helper.valideEmails).contains(emailArray[1])) { Toasty.error(LoginActivity.this, getString(R.string.email_error_domain, emailArray[1])).show(); return; } String host = emailArray[1]; String instance = Helper.getPeertubeUrl(host); final HashMap parameters = new HashMap<>(); connectionButton.setEnabled(false); try { instance = URLEncoder.encode(instance, "utf-8"); } catch (UnsupportedEncodingException e) { Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); } if (Arrays.asList(Helper.openid).contains(host)) { String finalInstance = instance; new Thread(() -> { try { actionToken = "/api/v1/oauth-clients/local"; String response = new HttpsConnection(LoginActivity.this).get("https://" + finalInstance + actionToken, 30, null, null); if (response == null) { runOnUiThread(() -> { connectionButton.setEnabled(true); Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); }); return; } JSONObject resobj; resobj = new JSONObject(response); client_id = resobj.get(Helper.CLIENT_ID).toString(); client_secret = resobj.get(Helper.CLIENT_SECRET).toString(); SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.CLIENT_ID, client_id); editor.putString(Helper.CLIENT_SECRET, client_secret); editor.apply(); parameters.clear(); parameters.put(Helper.CLIENT_ID, sharedpreferences.getString(Helper.CLIENT_ID, null)); parameters.put(Helper.CLIENT_SECRET, sharedpreferences.getString(Helper.CLIENT_SECRET, null)); Intent intent = new Intent(LoginActivity.this, WebviewConnectActivity.class); Bundle b = new Bundle(); b.putString("url", "https://" + Helper.getPeertubeUrl(host) + "/plugins/auth-openid-connect/0.0.1/auth/openid-connect"); intent.putExtras(b); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } catch (Exception e) { e.printStackTrace(); runOnUiThread(() -> { connectionButton.setEnabled(true); Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); }); } }).start(); } else { parameters.clear(); parameters.put(Helper.CLIENT_NAME, Helper.CLIENT_NAME_VALUE); parameters.put(Helper.REDIRECT_URIS, Helper.REDIRECT_CONTENT); parameters.put(Helper.SCOPES, Helper.OAUTH_SCOPES_PEERTUBE); parameters.put(Helper.WEBSITE, Helper.WEBSITE_VALUE); String finalInstance = instance; new Thread(() -> { try { actionToken = "/api/v1/oauth-clients/local"; String response = new HttpsConnection(LoginActivity.this).get("https://" + finalInstance + actionToken, 30, parameters, null); if (response == null) { runOnUiThread(() -> { connectionButton.setEnabled(true); Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); }); return; } JSONObject resobj; try { resobj = new JSONObject(response); client_id = resobj.get(Helper.CLIENT_ID).toString(); client_secret = resobj.get(Helper.CLIENT_SECRET).toString(); SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.CLIENT_ID, client_id); editor.putString(Helper.CLIENT_SECRET, client_secret); editor.apply(); parameters.clear(); parameters.put(Helper.CLIENT_ID, sharedpreferences.getString(Helper.CLIENT_ID, null)); parameters.put(Helper.CLIENT_SECRET, sharedpreferences.getString(Helper.CLIENT_SECRET, null)); parameters.put("grant_type", "password"); try { parameters.put("username", URLEncoder.encode(login_uid.getText().toString().trim().toLowerCase(), "UTF-8")); } catch (UnsupportedEncodingException e) { parameters.put("username", login_uid.getText().toString().trim().toLowerCase()); } try { parameters.put("password", URLEncoder.encode(login_passwd.getText().toString(), "UTF-8")); } catch (UnsupportedEncodingException e) { parameters.put("password", login_passwd.getText().toString()); } parameters.put("scope", "user"); String oauthUrl = "/api/v1/users/token"; try { String responseLogin = new HttpsConnection(LoginActivity.this).post("https://" + finalInstance + oauthUrl, 30, parameters, null); runOnUiThread(() -> { JSONObject resobjLogin; try { resobjLogin = new JSONObject(responseLogin); String token = resobjLogin.getString("access_token"); String refresh_token = resobjLogin.getString("refresh_token"); editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, token); editor.putString(Helper.PREF_INSTANCE, host); editor.apply(); //Update the account with the token; new UpdateAccountInfoAsyncTask(LoginActivity.this, token, client_id, client_secret, refresh_token, host).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } catch (JSONException e) { e.printStackTrace(); runOnUiThread(() -> connectionButton.setEnabled(true)); } }); } catch (final Exception e) { e.printStackTrace(); runOnUiThread(() -> { connectionButton.setEnabled(true); String message; if (e.getLocalizedMessage() != null && e.getLocalizedMessage().trim().length() > 0) message = e.getLocalizedMessage(); else if (e.getMessage() != null && e.getMessage().trim().length() > 0) message = e.getMessage(); else message = getString(R.string.client_error); Toasty.error(LoginActivity.this, message, Toast.LENGTH_LONG).show(); }); } } catch (JSONException e) { e.printStackTrace(); e.printStackTrace(); runOnUiThread(() -> connectionButton.setEnabled(true)); } } catch (final Exception e) { e.printStackTrace(); runOnUiThread(() -> { connectionButton.setEnabled(true); String message = null; if (e.getLocalizedMessage() != null) { message = e.getMessage(); } if (message == null) { message = getString(R.string.client_error); } Toasty.error(LoginActivity.this, message, Toast.LENGTH_LONG).show(); }); } }).start(); } }); } @Override protected void onResume() { super.onResume(); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return super.onOptionsItemSelected(item); } @Override public void onDestroy() { super.onDestroy(); } }