Skip to content

Commit

Permalink
Merge pull request #4 from epic-guys/develop
Browse files Browse the repository at this point in the history
Release 1.0
  • Loading branch information
alvi-se authored Dec 15, 2023
2 parents ec8a497 + c11849d commit b42141b
Show file tree
Hide file tree
Showing 59 changed files with 5,513 additions and 359 deletions.
7 changes: 7 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
plugins {
id 'com.android.application'
id 'androidx.navigation.safeargs'
}

android {
Expand Down Expand Up @@ -33,11 +34,17 @@ android {

dependencies {


implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.10.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.navigation:navigation-fragment:2.7.5'
implementation 'androidx.navigation:navigation-ui:2.7.5'
implementation 'androidx.gridlayout:gridlayout:1.0.0'
// Navigation
def nav_version = "2.7.5"
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"
// Required by OkHTTP
implementation 'org.conscrypt:conscrypt-android:2.5.2'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
Expand Down
15 changes: 7 additions & 8 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,33 @@
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS"></uses-permission>
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"></uses-permission>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />


<application
tools:replace="android:label,android:icon,android:theme"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:label="Esse4"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Esse4"
android:enableOnBackInvokedCallback="true"
tools:targetApi="31">
<activity
android:name=".activities.MainActivity"
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:label="Esse4"
android:theme="@style/Theme.Esse4">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.LoginActivity"
android:exported="false" />
</application>

</manifest>
194 changes: 94 additions & 100 deletions app/src/main/java/org/epic_guys/esse4/API/API.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package org.epic_guys.esse4.API;

import android.accounts.AccountManager;
import android.credentials.Credential;
import android.credentials.CredentialDescription;
import android.credentials.CredentialManager;
import android.credentials.RegisterCredentialDescriptionRequest;
import android.graphics.Picture;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import androidx.core.util.Pair;

import okhttp3.OkHttpClient;
import okhttp3.Credentials;
import okhttp3.Request;
Expand All @@ -17,10 +15,12 @@
import org.epic_guys.esse4.API.services.ApiService;
import org.epic_guys.esse4.API.services.JwtService;
import org.epic_guys.esse4.exceptions.ApiException;
import org.epic_guys.esse4.models.Carriera;
import org.epic_guys.esse4.models.Jwt;
import org.epic_guys.esse4.models.Persona;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.time.Instant;
import java.util.Date;
import java.util.List;
Expand All @@ -34,17 +34,27 @@

public class API {
private static API instance;
private OkHttpClient client;
private Retrofit retrofit;
private final OkHttpClient client;
private final Retrofit retrofit;
private Jwt jwt;
public static /*temp*/ boolean isLogged = false; //TEMPORARY FIX FOR LOGIN (see MainActivity.java)
public static final String BASE_URL = "https://esse3.unive.it/e3rest/api/";
private Persona loggedPersona;
private Carriera carrieraStudente;
// public static final String BASE_URL = "https://esse3.unive.it/e3rest/api/";
public static final String BASE_URL = "https://unive.esse3.pp.cineca.it/e3rest/api/";


private Jwt getJwt() {
return jwt;
}


public static Persona getLoggedPersona() {
return API.getInstance().loggedPersona;
}
public static Carriera getCarriera() {
return API.getInstance().carrieraStudente;
}

private API() {
this.client = new OkHttpClient.Builder()
.addInterceptor(chain -> {
Expand All @@ -70,42 +80,6 @@ public static API getInstance(){
return instance == null ? instance = new API() : instance;
}


/*
@NotNull
public static CompletableFuture<Void> fetchJwk() {
Request request = new Request.Builder()
.url(BASE_URL + "jwt/jwk")
.build();
final CompletableFuture<Void> future = new CompletableFuture<>();
API.getInstance().client.newCall(request).enqueue(new okhttp3.Callback() {
@Override
public void onFailure(@NotNull okhttp3.Call call, @NotNull IOException e) {
future.completeExceptionally(e);
}
@Override
public void onResponse(@NotNull okhttp3.Call call, @NotNull okhttp3.Response response) throws IOException {
Parser<Jwk<?>> parser = Jwks.parser().build();
try {
JSONObject json = new JSONObject(response.body().string());
String jwk = json.getJSONArray("keys").getJSONObject(0).toString();
API.getInstance().jwk = (Jwk<PublicKey>) parser.parse(jwk);
API.getInstance().jwtParser = Jwts.parser()
.verifyWith(API.getInstance().jwk.toKey())
.build();
future.complete(null);
} catch (JSONException e) {
future.completeExceptionally(e);
}
}
});
return future;
}
*/

@NotNull
public static CompletableFuture<Boolean> login (String username, String password) {
final CompletableFuture<Boolean> future = new CompletableFuture<>();
Expand All @@ -130,7 +104,6 @@ public static CompletableFuture<Boolean> login (String username, String password
.addConverterFactory(GsonConverterFactory.create())
.build();


basicRetrofit.create(JwtService.class)
.newJwt()
.enqueue(new retrofit2.Callback<Jwt>() {
Expand All @@ -142,76 +115,67 @@ public void onFailure(@NotNull Call<Jwt> call, @NotNull Throwable t) {

@Override
public void onResponse(@NotNull Call<Jwt> call, @NotNull Response<Jwt> response) {
if (response.code() == 200) {
// API.fetchJwk().join();

//log data to console
Log.i("API_TAG", BuildConfig.DEBUG ? response.toString() : "Login successful");
boolean success = response.code() == 200;
if (success) {
API.getInstance().jwt = response.body();
API.isLogged = true;
Log.i("API_TAG", API.isLogged ? "Logged in" : "Not logged in");


Log.d("Api", BuildConfig.DEBUG ? response.toString() : "Login successful");
} else {
API.getInstance().isLogged = false;
Log.d("Api", BuildConfig.DEBUG ? response.toString() : "Login failed");
}
future.complete(API.getInstance().isLogged);
future.complete(success);
}
});


return future;
}

public static CompletableFuture<Persona> getBasicData(){
public static CompletableFuture<Pair<Persona, Carriera>> getBasicData() {
Call<List<Persona>> callPersone = API.getService(AnagraficheService.class).getPersone();
Call<List<Carriera>> callCarriere = API.getService(AnagraficheService.class).getCarriere();

final CompletableFuture<Persona> future = new CompletableFuture<>();
return API.enqueueResource(callPersone).thenCombine(
API.enqueueResource(callCarriere),
(persone, carriere) -> {
API.getInstance().loggedPersona = persone.get(0);
API.getInstance().carrieraStudente = carriere.get(0);
return new Pair<>(persone.get(0), carriere.get(0));
});
}

API.getService(AnagraficheService.class)
.getPersone()
.enqueue( new retrofit2.Callback<List<Persona>>() {
@Override
public void onResponse(@NotNull Call<List<Persona>> call, @NotNull Response<List<Persona>> response) {
if (response.code() == 200) {
//log data to console
Log.i("API_TAG", BuildConfig.DEBUG ? response.toString() : "Anagrafiche Service Fetch successful");

//here I take the data I need, so:
// Matricola = { user{ userId } }
// FirstName = { user{ firstName } }
// LastName = { user{ lastName } }
// Type of degree
// Student's type
// Year of study = {user { trattiCarriera[ 0{ dettaglioTratto{ annoCorso } } ] } }
// Enrolment date
// Degree's Programme = "[" + {user { trattiCarriera[ 0{ dettaglioTratto{ cdsCod } } ] } } + "] - " + {user { trattiCarriera[ 0{ cdsDes } ] } }
// Study System
// Part-time = {user { trattiCarriera[ 0{ dettaglioTratto{ ptFlag } } ] } }
try {
Persona p = response.body().get(0);
future.complete(p);
} catch (NullPointerException e) {
future.completeExceptionally(e);
}
}
}
public static CompletableFuture<Bitmap> getPhoto() {
final CompletableFuture<Bitmap> future = new CompletableFuture<>();
Persona persona = API.getInstance().loggedPersona;

@Override
public void onFailure(Call<List<Persona>> call, Throwable t) {
// throw new RuntimeException("Could not fetch data: " + (BuildConfig.DEBUG ? t.getMessage() : "Server error"));
future.completeExceptionally(t);
Request request = new Request.Builder()
.url(API.BASE_URL + "anagrafica-service-v2/persone/" + /*persId*/ persona.getPersId() + "/foto").build();

API.getInstance().client.newCall(request).enqueue(new okhttp3.Callback() {
@Override
public void onFailure(@NotNull okhttp3.Call call, @NotNull IOException e) {
future.completeExceptionally(e);
}
@Override
public void onResponse(@NotNull okhttp3.Call call, @NotNull okhttp3.Response response) {
if (response.code() == 200) {
try {
assert response.body() != null;
byte[] imgBytes = response.body().bytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(imgBytes, 0, imgBytes.length);
future.complete(bitmap);
}catch (Exception e) {
future.completeExceptionally(e);
}
});

return future;
}

public static CompletableFuture<Picture> getPhoto(){
throw new UnsupportedOperationException();
Log.d("Api", BuildConfig.DEBUG ? response.toString() : "Photo Fetch successful");
}
}
});

return future;
}

/**
* @return Whether the expiration date is before the current time.
*/
public static boolean isValidJwt() {
return API.getInstance()
.jwt.getPayload().getExpirationTime()
Expand Down Expand Up @@ -259,4 +223,34 @@ public static <T extends ApiService> T getService(Class<T> serviceClass) {
return API.getInstance().retrofit.create(serviceClass);

}

/**
* Enqueues a Retrofit call and returns a CompletableFuture that will be completed when the call
* is completed.
* @param call Retrofit call to be enqueued.
* @return A CompletableFuture that will be completed when the call is completed.
* @param <T> Type of the resource returned by the call.
*/
public static <T> CompletableFuture<T> enqueueResource(Call<T> call) {
final CompletableFuture<T> future = new CompletableFuture<>();

call.enqueue(new Callback<T>() {
@Override
public void onResponse(@NotNull Call<T> call, @NotNull Response<T> response) {
if (response.isSuccessful()) {
future.complete(response.body());
} else {
ApiException exception = new ApiException("Error on response: " + response.code());
future.completeExceptionally(exception);
}
}

@Override
public void onFailure(@NotNull Call<T> call, @NotNull Throwable t) {
future.completeExceptionally(t);
}
});

return future;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.epic_guys.esse4.API.services;

import org.epic_guys.esse4.models.Carriera;
import org.epic_guys.esse4.models.Persona;
import retrofit2.Call;
import retrofit2.http.GET;
Expand All @@ -11,4 +12,7 @@ public interface AnagraficheService extends ApiService {

@GET(BASE_URL + "/persone")
Call<List<Persona>> getPersone();

@GET(BASE_URL + "/carriere")
Call<List<Carriera>> getCarriere();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.epic_guys.esse4.API.services;

import org.epic_guys.esse4.models.Appello;
import org.epic_guys.esse4.models.ParametriIscrizioneAppello;

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;

import java.util.List;

public interface CalendarioEsamiService extends ApiService {
String BASE_URL = "calesa-service-v1";

@GET(BASE_URL + "/appelli/{cdsId}/{adId}")
Call<List<Appello>> getAppelli(@Path("cdsId") Long idCorsoDiStudio, @Path("adId") Long idAttivitaDidattica);

@POST(BASE_URL + "/appelli/{cdsId}/{adId}/{appId}/iscritti")
Call<Void> postIscrizioneAppello(
@Path("cdsId") long idCorsoDiStudio,
@Path("adId") long idAttivitaDidattica,
@Path("appId") long idAppello,
@Body ParametriIscrizioneAppello parametriIscrizioneAppello
);
}
Loading

0 comments on commit b42141b

Please sign in to comment.