AppsView.java
package com.privacydashboard.application.views.apps;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.privacydashboard.application.data.GlobalVariables;
import com.privacydashboard.application.data.GlobalVariables.RightType;
import com.privacydashboard.application.data.GlobalVariables.Role;
import com.privacydashboard.application.data.entity.IoTApp;
import com.privacydashboard.application.data.entity.RightRequest;
import com.privacydashboard.application.data.entity.User;
import com.privacydashboard.application.data.entity.UserAppRelation;
import com.privacydashboard.application.data.service.CommunicationService;
import com.privacydashboard.application.data.service.DataBaseService;
import com.privacydashboard.application.security.AuthenticatedUser;
import com.privacydashboard.application.views.MainLayout;
import com.privacydashboard.application.views.contacts.ContactsView;
import com.privacydashboard.application.views.privacyNotice.PrivacyNoticeView;
import com.privacydashboard.application.views.questionnaire.SingleQuestionnaire;
import com.privacydashboard.application.views.usefulComponents.MyDialog;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.avatar.Avatar;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.contextmenu.ContextMenu;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.details.Details;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.html.*;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.notification.NotificationVariant;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.HttpURLConnection;
import java.net.URL;
import com.fasterxml.jackson.databind.node.ObjectNode;
import javax.annotation.security.PermitAll;
import javax.net.ssl.TrustManager;
import javax.net.ssl.SSLContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import java.io.StringReader;
import java.util.UUID;
import java.util.Arrays;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@PageTitle("Apps")
@Route(value = "apps-view", layout = MainLayout.class)
@PermitAll
@NpmPackage(value = "line-awesome", version = "1.3.0")
public class AppsView extends Div implements AfterNavigationObserver, BeforeEnterObserver {
private final DataBaseService dataBaseService;
private final AuthenticatedUser authenticatedUser;
private final CommunicationService communicationService;
private final Div summaryEvaluation= new Div();
private final TextField searchText=new TextField();
private final Grid<IoTApp> grid= new Grid<>();
private IoTApp priorityApp;
private List<IoTApp> getJsonAppsFromUrl() throws NullPointerException {
TrustManager[] dummyTrustManager = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
String responseString = "";
try{
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, dummyTrustManager, new java.security.SecureRandom());
URL url = new URL("https://yggio.sifis-home.eu:3000/dht-insecure/topic_name/SIFIS:container_list");
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
if(responseCode == HttpsURLConnection.HTTP_OK){
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while((inputLine = in.readLine()) != null){
response.append(inputLine);
}
in.close();
responseString = response.toString().substring(response.toString().indexOf("[")+1, response.toString().lastIndexOf("]"));
}
else{
System.out.println("GET Request failed");
}
JsonNode json = new ObjectMapper().readTree(new StringReader(responseString));
json = json.get("value");
int size = json.get("containers").size();
if(size == 0){
throw new NullPointerException("Size was 0");
}
IoTApp[] appArray = new IoTApp[size];
Iterator<JsonNode> iterator = json.get("containers").elements();
for(int i = 0; i < size; i++){
IoTApp app = new IoTApp();
app.setName(cleanAppName(iterator.next().asText()));
app.setId(new UUID(0, app.getName().hashCode()));
appArray[i] = app;
}
List<IoTApp> apps = removeDuplicates(Arrays.asList(appArray));
return apps;
}
catch(Exception e){
System.out.println("JsonFromUrl Exception: "+e.getMessage());
throw new NullPointerException(e.getMessage());
}
}
private ArrayList<IoTApp> removeDuplicates(List<IoTApp> list){
ArrayList<IoTApp> newList = new ArrayList<>();
for(IoTApp app : list){
if(!newList.contains(app))
newList.add(app);
}
return newList;
}
private String cleanAppName(String name){
String newName = name.split("3pa-")[1].split("-")[0];
return newName;
}
@Override
public void beforeEnter(BeforeEnterEvent event){
priorityApp=communicationService.getApp();
}
public AppsView(DataBaseService dataBaseService, AuthenticatedUser authenticatedUser, CommunicationService communicationService){
this.dataBaseService=dataBaseService;
this.authenticatedUser=authenticatedUser;
this.communicationService=communicationService;
addClassName("grid-view");
initilizeInfrastuctureEvaluation();
initializeSearchText();
initializeGrid();
VerticalLayout appLayout = new VerticalLayout();
try{
List<IoTApp> apps = getJsonAppsFromUrl();
for (IoTApp app : apps) {
appLayout.add(createApp(app));
}
}
catch(Exception e){
System.out.println("Exception: "+e);
Span exNotice = e.getMessage().equals("Size was 0") ? new Span("You do not have any apps.") : new Span("We could not retrieve your apps.");
exNotice.addClassName("bold");
appLayout.add(exNotice);
}
add(summaryEvaluation, searchText, appLayout, grid);
}
private void initilizeInfrastuctureEvaluation(){
Span evaluationDescription= new Span("Privacy Infrastructure Evaluation: ");
evaluationDescription.addClassName("bold");
Span evaluation= new Span();
GlobalVariables.QuestionnaireVote vote= GlobalVariables.QuestionnaireVote.GREEN;
int nRed=0;
for(IoTApp app : dataBaseService.getUserApps(authenticatedUser.getUser())){
if(app.getQuestionnaireVote().equals(GlobalVariables.QuestionnaireVote.RED)){
nRed++;
if(nRed>1){
vote= GlobalVariables.QuestionnaireVote.RED;
break;
}
}
if(app.getQuestionnaireVote().equals(GlobalVariables.QuestionnaireVote.RED) && vote.equals(GlobalVariables.QuestionnaireVote.GREEN)){
vote= GlobalVariables.QuestionnaireVote.ORANGE;
}
}
switch (vote){
case GREEN:
evaluation.setText("GREEN");
summaryEvaluation.addClassName("greenName");
break;
case ORANGE:
evaluation.setText("ORANGE");
summaryEvaluation.addClassName("orangeName");
break;
case RED:
evaluation.setText("RED");
summaryEvaluation.addClassName("redName");
break;
}
summaryEvaluation.add(evaluationDescription, evaluation);
summaryEvaluation.addClassName("summaryEvaluation");
}
private void initializeSearchText(){
searchText.setPlaceholder("Search...");
searchText.setValueChangeMode(ValueChangeMode.LAZY);
searchText.addValueChangeListener(e-> updateGrid());
searchText.addClassName("search");
}
private void initializeGrid(){
grid.addThemeVariants(GridVariant.LUMO_NO_BORDER, GridVariant.LUMO_NO_ROW_BORDERS);
grid.addComponentColumn(this::createApp);
}
private VerticalLayout createApp(IoTApp app){
Avatar avatar = new Avatar(app.getName());
Span name = new Span(app.getName());
name.addClassName("name");
Details details = new Details(new Span("More"), initializeApp(app));
VerticalLayout card = new VerticalLayout();
card.addClassName("card");
card.addClassName("canOpen");
card.setSpacing(false);
card.add(new HorizontalLayout(avatar , name), details);
card.addClickListener(e-> {
if(card.hasClassName("canOpen")){
details.setOpened(true);
card.removeClassNames("canOpen");
}
else if(!details.isOpened()){
card.addClassName("canOpen");
}
});
// se c'รจ un priorityUser apri details
if(app.equals(priorityApp)){
details.setOpened(true);
}
return card;
}
private VerticalLayout initializeApp(IoTApp i){
Span descriptionSpan= new Span("Description: ");
descriptionSpan.addClassName("bold");
Span description= new Span(descriptionSpan, new Span(i.getDescription()));
Div vote= getEvaluation(i);
Span privacyNotice= new Span("Privacy Notice");
privacyNotice.addClassName("link");
privacyNotice.addClickListener(e-> goToPrivacyNotice(i));
Details controllerDetails= new Details(new Span("Data Controllers: "), getUsers(i, Role.CONTROLLER));
Details DPODetails= new Details(new Span("Data Protection Officer: "), getUsers(i, Role.DPO));
VerticalLayout content=new VerticalLayout(description, vote, privacyNotice, controllerDetails, DPODetails);
if(authenticatedUser.getUser().getRole().equals(Role.SUBJECT)){
content.add(new Details(new Span("Consenses: ") , getConsenses(i)));
Button removeEverythingButton= new Button("Remove everything", e->removeEverything(i));
content.add(removeEverythingButton);
}
else{
content.add(new Details(new Span("Data Subjects: ") , getUsers(i, Role.SUBJECT)));
}
//content.add(new Span("ID: " + i.getId().toString()));
return content;
}
private Div getEvaluation(IoTApp app){
Span icon= new Span();
icon.addClassNames("las la-info-circle");
icon.addClassName("pointer");
ContextMenu contextMenu= new ContextMenu();
contextMenu.setTarget(icon);
contextMenu.setOpenOnClick(true);
contextMenu.addClassName("info");
Span descr= new Span("Evaluation: ");
descr.addClassName("bold");
Span vote=new Span();
String text="";
if(app.getQuestionnaireVote()==null){
vote.setText("NO EVALUATION YET");
vote.addClassName("redName");
text= "The questionnaire to evaluate this app hasn't been performed yet";
}
else{
switch (app.getQuestionnaireVote()){
case RED:
vote.setText("RED ");
vote.addClassName("redName");
text= "The app is not compliant with the GDPR";
break;
case ORANGE:
vote.setText("ORANGE ");
vote.addClassName("orangeName");
text= "The app is not so compliant with the GDPR";
break;
case GREEN:
vote.setText("GREEN ");
vote.addClassName("greenName");
text= "The app is compliant with the GDPR";
break;
}
}
if(!authenticatedUser.getUser().getRole().equals(Role.SUBJECT)) {
contextMenu.addItem("Go to the questionnaire", e -> {
communicationService.setApp(app);
UI.getCurrent().navigate(SingleQuestionnaire.class);
});
}
else {
contextMenu.addItem(text);
}
return new Div(descr, vote, icon);
}
private void goToPrivacyNotice(IoTApp i){
communicationService.setPrivacyNotice(dataBaseService.getPrivacyNoticeFromApp(i));
UI.getCurrent().navigate(PrivacyNoticeView.class);
}
private VerticalLayout getUsers(IoTApp i, Role role){
VerticalLayout layout=new VerticalLayout();
List<User> users;
switch(role) {
case SUBJECT:
users = dataBaseService.getSubjectsFromApp(i);
break;
case CONTROLLER:
users = dataBaseService.getControllersFromApp(i);
break;
case DPO:
users = dataBaseService.getDPOsFromApp(i);
break;
default:
return null;
}
for(User u : users){
if(u.equals(authenticatedUser.getUser())){
continue;
}
Span contactLink=new Span(u.getName());
contactLink.addClassName("link");
contactLink.addClickListener(e->communicationService.setContact(u));
contactLink.addClickListener(e-> UI.getCurrent().navigate(ContactsView.class));
layout.add(contactLink);
}
return layout;
}
private VerticalLayout getConsenses(IoTApp i){
VerticalLayout layout=new VerticalLayout();
if(i.getConsenses() == null){
return layout;
}
String[] appConsenses= i.getConsenses();
String[] userConsenses=dataBaseService.getConsensesFromUserAndApp(authenticatedUser.getUser(), i);
for(String consens : appConsenses){
Button button= new Button();
if(userConsenses!=null && List.of(userConsenses).contains(consens)){
button.setText("Withdraw consent");
button.addClickListener(e -> changeConsent(i, consens, "withdraw"));
}
else{
button.setText("Accept consent");
button.addClickListener(e -> changeConsent(i, consens, "accept"));
}
HorizontalLayout l=new HorizontalLayout(new Span(consens), button);
l.setAlignItems(FlexComponent.Alignment.CENTER);
l.setVerticalComponentAlignment(FlexComponent.Alignment.CENTER);
layout.add(l);
}
return layout;
}
private void changeConsent(IoTApp i, String consent, String action){
/*HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("http://www.a-domain.example/foo/");
// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>(4);
params.add(new BasicNameValuePair("user", authenticatedUser.getUser().getId().toString()));
params.add(new BasicNameValuePair("app", i.getId().toString()));
params.add(new BasicNameValuePair("consent", consent));
params.add(new BasicNameValuePair("action", action));
try {
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
} catch (UnsupportedEncodingException e){
e.printStackTrace();
}
//Execute and get the response.
try {
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
if (entity != null) {
try (InputStream instream = entity.getContent()) {
// do something useful
}
}
} catch (IOException e){
e.printStackTrace();
}
*/
// DA ELIMINARE
if(action.equals("withdraw")){
dataBaseService.removeConsensesFromUserAppRelation(dataBaseService.getUserAppRelationByUserAndApp(authenticatedUser.getUser(), i), List.of(consent));
}
else{
dataBaseService.addConsenses(dataBaseService.getUserAppRelationByUserAndApp(authenticatedUser.getUser(), i), List.of(consent));
}
// FINE DA ELIMINARE
RightRequest request=new RightRequest();
request.setSender(authenticatedUser.getUser());
request.setRightType(RightType.WITHDRAWCONSENT);
request.setApp(i);
request.setOther(consent);
request.setReceiver(dataBaseService.getControllersFromApp(i).get(0));
request.setHandled(false);
communicationService.setRightRequest(request);
UI.getCurrent().navigate("rights");
}
private void removeEverything(IoTApp app){
MyDialog dialog= new MyDialog();
Button confirm=new Button("Confirm", e-> {dataBaseService.removeEverythingFromUserAndApp(authenticatedUser.getUser(), app);
Notification notification = Notification.show("The request has been sent to the Data Controllers!");
notification.addThemeVariants(NotificationVariant.LUMO_SUCCESS);
dialog.close();});
dialog.setContinueButton(confirm);
dialog.setTitle("Confirm to remove everything");
dialog.setContent(
new VerticalLayout(new Span("Are you sure you want to remove all your personal information from the app " + app.getName() + "?")));
dialog.open();
}
private void updateGrid(){
List<IoTApp> ioTAppList;
if(searchText.getValue()==null || searchText.getValue().length()==0){
ioTAppList=dataBaseService.getUserApps(authenticatedUser.getUser());
}
else{
ioTAppList=dataBaseService.getUserAppsByName(authenticatedUser.getUser(), searchText.getValue());
}
// se esiste l'app selezionata nei parametri, mettilo al primo posto
if(priorityApp!=null){
if(ioTAppList.contains(priorityApp)){
Collections.swap(ioTAppList, 0, ioTAppList.indexOf(priorityApp));
}
}
grid.setItems(ioTAppList);
}
@Override
public void afterNavigation(AfterNavigationEvent event) {
updateGrid();
}
}