Skip to content

Commit

Permalink
Merge pull request #6 from MJU-Iced-Americano/feature/keycloak-user-s…
Browse files Browse the repository at this point in the history
…torage-jpa

#1 feat : Keycloak User Storage JPA 적용
  • Loading branch information
kimyubi authored Apr 17, 2023
2 parents 2c55b17 + fbf2851 commit afe1868
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ protected Birth() {
localDate = LocalDate.now();
}

private Birth(String value) {
this.localDate = LocalDate.parse(value);
}

public Birth(LocalDate localDate) {
this.localDate = localDate;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
*/
package org.mju.domain;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Expand All @@ -37,10 +40,15 @@ public class UserAdapter extends AbstractUserAdapterFederatedStorage {
private static final String PASSWORD_FIELD_NAME = "password";
private static final String USERNAME_FIELD_NAME = "username";

protected UserEntity entity;
protected String keycloakId;
protected final UserEntity entity;
protected final String keycloakId;

public UserAdapter(KeycloakSession session, RealmModel realm, ComponentModel model, UserEntity entity) {
public UserAdapter(
final KeycloakSession session,
final RealmModel realm,
final ComponentModel model,
final UserEntity entity
) {
super(session, realm, model);
this.entity = entity;
keycloakId = StorageId.keycloakId(model, entity.getId());
Expand Down Expand Up @@ -69,37 +77,81 @@ public String getId() {
return keycloakId;
}

@Override
public void removeAttribute(String name) {
setFieldValueByName(name, null);
}

@Override
public void setSingleAttribute(String name, String value) {
setFieldValueByName(name, value);
}

@Override
public void setAttribute(final String name, final List<String> values) {
super.setAttribute(name, values);
for (String value : values) {
setFieldValueByName(name, value);
}
}

private void setFieldValueByName(final String name, final String value) {
try {
entity.change();
if (isHibernateField(name)) {
return;
}
if (name.equals(ENABLED_FIELD_NAME) || name.equals(EMAIL_VERIFIED_FIELD_NAME)) {
super.setSingleAttribute(name, value);
return;
}
if (isKeycloakBasicInformationField(name)) {
Field field = entity.getClass().getDeclaredField(name);
setFieldBy(field, value);
setFieldBy(entity, field, value);
super.setSingleAttribute(name, value);
} else if (isAdditionalInformationField(name)) {
return;
}
if (isAdditionalInformationField(name)) {
Field field = entity.getAdditionalInformation().getClass().getDeclaredField(name);
setFieldBy(field, value);
} else {
if (name.equals(ENABLED_FIELD_NAME) || name.equals(EMAIL_VERIFIED_FIELD_NAME)) {
super.setSingleAttribute(name, value);
if (field.getType().isEnum()) {
setEnumField(field, value);
} else {
logger.error("Set field Error name : " + name + " value : " + value);
setObjectField(field, value);
}
}
} catch (NoSuchFieldException e) {
} catch (NoSuchFieldException | NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
logger.error("Set field Error name : " + name + " value : " + value);
throw new RuntimeException(e);
}
}

private void setObjectField(final Field field, final String value)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Constructor<?> constructor = field.getType().getDeclaredConstructor(String.class);
constructor.setAccessible(true);
Object fieldValue = constructor.newInstance(value);
constructor.setAccessible(false);
setFieldBy(entity.getAdditionalInformation(), field, fieldValue);
}

private void setEnumField(final Field field, final String value)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Object[] enumConstants = field.getType().getEnumConstants();
for (Object enumConstant : enumConstants) {
Method method = enumConstant.getClass().getMethod("name");
String enumName = (String) method.invoke(enumConstant);
if (enumName.equals(value)) {
setFieldBy(entity.getAdditionalInformation(), field, enumConstant);
return;
}
}
setFieldBy(entity.getAdditionalInformation(), field, null);
}

private static boolean isHibernateField(final String name) {
return name.equals("$$_hibernate_attributeInterceptor") || name.equals("$$_hibernate_compositeOwners");
}

private boolean isKeycloakBasicInformationField(final String name) {
return Arrays.stream(entity.getClass().getDeclaredFields())
.anyMatch(f -> f.getName().equals(name));
Expand All @@ -110,19 +162,10 @@ private boolean isAdditionalInformationField(final String name) {
.anyMatch(f -> f.getName().equals(name));
}

private void setFieldBy(final Field field, final String value) {
try {
field.setAccessible(true);
field.set(entity, value);
field.setAccessible(false);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}

@Override
public void removeAttribute(String name) {
setFieldValueByName(name, null);
private void setFieldBy(final Object entity, final Field field, final Object value) throws IllegalAccessException {
field.setAccessible(true);
field.set(entity, value);
field.setAccessible(false);
}

@Override
Expand All @@ -142,6 +185,7 @@ public Map<String, List<String>> getAttributes() {
}
field.setAccessible(false);
}
all.keySet().removeIf(UserAdapter::isHibernateField);
return all;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.mju.domain;

import java.time.LocalDateTime;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
Expand Down Expand Up @@ -32,6 +33,8 @@ public class UserEntity {
@Embedded
private AdditionalInformation additionalInformation = new AdditionalInformation();

private LocalDateTime modifiedDate;

protected UserEntity() {
}

Expand All @@ -45,6 +48,7 @@ public UserEntity(
this.email = email;
this.password = password;
this.additionalInformation = additionalInformation;
this.change();
}

public String getId() {
Expand All @@ -66,4 +70,8 @@ public String getUsername() {
public AdditionalInformation getAdditionalInformation() {
return additionalInformation;
}

protected void change() {
this.modifiedDate = LocalDateTime.now();
}
}
2 changes: 2 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
rootProject.name = 'sso'

include 'keycloak-user-storage-jpa'

0 comments on commit afe1868

Please sign in to comment.