Fix app asking for credential on every startup

This commit is contained in:
CappielloAntonio 2021-07-28 09:20:22 +02:00
parent a21a051cb5
commit 7bd2b10165
6 changed files with 116 additions and 52 deletions

View file

@ -44,8 +44,10 @@ public class App extends Application {
String server = PreferenceUtil.getInstance(context).getServer(); String server = PreferenceUtil.getInstance(context).getServer();
String username = PreferenceUtil.getInstance(context).getUser(); String username = PreferenceUtil.getInstance(context).getUser();
String password = PreferenceUtil.getInstance(context).getPassword(); String password = PreferenceUtil.getInstance(context).getPassword();
String token = PreferenceUtil.getInstance(context).getToken();
String salt = PreferenceUtil.getInstance(context).getSalt();
SubsonicPreferences preferences = new SubsonicPreferences(server, username, password); SubsonicPreferences preferences = new SubsonicPreferences(server, username, password, token, salt);
return new Subsonic(preferences); return new Subsonic(preferences);
} }

View file

@ -0,0 +1,10 @@
package com.cappielloantonio.play.interfaces;
import java.util.List;
public interface SystemCallback {
void onError(Exception exception);
void onSuccess(String token, String salt);
}

View file

@ -0,0 +1,46 @@
package com.cappielloantonio.play.repository;
import android.app.Application;
import com.cappielloantonio.play.App;
import com.cappielloantonio.play.interfaces.SystemCallback;
import com.cappielloantonio.play.subsonic.api.system.SystemClient;
import com.cappielloantonio.play.subsonic.models.ResponseStatus;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import retrofit2.Call;
import retrofit2.Callback;
public class SystemRepository {
private static final String TAG = "SongRepository";
private SystemClient systemClient;
public SystemRepository(Application application) {
systemClient = App.getSubsonicClientInstance(application, false).getSystemClient();
}
public void checkUserCredential(SystemCallback callback) {
systemClient
.ping()
.enqueue(new Callback<SubsonicResponse>() {
@Override
public void onResponse(Call<SubsonicResponse> call, retrofit2.Response<SubsonicResponse> response) {
if (response.body().getStatus().getValue().equals(ResponseStatus.FAILED)) {
callback.onError(new Exception(response.body().getError().getCode().getValue() + " - " + response.body().getError().getMessage()));
} else if (response.body().getStatus().getValue().equals(ResponseStatus.OK)) {
String salt = response.raw().request().url().queryParameter("s");
String token = response.raw().request().url().queryParameter("t");
callback.onSuccess(token, salt);
} else {
callback.onError(new Exception("Empty response"));
}
}
@Override
public void onFailure(Call<SubsonicResponse> call, Throwable t) {
callback.onError(new Exception(t.getMessage()));
}
});
}
}

View file

@ -7,16 +7,16 @@ import java.util.UUID;
public class SubsonicPreferences { public class SubsonicPreferences {
private String serverUrl; private String serverUrl;
private String username; private String username;
private String clientName = "SubsonicJavaClient"; private String clientName = "Play for Subsonic";
private int streamBitRate = 320;
private String streamFormat = "mp3";
private final SubsonicAuthentication authentication; private SubsonicAuthentication authentication;
public SubsonicPreferences(String serverUrl, String username, String password) { public SubsonicPreferences(String serverUrl, String username, String password, String token, String salt) {
this.serverUrl = serverUrl; this.serverUrl = serverUrl;
this.username = username; this.username = username;
this.authentication = new SubsonicAuthentication(password); if(password != null) this.authentication = new SubsonicAuthentication(password);
if(token != null) this.authentication.setToken(token);
if(salt != null) this.authentication.setSalt(salt);
} }
public String getServerUrl() { public String getServerUrl() {
@ -31,14 +31,6 @@ public class SubsonicPreferences {
return clientName; return clientName;
} }
public int getStreamBitRate() {
return streamBitRate;
}
public String getStreamFormat() {
return streamFormat;
}
public SubsonicAuthentication getAuthentication() { public SubsonicAuthentication getAuthentication() {
return authentication; return authentication;
} }
@ -63,6 +55,14 @@ public class SubsonicPreferences {
return token; return token;
} }
public void setSalt(String salt) {
this.salt = salt;
}
public void setToken(String token) {
this.token = token;
}
void update(String password) { void update(String password) {
this.salt = UUID.randomUUID().toString(); this.salt = UUID.randomUUID().toString();
this.token = StringUtil.tokenize(password + salt); this.token = StringUtil.tokenize(password + salt);

View file

@ -14,19 +14,11 @@ import androidx.fragment.app.Fragment;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.databinding.FragmentLoginBinding; import com.cappielloantonio.play.databinding.FragmentLoginBinding;
import com.cappielloantonio.play.helper.ErrorHelper; import com.cappielloantonio.play.interfaces.SystemCallback;
import com.cappielloantonio.play.subsonic.models.Genre; import com.cappielloantonio.play.repository.SystemRepository;
import com.cappielloantonio.play.subsonic.models.ResponseStatus;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.ui.activity.MainActivity; import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.util.PreferenceUtil; import com.cappielloantonio.play.util.PreferenceUtil;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
public class LoginFragment extends Fragment { public class LoginFragment extends Fragment {
private static final String TAG = "LoginFragment"; private static final String TAG = "LoginFragment";
@ -37,6 +29,8 @@ public class LoginFragment extends Fragment {
private String password; private String password;
private String server; private String server;
private SystemRepository systemRepository;
@Nullable @Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -56,9 +50,11 @@ public class LoginFragment extends Fragment {
} }
private void init() { private void init() {
systemRepository = new SystemRepository(App.getInstance());
bind.loginButton.setOnClickListener(v -> { bind.loginButton.setOnClickListener(v -> {
if (validateInput()) { if (validateInput()) {
saveServerPreference(server, username, password); saveServerPreference(server, username, password, null, null);
authenticate(); authenticate();
} }
}); });
@ -82,31 +78,18 @@ public class LoginFragment extends Fragment {
return true; return true;
} }
private void saveServerPreference(String server, String user, String password) { private void authenticate() {
PreferenceUtil.getInstance(requireContext()).setUser(user); systemRepository.checkUserCredential(new SystemCallback() {
PreferenceUtil.getInstance(requireContext()).setServer(server); @Override
PreferenceUtil.getInstance(requireContext()).setPassword(password); public void onError(Exception exception) {
Log.e(TAG, exception.getMessage());
Toast.makeText(requireContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
} }
private void authenticate() {
App.getSubsonicClientInstance(requireContext(), true)
.getSystemClient()
.ping()
.enqueue(new Callback<SubsonicResponse>() {
@Override @Override
public void onResponse(Call<SubsonicResponse> call, retrofit2.Response<SubsonicResponse> response) { public void onSuccess(String token, String salt) {
if (response.body().getStatus().getValue().equals(ResponseStatus.FAILED)) { saveServerPreference(null, null, null, token, salt);
ErrorHelper.handle(requireContext(), response.body().getError().getCode().getValue(), response.body().getError().getMessage());
} else if (response.body().getStatus().getValue().equals(ResponseStatus.OK)) {
enter(); enter();
} else {
Toast.makeText(requireContext(), "Empty response", Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call<SubsonicResponse> call, Throwable t) {
Log.e(TAG, t.getMessage());
Toast.makeText(requireContext(), t.getMessage(), Toast.LENGTH_LONG).show();
} }
}); });
} }
@ -114,4 +97,16 @@ public class LoginFragment extends Fragment {
private void enter() { private void enter() {
activity.goFromLogin(); activity.goFromLogin();
} }
private void saveServerPreference(String server, String user, String password, String token, String salt) {
if (user != null) PreferenceUtil.getInstance(requireContext()).setUser(user);
if (server != null) PreferenceUtil.getInstance(requireContext()).setServer(server);
if (password != null) PreferenceUtil.getInstance(requireContext()).setPassword(password);
if (token != null && salt != null) {
PreferenceUtil.getInstance(requireContext()).setPassword(null);
PreferenceUtil.getInstance(requireContext()).setToken(token);
PreferenceUtil.getInstance(requireContext()).setSalt(salt);
}
}
} }

View file

@ -20,6 +20,7 @@ public class PreferenceUtil {
public static final String USER = "user"; public static final String USER = "user";
public static final String PASSWORD = "password"; public static final String PASSWORD = "password";
public static final String TOKEN = "token"; public static final String TOKEN = "token";
public static final String SALT = "salt";
public static final String MUSIC_LIBRARY_ID = "music_library_id"; public static final String MUSIC_LIBRARY_ID = "music_library_id";
public static final String POSITION = "position"; public static final String POSITION = "position";
public static final String PROGRESS = "progress"; public static final String PROGRESS = "progress";
@ -96,6 +97,16 @@ public class PreferenceUtil {
editor.apply(); editor.apply();
} }
public String getSalt() {
return mPreferences.getString(SALT, null);
}
public void setSalt(String salt) {
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putString(SALT, salt);
editor.apply();
}
public Boolean getSync() { public Boolean getSync() {
return mPreferences.getBoolean(SYNC, false); return mPreferences.getBoolean(SYNC, false);
} }