Skip to content

Commit

Permalink
hotfix
Browse files Browse the repository at this point in the history
  • Loading branch information
elYanuki committed Oct 3, 2024
1 parent 29b8095 commit 2001800
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 77 deletions.
31 changes: 29 additions & 2 deletions backend/src/main/java/at/camconnect/boundary/UserResource.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,55 @@
package at.camconnect.boundary;

import at.camconnect.dtos.AutocompleteNumberOptionDTO;
import at.camconnect.dtos.KeycloakUser;
import at.camconnect.model.User;
import at.camconnect.repository.UserRepository;
import at.camconnect.responseSystem.CCException;
import at.camconnect.responseSystem.CCResponse;
import at.camconnect.services.UserSyncService;
import io.quarkus.security.Authenticated;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.annotation.security.RolesAllowed;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.json.JsonObject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.jwt.JsonWebToken;

import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

@Path("user")
public class UserResource {
@Inject
UserRepository userRepository;

@Inject
UserSyncService userSyncService;

AtomicBoolean isRunning = new AtomicBoolean(false);

@PUT
@Path("loadfromldap")
@RolesAllowed({"camconnect-admin", "medt-teacher"})
public Response loadFromLDAP(){
if (isRunning.compareAndSet(false, true)) {
List<KeycloakUser> users;
try{
users = userSyncService.syncUsersWithLDAP();
}catch (CCException ex){
return CCResponse.error(ex);
}

isRunning.set(false);

return CCResponse.ok(users);
} else {
return CCResponse.error(new CCException(1201, "users are already being loaded"));
}
}

@GET
@Path("/getbyid/{id}")
@Authenticated
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package at.camconnect.repository;

import at.camconnect.dtos.AutocompleteNumberOptionDTO;
import at.camconnect.dtos.KeycloakUser;
import at.camconnect.model.User;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public class CCStatus {
Map.entry(1203, "File is empty"),
Map.entry(1204, "File has Invalid Structure"),
Map.entry(1205, "Operation was not allowed"),
Map.entry(1206, "Invalid Data provided")

Map.entry(1206, "Invalid Data provided"),
Map.entry(1207, "Request to external provider was unsuccessful")
);

private int statusCode;
Expand Down
50 changes: 0 additions & 50 deletions backend/src/main/java/at/camconnect/services/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ public class AuthService {
@ConfigProperty(name = "quarkus.oidc.auth-server-url")
String AUTH_SERVER_URL;

@ConfigProperty(name = "quarkus.oidc.base-url")
String BASE_URL;

@ConfigProperty(name = "quarkus.oidc.client-id")
String AUTH_CLIENT_ID;

Expand Down Expand Up @@ -68,53 +65,6 @@ public Response requestLogin(String username, String password) {
}
}

public void persistUser(KeycloakUser user) {
try{
em.persist(new User(
user.id(),
user.getUserRole(),
user.firstName(),
user.lastName(),
user.email(),
user.username(),
"unknown"
));
}catch (Exception e){
e.printStackTrace();
}
}

public void syncUsersWithDatabase(String accessToken) {
try (Client client = ClientBuilder.newClient()) {
Response response = client.target(String.format("%s/admin/realms/%s/users?search=%s&max=1000", BASE_URL, "2425-5bhitm", "IT"))
.request(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer " + accessToken)
.get();

int statusCode = response.getStatus();
if (statusCode != 200) {
throw new RuntimeException("Failed to fetch users: HTTP status code " + statusCode);
}

String jsonResponse = response.readEntity(String.class);

ObjectMapper objectMapper = new ObjectMapper();
List<KeycloakUser> users = objectMapper.readValue(jsonResponse, new TypeReference<List<KeycloakUser>>() {});

for (KeycloakUser user : users) {
// Process each user
System.out.println("Processing user: " + user.username());

// Save or update the user in your database
persistUser(user);
}


} catch (Exception e) {
// ... (error handling)
}
}

public String getToken() {
try (Client client = ClientBuilder.newClient()) {
Form form = new Form();
Expand Down
74 changes: 68 additions & 6 deletions backend/src/main/java/at/camconnect/services/UserSyncService.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,93 @@
package at.camconnect.services;

import at.camconnect.dtos.KeycloakUser;
import at.camconnect.model.User;
import at.camconnect.responseSystem.CCException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.runtime.Startup;
import io.quarkus.runtime.StartupEvent;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import java.util.List;
import java.util.concurrent.CompletableFuture;

@Startup
@ApplicationScoped
@Transactional
public class UserSyncService {

@Inject
AuthService authService;

@Inject
EntityManager em;

@ConfigProperty(name = "quarkus.oidc.base-url")
String BASE_URL;

/*
public void onStart(@Observes StartupEvent event) {
CompletableFuture.runAsync(() -> syncUsers());
CompletableFuture.runAsync(this::syncUsersWithLDAP);
}
*/

public List<KeycloakUser> syncUsersWithLDAP() {
try (Client client = ClientBuilder.newClient()) {
String token = authService.getToken();

Response response = client.target(String.format("%s/admin/realms/%s/users?search=%s&max=1000", BASE_URL, "2425-5bhitm", "IT"))
.request(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer " + token)
.get();

int statusCode = response.getStatus();
if (statusCode != 200) {
throw new RuntimeException("Failed to fetch users: HTTP status code " + statusCode);
}

String jsonResponse = response.readEntity(String.class);

ObjectMapper objectMapper = new ObjectMapper();
List<KeycloakUser> users = objectMapper.readValue(jsonResponse, new TypeReference<List<KeycloakUser>>() {});

for (KeycloakUser user : users) {
// Process each user
System.out.println("Processing user: " + user.username());

// Save or update the user in your database
persistKeycloakUser(user);
}

return users;

private void syncUsers() {
try {
authService.syncUsersWithDatabase(authService.getToken());
} catch (Exception e) {
// Log the error or handle it appropriately
System.err.println("Error during user synchronization: " + e.getMessage());
throw new CCException(1207, e.getMessage());
}
}

public void persistKeycloakUser(KeycloakUser user) {
try{
em.persist(new User(
user.id(),
user.getUserRole(),
user.firstName(),
user.lastName(),
user.email(),
user.username(),
"unknown"
));
}catch (Exception e){
e.printStackTrace();
}
}
}
2 changes: 1 addition & 1 deletion backend/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ quarkus.http.cors.origins=*
quarkus.http.cors.methods=GET, POST, PUT, DELETE
quarkus.http.cors.headers=Content-Type, Authorization

quarkus.hibernate-orm.database.generation=update
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=false
#added dont-import.qsl because quarkus will crash wehen fed a completly commented out sql script.. or maybe just our sql script
quarkus.hibernate-orm.sql-load-script=import.sql
Expand Down
32 changes: 21 additions & 11 deletions frontend/web/src/components/userSettings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import {LitElement, html} from 'lit'
import {customElement, property} from 'lit/decorators.js'
import styles from '../../styles/components/userSettings.styles.scss'
import PopupEngine from "../util/PopupEngine"
import {config, SimpleColorEnum, SizeEnum} from "../base"
import {ColorEnum, config, SimpleColorEnum, SizeEnum} from "../base"
import Util from "../util/Util"
import {ButtonType} from "./basic/button.component"
import {model} from "../index"
import {Api} from "../util/Api"
import {ObservedProperty} from "../model"
import {AppState} from "../AppState"
import AuthService from "../service/auth.service"
import UserService from "../service/user.service"

@customElement('cc-user-settings')
export class UserSettingsComponent extends LitElement {
Expand All @@ -26,12 +27,8 @@ export class UserSettingsComponent extends LitElement {
<cc-navbar type="back"></cc-navbar>
<main>
<h1>Hallo ${this.appState.value.currentUser?.firstname}</h1>
<cc-button @click="${AuthService.logOut}">Ausloggen</cc-button>
<section>
<h1>Notifications</h1>
<h1>Beneachrichtigungen</h1>
<cc-toggle>Send emails</cc-toggle>
<cc-toggle>Show push notifications</cc-toggle>
</section>
Expand Down Expand Up @@ -66,22 +63,35 @@ export class UserSettingsComponent extends LitElement {
</section>
<section>
<h1>Data</h1>
<h1>Verwalten</h1>
<div class="line">
<p>Alle Verleiheinträge exportieren</p>
<a href="${config.api_url}/rent/getcsv" download>
<cc-button type="${ButtonType.OUTLINED}">Exportieren</cc-button>
</a>
</div>
<div class="line">
<p>Alle Gerätetypen exportieren</p>
<a href="${config.api_url}/devicetype/getcsv" download>
alle gerätetypen exportieren
<cc-button type="${ButtonType.OUTLINED}">Exportieren</cc-button>
</a>
</div>
<div class="inputField">
<label for="importRents">Import rents:</label>
<div class="inputField line">
<label for="importRents">Import rents</label>
<input id="importRents" type="file" @change="${(event) => {this.importDataFromCsv(event)}}" accept=".csv"/>
</div>
<div class="line">
<p>Nutzer vom LDAP Server synchronisieren</p>
<cc-button type="${ButtonType.OUTLINED}" color="${ColorEnum.ACCENT}" @click="${UserService.loadFromLDAP}">Laden</cc-button>
</div>
<div class="line">
<p>Einen anderen Account verwenden</p>
<cc-button type="${ButtonType.OUTLINED}" color="${ColorEnum.ACCENT}" @click="${AuthService.logOut}">Ausloggen</cc-button>
</div>
</section>
</main>
`
Expand Down
4 changes: 2 additions & 2 deletions frontend/web/src/service/deviceSet.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface DeviceSet {

export default class DeviceSetService{
static fetchAll(){
Api.fetchData<DeviceSet[]>("/deviceset/getall")
Api.getData<DeviceSet[]>("/deviceset/getall")
.then(result => {
model.loadDeviceSets(result.data)
})
Expand Down Expand Up @@ -70,7 +70,7 @@ export default class DeviceSetService{
}

static getDeviceSetById(id: number) {
return Api.fetchData<DeviceSet>("/deviceset/getbyid?id=" + id)
return Api.getData<DeviceSet>("/deviceset/getbyid?id=" + id)
.then(result => {
return result.data;
})
Expand Down
2 changes: 1 addition & 1 deletion frontend/web/src/service/deviceType.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export default class DeviceTypeService {
}

static getDeviceTypeById(id: number) {
return Api.fetchData<DeviceType>(`/devicetype/getbyid/${id}`)
return Api.getData<DeviceType>(`/devicetype/getbyid/${id}`)
.then(result => {
return result.data;
})
Expand Down
10 changes: 10 additions & 0 deletions frontend/web/src/service/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,14 @@ export default class UserService {
return response.data
})
}

static loadFromLDAP(){
return Api.putData("/user/loadfromldap")
.then(response => {
console.log(response)
})
.catch(error => {
console.error(error)
})
}
}
2 changes: 1 addition & 1 deletion frontend/web/styles/components/basic/button.styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
:host{
all: initial;
height: fit-content;
min-width: 10ch;
width: fit-content;
-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;
}
Expand All @@ -16,6 +15,7 @@ button{
cursor: pointer;
transition: background-color $transitionTimeShort, color $transitionTimeShort, border ease $transitionTimeShort, box-shadow $transitionTimeShort;
white-space: nowrap;
min-width: 10ch;

-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;

Expand Down
Loading

0 comments on commit 2001800

Please sign in to comment.