-
Notifications
You must be signed in to change notification settings - Fork 127
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
baaa4db
commit 7ad6d49
Showing
37 changed files
with
1,685 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
security-annotations/src/main/java/io/micronaut/security/annotation/CreatedBy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* | ||
* Copyright 2017-2023 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micronaut.security.annotation; | ||
|
||
import io.micronaut.data.annotation.AutoPopulated; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* An annotation for use with Micronaut Data entities that will cause the annotated field to be automatically | ||
* populated on save with the identity of the currently authenticated user. | ||
* | ||
* @author Jeremy Grelle | ||
* @since 4.5.0 | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ElementType.METHOD, ElementType.FIELD}) | ||
@Documented | ||
@AutoPopulated(updateable = false) | ||
public @interface CreatedBy { | ||
} |
38 changes: 38 additions & 0 deletions
38
security-annotations/src/main/java/io/micronaut/security/annotation/UpdatedBy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* | ||
* Copyright 2017-2023 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micronaut.security.annotation; | ||
|
||
import io.micronaut.data.annotation.AutoPopulated; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* An annotation for use with Micronaut Data entities that will cause the annotated field to be automatically | ||
* populated on both save and update with the identity of the currently authenticated user. | ||
* | ||
* @author Jeremy Grelle | ||
* @since 4.5.0 | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ElementType.METHOD, ElementType.FIELD}) | ||
@Documented | ||
@AutoPopulated | ||
public @interface UpdatedBy { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
security/src/main/java/io/micronaut/security/audit/UserAuditingEntityEventListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/* | ||
* Copyright 2017-2023 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micronaut.security.audit; | ||
|
||
import io.micronaut.context.annotation.Requires; | ||
import io.micronaut.core.annotation.AnnotationMetadata; | ||
import io.micronaut.core.annotation.NonNull; | ||
import io.micronaut.core.annotation.Nullable; | ||
import io.micronaut.core.beans.BeanProperty; | ||
import io.micronaut.core.convert.ConversionService; | ||
import io.micronaut.core.convert.exceptions.ConversionErrorException; | ||
import io.micronaut.data.annotation.AutoPopulated; | ||
import io.micronaut.data.annotation.event.PrePersist; | ||
import io.micronaut.data.annotation.event.PreUpdate; | ||
import io.micronaut.data.event.EntityEventContext; | ||
import io.micronaut.data.model.runtime.RuntimePersistentProperty; | ||
import io.micronaut.data.runtime.event.listeners.AutoPopulatedEntityEventListener; | ||
import io.micronaut.security.annotation.CreatedBy; | ||
import io.micronaut.security.annotation.UpdatedBy; | ||
import io.micronaut.security.authentication.Authentication; | ||
import io.micronaut.security.utils.SecurityService; | ||
import jakarta.inject.Singleton; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.util.*; | ||
import java.util.function.Predicate; | ||
|
||
/** | ||
* An event listener that handles auto-population of entity fields annotated with {@link CreatedBy} or | ||
* {@link UpdatedBy} by mapping them from the current {@link Authentication}. | ||
* | ||
* @author Jeremy Grelle | ||
* @since 4.5.0 | ||
*/ | ||
@Requires(classes = { AutoPopulatedEntityEventListener.class, EntityEventContext.class }) | ||
@Singleton | ||
final class UserAuditingEntityEventListener extends AutoPopulatedEntityEventListener { | ||
private static final Logger LOG = LoggerFactory.getLogger(UserAuditingEntityEventListener.class); | ||
|
||
private final SecurityService securityService; | ||
|
||
private final ConversionService conversionService; | ||
|
||
UserAuditingEntityEventListener(SecurityService securityService, ConversionService conversionService) { | ||
this.securityService = securityService; | ||
this.conversionService = conversionService; | ||
} | ||
|
||
@Override | ||
public boolean prePersist(@NonNull EntityEventContext<Object> context) { | ||
return populate(context, PrePersist.class); | ||
} | ||
|
||
@Override | ||
public boolean preUpdate(@NonNull EntityEventContext<Object> context) { | ||
return populate(context, PreUpdate.class); | ||
} | ||
|
||
@Override | ||
protected @NonNull List<Class<? extends Annotation>> getEventTypes() { | ||
return Arrays.asList(PrePersist.class, PreUpdate.class); | ||
} | ||
|
||
@Override | ||
protected @NonNull Predicate<RuntimePersistentProperty<Object>> getPropertyPredicate() { | ||
return property -> { | ||
final AnnotationMetadata annotationMetadata = property.getAnnotationMetadata(); | ||
return annotationMetadata.hasAnnotation(CreatedBy.class) || annotationMetadata.hasAnnotation(UpdatedBy.class); | ||
}; | ||
} | ||
|
||
private boolean populate(@NonNull EntityEventContext<Object> context, | ||
@NonNull Class<? extends Annotation> listenerAnnotation) { | ||
try { | ||
securityService.getAuthentication().ifPresent(authentication -> { | ||
Map<Class<?>, Object> valueForType = new HashMap<>(); | ||
for (RuntimePersistentProperty<Object> persistentProperty : getApplicableProperties(context.getPersistentEntity())) { | ||
if (shouldSetProperty(persistentProperty, listenerAnnotation)) { | ||
final BeanProperty<Object, Object> beanProperty = persistentProperty.getProperty(); | ||
Object value = valueForType.computeIfAbsent(beanProperty.getType(), type -> convert(authentication, beanProperty)); | ||
if (value != null) { | ||
context.setProperty(beanProperty, value); | ||
} | ||
} | ||
} | ||
}); | ||
return true; | ||
} catch (ConversionErrorException e) { | ||
return false; | ||
} | ||
} | ||
|
||
@Nullable | ||
private Object convert(@NonNull Authentication authentication, @NonNull BeanProperty<Object, Object> beanProperty) throws ConversionErrorException { | ||
try { | ||
return conversionService.convertRequired(authentication, beanProperty.getType()); | ||
} catch (ConversionErrorException e) { | ||
if (LOG.isErrorEnabled()) { | ||
LOG.error("Cannot convert from {} to {} for bean property {}", authentication.getClass().getSimpleName(), beanProperty.getType(), beanProperty.getName(), e); | ||
} | ||
throw e; | ||
} | ||
} | ||
|
||
private boolean shouldSetProperty(@NonNull RuntimePersistentProperty<Object> persistentProperty, Class<? extends Annotation> listenerAnnotation) { | ||
if (listenerAnnotation == PrePersist.class) { | ||
return true; | ||
} | ||
if (listenerAnnotation == PreUpdate.class) { | ||
return persistentProperty.getAnnotationMetadata().booleanValue(AutoPopulated.class, AutoPopulated.UPDATEABLE).orElse(true); | ||
} | ||
return false; | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
security/src/main/java/io/micronaut/security/audit/package-info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* Copyright 2017-2023 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
/** | ||
* Contains classes specific to adding security auditing integration with Micronaut Data. | ||
* | ||
* @author Jeremy Grelle | ||
* @since 4.5.0 | ||
*/ | ||
package io.micronaut.security.audit; |
54 changes: 54 additions & 0 deletions
54
security/src/main/java/io/micronaut/security/converters/PrincipalToStringConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright 2017-2023 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micronaut.security.converters; | ||
|
||
import io.micronaut.core.annotation.Internal; | ||
import io.micronaut.core.convert.ConversionContext; | ||
import io.micronaut.core.convert.TypeConverter; | ||
import io.micronaut.security.annotation.CreatedBy; | ||
import io.micronaut.security.annotation.UpdatedBy; | ||
import io.micronaut.security.authentication.Authentication; | ||
|
||
import java.security.Principal; | ||
import java.util.Optional; | ||
|
||
/** | ||
* A {@link Principal} to {@code String} converter. | ||
* | ||
* This is intended as the default implementation for conversion of the current {@link Authentication} to {@code String} | ||
* entity fields annotated with either {@link CreatedBy} or {@link UpdatedBy}, | ||
* and simply converts to {@link Principal#getName()}. | ||
* This implementation may be replaced for custom mapping of a unique {@link String} identifier, or additional converters | ||
* may be provided for mapping to more complex types. | ||
* | ||
* @author Jeremy Grelle | ||
* @since 4.5.0 | ||
*/ | ||
@Internal | ||
final class PrincipalToStringConverter implements TypeConverter<Principal, String> { | ||
|
||
/** | ||
* | ||
* @param principal The source principal | ||
* @param targetType The target type being converted to | ||
* @param context The {@link ConversionContext} | ||
* @return The converted type or empty if the conversion is not possible | ||
*/ | ||
@Override | ||
public Optional<String> convert(Principal principal, Class<String> targetType, ConversionContext context) { | ||
return Optional.ofNullable(principal.getName()); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
security/src/main/java/io/micronaut/security/converters/SecurityTypeConvertersRegistrar.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* Copyright 2017-2024 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micronaut.security.converters; | ||
|
||
import io.micronaut.core.annotation.Internal; | ||
import io.micronaut.core.convert.MutableConversionService; | ||
import io.micronaut.core.convert.TypeConverterRegistrar; | ||
|
||
import java.security.Principal; | ||
|
||
/** | ||
* Registers security {@link io.micronaut.core.convert.TypeConverter}s. | ||
* @author Sergio del Amo | ||
* @since 4.5.0 | ||
*/ | ||
@Internal | ||
public final class SecurityTypeConvertersRegistrar implements TypeConverterRegistrar { | ||
@Override | ||
public void register(MutableConversionService conversionService) { | ||
conversionService.addConverter(Principal.class, String.class, new PrincipalToStringConverter()); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
security/src/main/java/io/micronaut/security/converters/package-info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright 2017-2024 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
/** | ||
* Security {@link io.micronaut.core.convert.TypeConverter}s. | ||
*/ | ||
package io.micronaut.security.converters; |
1 change: 1 addition & 0 deletions
1
...ity/src/main/resources/META-INF/services/io.micronaut.core.convert.TypeConverterRegistrar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
io.micronaut.security.converters.SecurityTypeConvertersRegistrar |
Oops, something went wrong.