Little refactoring per Essegrande
This commit is contained in:
parent
468f1e5b58
commit
4882645311
@ -5,8 +5,9 @@ public class CommonConst {
|
||||
public static class Login {
|
||||
|
||||
public static class Azienda {
|
||||
public static String protocol = "https";
|
||||
public static String host = "www2.studioml.it";
|
||||
public static int port = 80;
|
||||
public static int port = 443;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -19,9 +19,7 @@ public class MenuRESTConsumer extends _BaseRESTConsumer {
|
||||
menuRESTConsumerService.retrieveMenuConfig(rootCodOpz).enqueue(new Callback<>() {
|
||||
@Override
|
||||
public void onResponse(Call<ServiceRESTResponse<StbMenu>> call, Response<ServiceRESTResponse<StbMenu>> response) {
|
||||
analyzeAnswer(response, "retrieveMenu", (m) -> {
|
||||
onComplete.run(response.body().getEntity());
|
||||
}, onFailed);
|
||||
analyzeAnswer(response, "retrieveMenu", onComplete, onFailed);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -4,10 +4,16 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import it.integry.integrywmsnative.core.rest.deserializer.LocalDateDeserializer;
|
||||
import it.integry.integrywmsnative.core.rest.deserializer.LocalDateTimeDeserializer;
|
||||
import it.integry.integrywmsnative.core.rest.serializer.LocalDateSerializer;
|
||||
@ -26,25 +32,25 @@ public class RESTBuilder {
|
||||
private static final boolean ADD_LOGGER_INTERCEPTOR = false;
|
||||
|
||||
public static <T> T getService(final Class<T> service) {
|
||||
return getService(service, SettingsManager.i().getServer().getHost(), SettingsManager.i().getServer().getPort(), true);
|
||||
return getService(service, SettingsManager.i().getServer().getProtocol(), SettingsManager.i().getServer().getHost(), SettingsManager.i().getServer().getPort(), true);
|
||||
|
||||
}
|
||||
|
||||
public static <T> T getService(final Class<T> service, int timeout) {
|
||||
return getService(service, SettingsManager.i().getServer().getHost(), SettingsManager.i().getServer().getPort(), true, true, timeout);
|
||||
return getService(service, SettingsManager.i().getServer().getProtocol(), SettingsManager.i().getServer().getHost(), SettingsManager.i().getServer().getPort(), true, true, timeout);
|
||||
|
||||
}
|
||||
|
||||
public static <T> T getService(final Class<T> service, String host, int port, boolean addInterceptors) {
|
||||
return getService(service, host, port, addInterceptors, true, 60);
|
||||
public static <T> T getService(final Class<T> service, String protocol, String host, int port, boolean addInterceptors) {
|
||||
return getService(service, protocol, host, port, addInterceptors, true, 60);
|
||||
}
|
||||
|
||||
public static <T> T getService(final Class<T> service, String host, int port, boolean addInterceptors, boolean addEmsApi) {
|
||||
return getService(service, host, port, addInterceptors, addEmsApi, 60);
|
||||
public static <T> T getService(final Class<T> service, String protocol, String host, int port, boolean addInterceptors, boolean addEmsApi) {
|
||||
return getService(service, protocol, host, port, addInterceptors, addEmsApi, 60);
|
||||
}
|
||||
|
||||
public static <T> T getService(final Class<T> service, String host, int port, boolean addInterceptors, boolean addEmsApi, int timeout) {
|
||||
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
|
||||
public static <T> T getService(final Class<T> service, String protocol, String host, int port, boolean addInterceptors, boolean addEmsApi, int timeout) {
|
||||
OkHttpClient.Builder clientBuilder = getDefaultHttpClient();
|
||||
|
||||
clientBuilder.connectTimeout(timeout, TimeUnit.SECONDS);
|
||||
clientBuilder.readTimeout(timeout, TimeUnit.SECONDS);
|
||||
@ -57,7 +63,7 @@ public class RESTBuilder {
|
||||
|
||||
OkHttpClient client = clientBuilder.build();
|
||||
|
||||
String endpoint = "http://" + host + ":" + port + "/" + (addEmsApi ? "ems-api/" : "");
|
||||
String endpoint = protocol + "://" + host + ":" + port + "/" + (addEmsApi ? "ems-api/" : "");
|
||||
|
||||
|
||||
Gson gson = new GsonBuilder()
|
||||
@ -82,4 +88,39 @@ public class RESTBuilder {
|
||||
public static int getDefaultPort() {
|
||||
return SettingsManager.i().getServer().getPort();
|
||||
}
|
||||
|
||||
|
||||
public static OkHttpClient.Builder getDefaultHttpClient() {
|
||||
TrustManager[] trustAllCerts = new TrustManager[]{
|
||||
new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
return new java.security.cert.X509Certificate[]{};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SSLContext sslContext = null;
|
||||
try {
|
||||
sslContext = SSLContext.getInstance("SSL");
|
||||
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
|
||||
} catch (KeyManagementException | NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
OkHttpClient.Builder client = new OkHttpClient.Builder()
|
||||
.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
|
||||
.hostnameVerifier((hostname, session) -> true);
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
package it.integry.integrywmsnative.core.rest.model;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import it.integry.integrywmsnative.core.utility.UtilityDate;
|
||||
|
||||
/**
|
||||
* Created by GiuseppeS on 06/03/2018.
|
||||
*/
|
||||
@ -12,7 +9,6 @@ import it.integry.integrywmsnative.core.utility.UtilityDate;
|
||||
public class ServiceRESTResponse<T> {
|
||||
|
||||
private int esito;
|
||||
private String execDate;
|
||||
private String profileDB;
|
||||
private String errorMessage;
|
||||
|
||||
@ -24,9 +20,6 @@ public class ServiceRESTResponse<T> {
|
||||
return EsitoType.fromIntValue(esito);
|
||||
}
|
||||
|
||||
public Date getExecDate() {
|
||||
return UtilityDate.recognizeDateWithExceptionHandler(execDate);
|
||||
}
|
||||
|
||||
public String getProfileDB() {
|
||||
return profileDB;
|
||||
|
||||
@ -32,6 +32,7 @@ public class ServerStatusChecker {
|
||||
public void run() {
|
||||
if (shouldExecute && !UtilityString.isNullOrEmpty(SettingsManager.i().getServer().getHost())) {
|
||||
UtilityServer.isEmsApiAvailable(
|
||||
SettingsManager.i().getServer().getProtocol(),
|
||||
SettingsManager.i().getServer().getHost(),
|
||||
SettingsManager.i().getServer().getPort(),
|
||||
() -> mInternalCallback.run(true),
|
||||
|
||||
@ -20,6 +20,7 @@ public class SettingsModel {
|
||||
|
||||
public static class Server {
|
||||
private String codAzienda;
|
||||
private String protocol;
|
||||
private String host;
|
||||
private int port;
|
||||
|
||||
@ -32,6 +33,15 @@ public class SettingsModel {
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public Server setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
@ -7,8 +7,8 @@ import java.net.SocketAddress;
|
||||
|
||||
import it.integry.integrywmsnative.core.exception.InvalidLicenseException;
|
||||
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
|
||||
import it.integry.integrywmsnative.core.rest.RESTBuilder;
|
||||
import it.integry.integrywmsnative.gest.login.exception.ServerNotReachableException;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
@ -38,16 +38,18 @@ public class UtilityServer {
|
||||
}).start();
|
||||
}
|
||||
|
||||
public static void isEmsApiAvailable(final String serverAddress, final int serverTCPport, final Runnable onComplete, final RunnableArgs<Exception> onFailed) {
|
||||
public static void isEmsApiAvailable(final String protocol, final String serverAddress, final int serverTCPport, final Runnable onComplete, final RunnableArgs<Exception> onFailed) {
|
||||
new Thread(() -> {
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(String.format("http://%s:%d/ems-api/system/ok", serverAddress, serverTCPport))
|
||||
.url(String.format("%s://%s:%d/ems-api/system/ok", protocol, serverAddress, serverTCPport))
|
||||
.build();
|
||||
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
Response response = RESTBuilder.getDefaultHttpClient().build()
|
||||
.newCall(request)
|
||||
.execute();
|
||||
response.close();
|
||||
|
||||
if (response.code() == 200) onComplete.run();
|
||||
@ -55,7 +57,8 @@ public class UtilityServer {
|
||||
onFailed.run(new ServerNotReachableException(serverAddress, serverTCPport, null));
|
||||
else if (response.code() == 550)
|
||||
onFailed.run(new InvalidLicenseException());
|
||||
else onFailed.run(new Exception("Errore non identificato (STATUS: " + response.code() + ")"));
|
||||
else
|
||||
onFailed.run(new Exception("Errore non identificato (STATUS: " + response.code() + ")"));
|
||||
} catch (IOException e) {
|
||||
onFailed.run(new ServerNotReachableException(serverAddress, serverTCPport, e));
|
||||
}
|
||||
|
||||
@ -98,14 +98,14 @@ public class LoginActivity extends BaseActivity implements LoginViewModel.Listen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoginCompleted(String host, int port, String fullName, List<String> availableProfiles) {
|
||||
public void onLoginCompleted(String protocol, String host, int port, String fullName, List<String> availableProfiles) {
|
||||
|
||||
this.onLoadingEnded();
|
||||
runOnUiThread(() -> DialogSimpleMessageView.makeSuccessDialog(
|
||||
"Benvenuto",
|
||||
Html.fromHtml("Ciao <b>" + fullName + "</b>, la Integry le augura di svolgere al meglio il suo lavoro"),
|
||||
null,
|
||||
() -> showProfileDBSelectionDialog(host, port, availableProfiles))
|
||||
() -> showProfileDBSelectionDialog(protocol, host, port, availableProfiles))
|
||||
.show(getSupportFragmentManager(), "tag"));
|
||||
|
||||
}
|
||||
@ -117,7 +117,7 @@ public class LoginActivity extends BaseActivity implements LoginViewModel.Listen
|
||||
loginButtonEnabled.set(true);
|
||||
}
|
||||
|
||||
private void showProfileDBSelectionDialog(final String host, final int port, final List<String> availableProfiles) {
|
||||
private void showProfileDBSelectionDialog(final String protocol, final String host, final int port, final List<String> availableProfiles) {
|
||||
Runnable onComplete = () -> {
|
||||
SettingsManager.update();
|
||||
|
||||
@ -129,7 +129,7 @@ public class LoginActivity extends BaseActivity implements LoginViewModel.Listen
|
||||
if (availableProfiles != null && availableProfiles.size() == 1) {
|
||||
SettingsManager.i().getUserSession().setProfileDB(availableProfiles.get(0));
|
||||
|
||||
mViewmodel.loadDepo(codAzienda.get(), host, port, username.get(), password.get(), onComplete);
|
||||
mViewmodel.loadDepo(codAzienda.get(), protocol, host, port, username.get(), password.get(), onComplete);
|
||||
} else {
|
||||
|
||||
// setup the alert builder
|
||||
@ -144,7 +144,7 @@ public class LoginActivity extends BaseActivity implements LoginViewModel.Listen
|
||||
builder.setItems(profiles, (dialog, which) -> {
|
||||
SettingsManager.i().getUserSession().setProfileDB(availableProfiles.get(which));
|
||||
|
||||
mViewmodel.loadDepo(codAzienda.get(), host, port, username.get(), password.get(), onComplete);
|
||||
mViewmodel.loadDepo(codAzienda.get(), protocol, host, port, username.get(), password.get(), onComplete);
|
||||
});
|
||||
|
||||
// create and show the alert dialog
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
package it.integry.integrywmsnative.gest.login.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LoginDTO {
|
||||
|
||||
private String full_name;
|
||||
private List<String> availableProfiles;
|
||||
|
||||
public String getFull_name() {
|
||||
return full_name;
|
||||
}
|
||||
|
||||
public LoginDTO setFull_name(String full_name) {
|
||||
this.full_name = full_name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getAvailableProfiles() {
|
||||
return availableProfiles;
|
||||
}
|
||||
|
||||
public LoginDTO setAvailableProfiles(List<String> availableProfiles) {
|
||||
this.availableProfiles = availableProfiles;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package it.integry.integrywmsnative.gest.login.dto;
|
||||
|
||||
public class LoginRequestDTO {
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public LoginRequestDTO setUsername(String username) {
|
||||
this.username = username;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public LoginRequestDTO setPassword(String password) {
|
||||
this.password = password;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package it.integry.integrywmsnative.gest.login.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LoginResponseDTO {
|
||||
|
||||
private String fullName;
|
||||
private List<String> availableProfiles;
|
||||
|
||||
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public List<String> getAvailableProfiles() {
|
||||
return availableProfiles;
|
||||
}
|
||||
|
||||
}
|
||||
@ -10,7 +10,8 @@ import it.integry.integrywmsnative.core.rest.RESTBuilder;
|
||||
import it.integry.integrywmsnative.core.rest.consumers._BaseRESTConsumer;
|
||||
import it.integry.integrywmsnative.core.rest.model.ServiceRESTResponse;
|
||||
import it.integry.integrywmsnative.gest.login.dto.LoginAziendaDTO;
|
||||
import it.integry.integrywmsnative.gest.login.dto.LoginDTO;
|
||||
import it.integry.integrywmsnative.gest.login.dto.LoginResponseDTO;
|
||||
import it.integry.integrywmsnative.gest.login.dto.LoginRequestDTO;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
@ -19,12 +20,13 @@ import retrofit2.Response;
|
||||
public class LoginRESTConsumer extends _BaseRESTConsumer {
|
||||
|
||||
|
||||
public void retrieveServerData(String codAzienda, RunnableArgs<LoginAziendaDTO> onComplete, RunnableArgs<Exception> onFailed){
|
||||
public void retrieveServerData(String codAzienda, RunnableArgs<LoginAziendaDTO> onComplete, RunnableArgs<Exception> onFailed) {
|
||||
|
||||
String protocol = CommonConst.Login.Azienda.protocol;
|
||||
String host = CommonConst.Login.Azienda.host;
|
||||
int port = CommonConst.Login.Azienda.port;
|
||||
|
||||
LoginRESTConsumerService service = RESTBuilder.getService(LoginRESTConsumerService.class, host, port, false, true);
|
||||
LoginRESTConsumerService service = RESTBuilder.getService(LoginRESTConsumerService.class, protocol, host, port, false, true);
|
||||
service.loginAzienda(codAzienda).enqueue(new Callback<>() {
|
||||
@Override
|
||||
public void onResponse(Call<ServiceRESTResponse<LoginAziendaDTO>> call, Response<ServiceRESTResponse<LoginAziendaDTO>> response) {
|
||||
@ -40,17 +42,22 @@ public class LoginRESTConsumer extends _BaseRESTConsumer {
|
||||
}
|
||||
|
||||
|
||||
public void authenticate(String host, int port, String username, String password, RunnableArgs<LoginDTO> onComplete, RunnableArgs<Exception> onFailed){
|
||||
LoginRESTConsumerService service = RESTBuilder.getService(LoginRESTConsumerService.class, host, port, false);
|
||||
service.login(username, password).enqueue(new Callback<>() {
|
||||
public void authenticate(String protocol, String host, int port, String username, String password, RunnableArgs<LoginResponseDTO> onComplete, RunnableArgs<Exception> onFailed) {
|
||||
LoginRESTConsumerService service = RESTBuilder.getService(LoginRESTConsumerService.class, protocol, host, port, false);
|
||||
|
||||
LoginRequestDTO loginRequestDTO = new LoginRequestDTO()
|
||||
.setUsername(username)
|
||||
.setPassword(password);
|
||||
|
||||
service.login(loginRequestDTO).enqueue(new Callback<>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(Call<ServiceRESTResponse<LoginDTO>> call, Response<ServiceRESTResponse<LoginDTO>> response) {
|
||||
public void onResponse(Call<ServiceRESTResponse<LoginResponseDTO>> call, Response<ServiceRESTResponse<LoginResponseDTO>> response) {
|
||||
analyzeAnswer(response, "Login", onComplete, onFailed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ServiceRESTResponse<LoginDTO>> call, final Throwable t) {
|
||||
public void onFailure(Call<ServiceRESTResponse<LoginResponseDTO>> call, final Throwable t) {
|
||||
Log.e("Login", t.toString());
|
||||
onFailed.run(new Exception(t));
|
||||
}
|
||||
|
||||
@ -3,8 +3,10 @@ package it.integry.integrywmsnative.gest.login.rest;
|
||||
|
||||
import it.integry.integrywmsnative.core.rest.model.ServiceRESTResponse;
|
||||
import it.integry.integrywmsnative.gest.login.dto.LoginAziendaDTO;
|
||||
import it.integry.integrywmsnative.gest.login.dto.LoginDTO;
|
||||
import it.integry.integrywmsnative.gest.login.dto.LoginResponseDTO;
|
||||
import it.integry.integrywmsnative.gest.login.dto.LoginRequestDTO;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Query;
|
||||
@ -16,6 +18,6 @@ public interface LoginRESTConsumerService {
|
||||
Call<ServiceRESTResponse<LoginAziendaDTO>> loginAzienda(@Query("codHash") String codHash);
|
||||
|
||||
@POST("loginWeb")
|
||||
Call<ServiceRESTResponse<LoginDTO>> login(@Query("username") String username, @Query("password") String password);
|
||||
Call<ServiceRESTResponse<LoginResponseDTO>> login(@Body LoginRequestDTO loginRequestDTO);
|
||||
|
||||
}
|
||||
|
||||
@ -48,15 +48,16 @@ public class LoginViewModel {
|
||||
return;
|
||||
}
|
||||
|
||||
final String protocol = u.getProtocol();
|
||||
final String host = u.getHost();
|
||||
final int port = u.getPort();
|
||||
|
||||
UtilityServer.isEmsApiAvailable(host, port, () -> {
|
||||
UtilityServer.isEmsApiAvailable(protocol, host, port, () -> {
|
||||
|
||||
mLoginRESTConsumer.authenticate(host, port, username, password, loginDTO -> {
|
||||
mLoginRESTConsumer.authenticate(protocol, host, port, username, password, loginDTO -> {
|
||||
|
||||
SettingsManager.i().createUserSession();
|
||||
SettingsManager.i().getUser().setFullname(!UtilityString.isNullOrEmpty(loginDTO.getFull_name()) ? loginDTO.getFull_name() : username);
|
||||
SettingsManager.i().getUser().setFullname(!UtilityString.isNullOrEmpty(loginDTO.getFullName()) ? loginDTO.getFullName() : username);
|
||||
|
||||
List<String> availableProfiles = null;
|
||||
if(loginDTO.getAvailableProfiles() != null && !loginDTO.getAvailableProfiles().isEmpty()) {
|
||||
@ -65,7 +66,7 @@ public class LoginViewModel {
|
||||
.toList();
|
||||
}
|
||||
|
||||
this.sendOnLoginCompleted(host, port, loginDTO.getFull_name(), availableProfiles);
|
||||
this.sendOnLoginCompleted(protocol, host, port, loginDTO.getFullName(), availableProfiles);
|
||||
}, this::sendError);
|
||||
|
||||
|
||||
@ -76,9 +77,10 @@ public class LoginViewModel {
|
||||
}
|
||||
|
||||
|
||||
public void loadDepo(String codAzienda, String host, int port, String username, String password, Runnable onComplete) {
|
||||
public void loadDepo(String codAzienda, String protocol, String host, int port, String username, String password, Runnable onComplete) {
|
||||
|
||||
SettingsManager.i().getServer().setCodAzienda(codAzienda);
|
||||
SettingsManager.i().getServer().setProtocol(protocol);
|
||||
SettingsManager.i().getServer().setHost(host);
|
||||
SettingsManager.i().getServer().setPort(port);
|
||||
|
||||
@ -109,9 +111,9 @@ public class LoginViewModel {
|
||||
if (this.mListener != null) mListener.onLoadingEnded();
|
||||
}
|
||||
|
||||
private void sendOnLoginCompleted(String host, int port, String fullName, List<String> availableProfiles) {
|
||||
private void sendOnLoginCompleted(String protocol, String host, int port, String fullName, List<String> availableProfiles) {
|
||||
if (this.mListener != null)
|
||||
mListener.onLoginCompleted(host, port, fullName, availableProfiles);
|
||||
mListener.onLoginCompleted(protocol, host, port, fullName, availableProfiles);
|
||||
}
|
||||
|
||||
private void sendError(Exception ex) {
|
||||
@ -126,7 +128,7 @@ public class LoginViewModel {
|
||||
public interface Listener extends ILoadingListener {
|
||||
void onError(Exception ex);
|
||||
|
||||
void onLoginCompleted(String host, int port, String fullName, List<String> availableProfiles);
|
||||
void onLoginCompleted(String protocol, String host, int port, String fullName, List<String> availableProfiles);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user