diff --git a/deployment/pom.xml b/deployment/pom.xml index 00dfe3e..7052130 100644 --- a/deployment/pom.xml +++ b/deployment/pom.xml @@ -46,6 +46,10 @@ io.quarkus quarkus-websockets-client-deployment + + io.quarkus + quarkus-security-deployment + io.quarkus quarkus-jsonp-deployment @@ -56,7 +60,7 @@ io.quarkus - quarkus-vertx-http-dev-ui-spi + quarkus-devui-deployment-spi io.quarkus diff --git a/deployment/src/main/java/io/quarkiverse/omnifaces/deployment/OmnifacesProcessor.java b/deployment/src/main/java/io/quarkiverse/omnifaces/deployment/OmnifacesProcessor.java index 4af341c..993e34e 100644 --- a/deployment/src/main/java/io/quarkiverse/omnifaces/deployment/OmnifacesProcessor.java +++ b/deployment/src/main/java/io/quarkiverse/omnifaces/deployment/OmnifacesProcessor.java @@ -36,6 +36,9 @@ import org.omnifaces.config.WebXml; import org.omnifaces.resourcehandler.CombinedResourceHandler; import org.omnifaces.resourcehandler.WebAppManifest; +import org.omnifaces.security.AnonymousTagHandler; +import org.omnifaces.security.AuthenticatedTagHandler; +import org.omnifaces.security.AuthorizeTagHandler; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem; @@ -185,9 +188,25 @@ void registerForReflection(BuildProducer reflectiveCla ReflectiveClassBuildItem.builder(classNames.toArray(new String[0])).methods(true).serialization(true).build()); } + @BuildStep + void registerSecurityTaglibForReflection(BuildProducer reflectiveClass) { + final List classes = new ArrayList<>(); + + classes.add(AnonymousTagHandler.class.getName()); + classes.add(AuthenticatedTagHandler.class.getName()); + classes.add(AuthorizeTagHandler.class.getName()); + + reflectiveClass.produce(ReflectiveClassBuildItem.builder(classes.toArray(new String[0])) + .constructors() + .methods() + .fields() + .serialization() + .build()); + } + @Record(ExecutionTime.STATIC_INIT) @BuildStep - void registerWebManifests(OmniFacesRecorder recorder, BuildProducer unremovableBeans) { + void registerUnremovableBeans(OmniFacesRecorder recorder, BuildProducer unremovableBeans) { // make WebManifest beans un-removable, users still have to make them beans // https://github.com/quarkiverse/quarkus-omnifaces/issues/72 unremovableBeans.produce(UnremovableBeanBuildItem.beanTypes(WebAppManifest.class)); @@ -204,6 +223,7 @@ void substrateResourceBuildItems(BuildProducer nat "META-INF/omnifaces.taglib.xml", "META-INF/omnifaces-functions.taglib.xml", "META-INF/omnifaces-ui.taglib.xml", + "META-INF/omnifaces-security.taglib.xml", "META-INF/web-fragment.xml", "META-INF/faces-config.xml", "META-INF/web.xml", diff --git a/deployment/src/main/java/io/quarkiverse/omnifaces/deployment/devui/OmnifacesDevUIProcessor.java b/deployment/src/main/java/io/quarkiverse/omnifaces/deployment/devui/OmnifacesDevUIProcessor.java index 9c72151..d73c099 100644 --- a/deployment/src/main/java/io/quarkiverse/omnifaces/deployment/devui/OmnifacesDevUIProcessor.java +++ b/deployment/src/main/java/io/quarkiverse/omnifaces/deployment/devui/OmnifacesDevUIProcessor.java @@ -1,7 +1,5 @@ package io.quarkiverse.omnifaces.deployment.devui; -import org.omnifaces.config.WebXml; - import io.quarkus.deployment.IsDevelopment; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; @@ -17,18 +15,12 @@ */ public class OmnifacesDevUIProcessor { - private static final String EXTENSION_NAME = "OmniFaces"; - @BuildStep(onlyIf = IsDevelopment.class) void createCard(BuildProducer cardPageBuildItemBuildProducer) { final CardPageBuildItem card = new CardPageBuildItem(); - final PageBuilder versionPage = Page.externalPageBuilder("Version") - .icon("font-awesome-solid:book") - .url("https://omnifaces.org/") - .doNotEmbed() - .staticLabel(WebXml.class.getPackage().getImplementationVersion()); - card.addPage(versionPage); + card.addLibraryVersion("org.omnifaces", "omnifaces", "OmniFaces", + "https://omnifaces.org/"); final PageBuilder localePage = Page.externalPageBuilder("Locale") .icon("font-awesome-solid:location-dot") @@ -44,8 +36,6 @@ void createCard(BuildProducer cardPageBuildItemBuildProducer) .dynamicLabelJsonRPCMethodName("getSessionTimeout"); card.addPage(sessionPage); - card.setCustomCard("qwc-omnifaces-card.js"); - cardPageBuildItemBuildProducer.produce(card); } diff --git a/deployment/src/main/resources/dev-ui/qwc-omnifaces-card.js b/deployment/src/main/resources/dev-ui/qwc-omnifaces-card.js deleted file mode 100644 index 066a02f..0000000 --- a/deployment/src/main/resources/dev-ui/qwc-omnifaces-card.js +++ /dev/null @@ -1,92 +0,0 @@ -import { LitElement, html, css} from 'lit'; -import { pages } from 'build-time-data'; -import {JsonRpc} from 'jsonrpc'; -import 'qwc/qwc-extension-link.js'; - -export class QwcOmniFacesCard extends LitElement { - - jsonRpc = new JsonRpc(this); - - static styles = css` - .identity { - display: flex; - justify-content: flex-start; - } - - .description { - padding-bottom: 10px; - } - - .logo { - padding-bottom: 10px; - margin-right: 5px; - } - - .card-content { - color: var(--lumo-contrast-90pct); - display: flex; - flex-direction: column; - justify-content: flex-start; - padding: 2px 2px; - height: 100%; - } - - .card-content slot { - display: flex; - flex-flow: column wrap; - padding-top: 5px; - } - `; - - static properties = { - extensionName: {attribute: true}, - description: {attribute: true}, - guide: {attribute: true}, - namespace: {attribute: true}, - }; - - constructor() { - super(); - } - - connectedCallback() { - super.connectedCallback(); - } - - render() { - return html`
-
- -
${this.description}
-
- ${this._renderCardLinks()} -
- `; - } - - _renderCardLinks(){ - return html`${pages.map(page => html` - - - `)}`; - } - -} -customElements.define('qwc-omnifaces-card', QwcOmniFacesCard); \ No newline at end of file diff --git a/pom.xml b/pom.xml index f62cba1..efd465e 100644 --- a/pom.xml +++ b/pom.xml @@ -24,9 +24,10 @@ 17 - 3.27.0 + 4.0.0 + 3.27.1 4.1.2 - 5.0-M6 + 5.0 diff --git a/runtime/pom.xml b/runtime/pom.xml index dadcfdd..3c2d4b4 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -21,6 +21,10 @@ io.quarkus quarkus-jaxp
+ + io.quarkus + quarkus-security + io.quarkus quarkus-info-runtime-spi @@ -37,6 +41,11 @@ org.omnifaces omnifaces + + jakarta.security.enterprise + jakarta.security.enterprise-api + ${jakarta-security.version} + org.graalvm.sdk graal-sdk diff --git a/runtime/src/main/java/io/quarkus/omnifaces/runtime/FacesInfoContributor.java b/runtime/src/main/java/io/quarkus/omnifaces/runtime/FacesInfoContributor.java index f00eea7..9d39e55 100644 --- a/runtime/src/main/java/io/quarkus/omnifaces/runtime/FacesInfoContributor.java +++ b/runtime/src/main/java/io/quarkus/omnifaces/runtime/FacesInfoContributor.java @@ -4,6 +4,7 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Strings; import org.omnifaces.util.Faces; import io.quarkus.info.runtime.spi.InfoContributor; @@ -18,7 +19,7 @@ public String name() { @Override public Map data() { - String facesImpl = StringUtils.removeIgnoreCase(StringUtils.removeIgnoreCase(Faces.getImplInfo(), "Core"), "Impl"); + String facesImpl = Strings.CI.remove(Strings.CI.remove(Faces.getImplInfo(), "Core"), "Impl"); String server = "Undertow " + Undertow.class.getPackage().getImplementationVersion(); String omniFaces = "OmniFaces: " + StringUtils.defaultIfEmpty( org.omnifaces.util.Faces.class.getPackage().getImplementationVersion(), "???"); diff --git a/runtime/src/main/java/io/quarkus/omnifaces/runtime/SecurityContextImpl.java b/runtime/src/main/java/io/quarkus/omnifaces/runtime/SecurityContextImpl.java new file mode 100644 index 0000000..6b496ac --- /dev/null +++ b/runtime/src/main/java/io/quarkus/omnifaces/runtime/SecurityContextImpl.java @@ -0,0 +1,74 @@ +package io.quarkus.omnifaces.runtime; + +import java.security.Principal; +import java.util.HashSet; +import java.util.Set; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.security.enterprise.AuthenticationStatus; +import jakarta.security.enterprise.SecurityContext; +import jakarta.security.enterprise.authentication.mechanism.http.AuthenticationParameters; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import io.quarkus.security.identity.SecurityIdentity; + +/** + * Basic Jakarta SecurityContext implementation + * based on Quarkus' SecurityIdentity + * + * @author Leonardo Bernardes + */ +@Named +@RequestScoped +public class SecurityContextImpl implements SecurityContext { + + @Inject + SecurityIdentity identity; + + @Override + public Principal getCallerPrincipal() { + return identity.isAnonymous() ? null : identity.getPrincipal(); + } + + @Override + public Set getPrincipalsByType(Class pType) { + Set result = new HashSet<>(); + + if (!identity.isAnonymous()) + result.add(identity.getPrincipal(pType)); + + return result; + } + + @Override + public boolean isCallerInRole(String role) { + if (identity.isAnonymous()) + return false; + + return identity.hasRole(role); + } + + @Override + public Set getAllDeclaredCallerRoles() { + Set result = new HashSet<>(); + + if (!identity.isAnonymous()) + result = identity.getRoles(); + + return result; + } + + @Override + public boolean hasAccessToWebResource(String resource, String... methods) { + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public AuthenticationStatus authenticate(HttpServletRequest request, HttpServletResponse response, + AuthenticationParameters parameters) { + throw new UnsupportedOperationException("Not implemented"); + } +}