Coder Social home page Coder Social logo

quarkiverse / quarkus-renarde Goto Github PK

View Code? Open in Web Editor NEW
74.0 9.0 16.0 4.96 MB

Server-side Web Framework with Qute templating, magic/easier controllers, auth, reverse-routing

License: Apache License 2.0

Java 98.09% HTML 1.87% CSS 0.02% JavaScript 0.02%
quarkus-extension

quarkus-renarde's Introduction

quarkus-renarde's People

Contributors

actions-user avatar allcontributors[bot] avatar aloubyansky avatar dependabot[bot] avatar fromage avatar gastaldi avatar gbourant avatar gsmet avatar holly-cummins avatar ia3andy avatar ladicek avatar martin-kofoed-jyskebank-dk avatar maxandersen avatar nderwin avatar thejavaguy avatar yatho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quarkus-renarde's Issues

Roles with oidc

Currently if an admin want to make an oidc user admin, it is not possible RenardeUser.roles() is only used for JWT users

Passing both a @BeanParam and @RestPath allowed on endpoints?

Hi,

In Quarkus/Renarde, can I pass in a @BeanParam and a @RestPath? I'm trying to do a call to this endpoint and I'm getting a class cast exception:

 @POST
    @Path("/accounts/password/change/{userId}")
    @RolesAllowed({Application.USER_ROLE})
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response doChangePassword(@BeanParam Account.PasswordChange passChangeForm, @RestPath Long userId) {

I originally had just form being passed in and the URL didn't have the userId on the path.

I wanted to add the userId to the path so I can pass the user. I could modify the password form to pass it, but I thought I should be able to pass multiple params.

Is this allowed?

Error:

2023-03-13 14:13:17,076 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-0) HTTP Request to /accounts/password/change/1400 failed, error id: a31d737a-2f85-4735-932b-0e04a084fd78-1: java.lang.ClassCastException: class java.lang.Long cannot be cast to class com.acme.support.site.rest.Account$PasswordChange (java.lang.Long is in module java.base of loader 'bootstrap'; com.acme.support.site.rest.Account$PasswordChange is in unnamed module of loader io.quarkus.bootstrap.runner.RunnerClassLoader @396a51ab)
    at com.acme.support.site.rest.Account.__urivarargs$doChangePassword$33b635c8a9baab1fb6da6216187edcf3bb62c1f7(Account.java)
   at __RenardeInit$$function$$6.getRoute(Unknown Source)
	at io.quarkiverse.renarde.router.Router.findURI(Router.java:152)
	at io.quarkiverse.renarde.util.QuteResolvers.findURI(QuteResolvers.java:65)
	at io.quarkiverse.renarde.util.QuteResolvers.lambda$configureEngine$1(QuteResolvers.java:47)
	at io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)
	at io.smallrye.mutiny.operators.uni.UniAndCombination$AndSupervisor.computeAndFireTheOutcome(UniAndCombination.java:147)
	at io.smallrye.mutiny.operators.uni.UniAndCombination$AndSupervisor.check(UniAndCombination.java:131)
	at io.smallrye.mutiny.operators.uni.UniAndCombination$UniHandler.onItem(UniAndCombination.java:221)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromCompletionStage$CompletionStageUniSubscription.forwardResult(UniCreateFromCompletionStage.java:63)
	at io.quarkus.qute.CompletedStage.whenComplete(CompletedStage.java:268)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromCompletionStage$CompletionStageUniSubscription.forward(UniCreateFromCompletionStage.java:51)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromCompletionStage.subscribe(UniCreateFromCompletionStage.java:35)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniAndCombination$UniHandler.subscribe(UniAndCombination.java:234)
	at io.smallrye.mutiny.operators.uni.UniAndCombination$AndSupervisor.run(UniAndCombination.java:88)
	at io.smallrye.mutiny.operators.uni.UniAndCombination$AndSupervisor.access$000(UniAndCombination.java:57)
	at io.smallrye.mutiny.operators.uni.UniAndCombination.subscribe(UniAndCombination.java:54)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:52)
	at io.smallrye.mutiny.groups.UniSubscribe.with(UniSubscribe.java:112)
	at io.smallrye.mutiny.operators.uni.UniSubscribeToCompletionStage.subscribe(UniSubscribeToCompletionStage.java:30)
	at io.smallrye.mutiny.groups.UniSubscribe.asCompletionStage(UniSubscribe.java:178)
	at io.smallrye.mutiny.groups.UniSubscribe.asCompletionStage(UniSubscribe.java:165)
	at io.smallrye.mutiny.Uni.subscribeAsCompletionStage(Uni.java:142)
	at io.smallrye.mutiny.converters.uni.ToCompletionStage.apply(ToCompletionStage.java:18)
	at io.smallrye.mutiny.converters.uni.ToCompletionStage.apply(ToCompletionStage.java:8)
	at io.smallrye.mutiny.groups.UniConvert.with(UniConvert.java:33)
	at io.smallrye.mutiny.groups.UniConvert.toCompletionStage(UniConvert.java:38)
	at io.quarkiverse.renarde.util.QuteResolvers.lambda$configureEngine$2(QuteResolvers.java:48)
	at io.quarkus.qute.ValueResolverBuilder$5.apply(ValueResolverBuilder.java:135)
	at io.quarkus.qute.ValueResolverBuilder$5.apply(ValueResolverBuilder.java:132)
	at io.quarkus.qute.ValueResolverBuilder$ValueResolverImpl.resolve(ValueResolverBuilder.java:179)
	at io.quarkus.qute.EvaluatorImpl.resolve(EvaluatorImpl.java:208)
	at io.quarkus.qute.EvaluatorImpl.resolveReference(EvaluatorImpl.java:128)
	at io.quarkus.qute.EvaluatorImpl.lambda$evaluate$0(EvaluatorImpl.java:80)
	at io.quarkus.qute.CompletedStage.thenCompose(CompletedStage.java:232)
	at io.quarkus.qute.EvaluatorImpl.evaluate(EvaluatorImpl.java:79)
	at io.quarkus.qute.ResolutionContextImpl$ChildResolutionContext.evaluate(ResolutionContextImpl.java:87)
	at io.quarkus.qute.Futures.evaluateParams(Futures.java:50)
	at io.quarkus.qute.IncludeSectionHelper.resolve(IncludeSectionHelper.java:54)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:53)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:58)
	at io.quarkus.qute.SectionNode$SectionResolutionContextImpl.execute(SectionNode.java:223)
	at io.quarkus.qute.InsertSectionHelper.resolve(InsertSectionHelper.java:20)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:53)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:58)
	at io.quarkus.qute.SectionNode$SectionResolutionContextImpl.execute(SectionNode.java:223)
	at io.quarkus.qute.SectionHelper$SectionResolutionContext.execute(SectionHelper.java:46)
	at io.quarkus.qute.Parser$1.resolve(Parser.java:1247)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:53)
	at io.quarkus.qute.IncludeSectionHelper.lambda$resolve$1(IncludeSectionHelper.java:71)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenCompleteStage(CompletableFuture.java:887)
	at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:2325)
	at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:144)
	at io.quarkus.qute.IncludeSectionHelper.resolve(IncludeSectionHelper.java:54)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:53)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:58)
	at io.quarkus.qute.SectionNode$SectionResolutionContextImpl.execute(SectionNode.java:219)
	at io.quarkus.qute.SectionHelper$SectionResolutionContext.execute(SectionHelper.java:46)
	at io.quarkus.qute.Parser$1.resolve(Parser.java:1247)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:53)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:58)
	at io.quarkus.qute.TemplateImpl$TemplateInstanceImpl.renderData(TemplateImpl.java:227)
	at io.quarkus.qute.TemplateImpl$TemplateInstanceImpl.renderAsyncNoTimeout(TemplateImpl.java:218)
	at io.smallrye.context.impl.wrappers.SlowContextualSupplier.get(SlowContextualSupplier.java:21)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromCompletionStage.subscribe(UniCreateFromCompletionStage.java:24)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniFailOnTimeout.subscribe(UniFailOnTimeout.java:36)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:52)
	at io.smallrye.mutiny.groups.UniSubscribe.with(UniSubscribe.java:112)
	at io.smallrye.mutiny.groups.UniSubscribe.with(UniSubscribe.java:89)
	at org.jboss.resteasy.reactive.server.filters.FilterUtil.handleUniVoid(FilterUtil.java:61)
	at io.quarkus.resteasy.reactive.qute.runtime.TemplateResponseFilter$GeneratedServerResponseFilter$filter.filter(Unknown Source)
	at org.jboss.resteasy.reactive.server.spi.ResteasyReactiveContainerResponseFilter.filter(ResteasyReactiveContainerResponseFilter.java:10)
	at org.jboss.resteasy.reactive.server.handlers.ResourceResponseFilterHandler.handle(ResourceResponseFilterHandler.java:25)
	at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:123)
	at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)

"The class io.quarkiverse.renarde.Controller is not inside the Jandex index"

I was working with the 3.0.0.CR2 version of Quarkus until this afternoon, using the 3.0.0 version of Renarde. After upgrading Quarkus to to 3.0.1.Final, I started getting following exception when starting my application:

	[error]: Build step io.quarkus.rest.client.reactive.deployment.RestClientReactiveProcessor#addRestClientBeans threw an exception: java.lang.RuntimeException: The class io.quarkiverse.renarde.Controller is not inside the Jandex index
	at org.jboss.resteasy.reactive.common.processor.JandexUtil.isImplementorOf(JandexUtil.java:397)
	at io.quarkus.rest.client.reactive.deployment.RestClientReactiveProcessor.addRestClientBeans(RestClientReactiveProcessor.java:510)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:909)
	at io.quarkus.builder.BuildContext.run(BuildContext.java:282)
	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
	at java.base/java.lang.Thread.run(Thread.java:833)
	at org.jboss.threads.JBossThread.run(JBossThread.java:501)

Any idea on what's wrong and how I can fix that?

D.

Build Break: 'quarkus.oidc.auth-server-url' is required even when not using OIDC (Production Mode)

Hello again,

Since we are just using JWT and JDBC for authentication we don't need any of the OIDC configuration settings.

However, when running our app in PROD mode we are required to add the configuration key:

quarkus.oidc.auth-server-url

So, to get around the error I entered:
quarkus.oidc.auth-server-url=http://localhost

the stops the build time error however upon startup we get a WARN and the application seems to run fine so far.

It seems that most security on Quarkus assumes everyone is using OIDC? We aren't and are just using standard JDBC (for now).

Thanks again!

2022-09-18 15:04:51,460 WARN  [io.qua.oid.com.run.OidcCommonUtils] (vert.x-eventloop-thread-1) OIDC Server is not available:: io.quarkus.oidc.common.runtime.OidcEndpointAccessException
        at io.quarkus.oidc.common.runtime.OidcCommonUtils.lambda$discoverMetadata$2(OidcCommonUtils.java:406)
        at io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)
        at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:36)
        at io.smallrye.mutiny.vertx.AsyncResultUni.lambda$subscribe$1(AsyncResultUni.java:35)
        at io.smallrye.mutiny.vertx.DelegatingHandler.handle(DelegatingHandler.java:25)
        at io.vertx.ext.web.client.impl.HttpContext.handleDispatchResponse(HttpContext.java:390)
        at io.vertx.ext.web.client.impl.HttpContext.execute(HttpContext.java:377)

How to generate REST endpoint URLS in Templates?

Hi,

In Play framework, they appear to let you generate REST endpoints in the HTML using something like:
jsRoutes.controllers.Blogs.view(parseInt(full.id));

and things like <img src="@routes.Assets.at("images/checkmark_12x12.png")"/> to point to images, etc.

Is this possible in Renarde?

I'd like to also return JSON data to populate HTML UI components which use Ajax to fetch the data from our backend endpoints running in the same app.

something like "http://localhost/videos/listJson" and have this URI autogenerated in our templates.

Does the {uri} do this? and if so does it handle parameters as well?

Thanks.

Use @Path("/foo") on Controller and @Path("/bar") Router resolve to `/bar`

Spec clearly state that it should resolve to /foo/bar instead.

This is what is wrong: Router.getURI(FooController::bar) and also when using uri:FooController.bar from a template.

The endpoint though is working as expected /foo/bar is reachable.

PS: is there a reason for not having bar resolving to foo/bar and /bar to /bar which allows more possibilities.

An issue which fix also this bug on the plugins:
redhat-developer/quarkus-ls#892

Runtime failure with Quarkus 3.0.1.Final and 3.0.0 branch of Renarde

I've upgraded my pom.xml to use the latest Quarkus 3.0.1.Final and the 3.0.0 branch of Renarde both security and main modules.

After changing all my references from javax to jakarta, etc. everything builds and deploys.

But when I make my first attempt at authorization checking I get the following error:

Is the 3.0.0 branch production ready?

If I try to use the 1.0.5 version which works with Quarkus 2.16.x in the 3.0.1.Final pom, I get errors from Renarde because it is still using the old Javax references.

2023-04-26 16:23:54,073 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (vert.x-eventloop-thread-1) HTTP Request to /apple-touch-icon-precomposed.png failed, error id: f2fef1dc-3f33-4560-b3db-72b3797dc82f-3: java.lang.NoSuchMethodError: io.quarkus.smallrye.jwt.runtime.auth.JWTAuthMechanism: method 'void <init>()' not found
support-site     | 	at io.quarkiverse.renarde.util.RenardeJWTAuthMechanism.<init>(RenardeJWTAuthMechanism.java:22)
support-site     | 	at io.quarkiverse.renarde.util.RenardeJWTAuthMechanism_ClientProxy.<init>(Unknown Source)
support-site     | 	at io.quarkiverse.renarde.util.RenardeJWTAuthMechanism_Bean.proxy(Unknown Source)
support-site     | 	at io.quarkiverse.renarde.util.RenardeJWTAuthMechanism_Bean.get(Unknown Source)
support-site     | 	at io.quarkiverse.renarde.util.RenardeJWTAuthMechanism_Bean.get(Unknown Source)
support-site     | 	at io.quarkus.arc.impl.InstanceImpl.getBeanInstance(InstanceImpl.java:323)
support-site     | 	at io.quarkus.arc.impl.InstanceImpl$InstanceIterator.next(InstanceImpl.java:361)
support-site     | 	at io.quarkus.vertx.http.runtime.security.HttpAuthenticator.<init>(HttpAuthenticator.java:41)
support-site     | 	at io.quarkus.vertx.http.runtime.security.HttpAuthenticator_Bean.doCreate(Unknown Source)
support-site     | 	at io.quarkus.vertx.http.runtime.security.HttpAuthenticator_Bean.create(Unknown Source)
support-site     | 	at io.quarkus.vertx.http.runtime.security.HttpAuthenticator_Bean.create(Unknown Source)
support-site     | 	at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:113)
support-site     | 	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:37)
support-site     | 	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:34)
support-site     | 	at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
support-site     | 	at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
support-site     | 	at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:34)
support-site     | 	at io.quarkus.vertx.http.runtime.security.HttpAuthenticator_Bean.get(Unknown Source)
support-site     | 	at io.quarkus.vertx.http.runtime.security.HttpAuthenticator_Bean.get(Unknown Source)```

Localisation working in 'dev mode', but not in packaged application

When running my application in dev mode everything works great. But when I package my application and run it from command line, RenardeConfig.addLanguageBundle tries to locate message files from absolute path of project workspace and not from application package. I get exception:

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at io.quarkus.bootstrap.runner.QuarkusEntryPoint.doRun(QuarkusEntryPoint.java:61)
	at io.quarkus.bootstrap.runner.QuarkusEntryPoint.main(QuarkusEntryPoint.java:32)
Caused by: java.lang.ExceptionInInitializerError
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:70)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
	at io.quarkus.runner.GeneratedMain.main(Unknown Source)
	... 6 more
Caused by: java.lang.RuntimeException: Failed to start quarkus
	at io.quarkus.runner.ApplicationImpl.(Unknown Source)
	... 15 more
Caused by: java.io.UncheckedIOException: java.nio.file.NoSuchFileException: /home/user/workspace/app-name/target/classes/messages_en.properties
	at io.quarkiverse.renarde.impl.RenardeConfig.addLanguageBundle(RenardeConfig.java:43)
	at io.quarkiverse.renarde.impl.RenardeConfig_ClientProxy.addLanguageBundle(Unknown Source)
	at io.quarkiverse.renarde.impl.RenardeRecorder.addLanguageBundle(RenardeRecorder.java:16)
	at io.quarkus.deployment.steps.RenardeProcessor$findMessageFiles848786311.deploy_0(Unknown Source)
	at io.quarkus.deployment.steps.RenardeProcessor$findMessageFiles848786311.deploy(Unknown Source)
	... 16 more
Caused by: java.nio.file.NoSuchFileException: /home/user/workspace/app-name/target/classes/messages_en.properties
	at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
	at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:218)
	at java.base/java.nio.file.Files.newByteChannel(Files.java:380)
	at java.base/java.nio.file.Files.newByteChannel(Files.java:432)
	at java.base/java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:422)
	at java.base/java.nio.file.Files.newInputStream(Files.java:160)
	at java.base/java.nio.file.Files.newBufferedReader(Files.java:2922)
	at io.quarkiverse.renarde.impl.RenardeConfig.addLanguageBundle(RenardeConfig.java:40)
	... 20 more

Investigate possibility of declaring checked-templates as instance native methods

public class Foo extends Controller {
 public native TemplateInstance index();
 public TemplateInstance foo(){
  return index();
 }
}
public class Bar extends Controller {
 public TemplateInstance foo(){
  return template(Foo.class).index();
 }
}

This would allow us shorter declarations for the common cases, but names of templates and controller methods would clash.

Renarde and Keycloak

It's not an issue but more of a question but I couldn't find where to ask it.

Is there any way to use Keycloak as OIDC solution with Renarde? It is something that I would like to do for a company I am building different solutions for but couldn't find nothing in the documentation.

D.

Cookie “_renarde_flash” does not have a proper “SameSite” attribute value

I'm seeing these warnings in Firefox

Cookie “_renarde_flash” does not have a proper “SameSite” attribute value. Soon, cookies without the “SameSite” attribute or with an invalid value will be treated as “Lax”. This means that the cookie will no longer be sent in third-party contexts. If your application depends on this cookie being available in such contexts, please add the “SameSite=None“ attribute to it. To know more about the “SameSite“ attribute, read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite downloads

Unsatisfied dependency for type io.quarkiverse.renarde.oidc.RenardeOidcHandler and qualifiers [@Default]

We are trying to convert a legacy Play 2.x framework web application to run on Quarkus with minimal-changes to the existing code base.

So far it looks like Renamed is a VERY close fit to the Play framework in terms of Routing and template processing which we hope would make it easy to move over to Quarkus.

However, when setting up the user security I ran into an issue. We are NOT using OIDC and only a JDBC backend. Reading the Renarde Security page it looks like I need to import the OIDC dependency.

Doing so and setting up my User class to implement RenardeUser when I try to restart Quarkus I get the error below.

It seems that by making my UserProvider also implement the OIDC provider interface fixes the build issue, but it seems I shouldn't need to do this if just using JWT/Database?

I am using Quarkus 2.12.2.Final and

<dependency>
      <groupId>io.quarkiverse.renarde</groupId>
      <artifactId>quarkus-renarde-oidc</artifactId>
      <version>1.0.3</version>
    </dependency>

Thanks..

public class MyOidcSetup implements RenardeUserProvider,RenardeOidcHandler {

    @Inject
    RenardeSecurity security;

    @Override
    public RenardeUser findUser(String tenantId, String id) {
        return User.findByEmail(id);
    }

    @Override
    public void oidcSuccess(String tenantId, String authId) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void loginWithOidcSession(String tenantId, String authId) {
        // TODO Auto-generated method stub
        
    }
}
2022-09-18 10:00:43,657 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (main) Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
        [error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type io.quarkiverse.renarde.oidc.RenardeOidcHandler and qualifiers [@Default]
        - java member: io.quarkiverse.renarde.oidc.impl.RenardeSecurityController#oidcHandler
        - declared on CLASS bean [types=[io.quarkiverse.renarde.oidc.impl.RenardeSecurityController, java.lang.Object, io.quarkiverse.renarde.Controller], qualifiers=[@Default, @Any], target=io.quarkiverse.renarde.oidc.impl.RenardeSecurityController]
        at io.quarkus.arc.processor.BeanDeployment.processErrors(BeanDeployment.java:1215)

error- and ifError-tags parameter

I just made a little example app with quarkus-renarde together with Unpoly and Tailwind CSS and I'm amazed how good renarde already works!
(If anyone is interested about the setup: Have a look at the Readme of https://github.com/simeonlin/qute-blog -> I’m in love with this approach to build small webapps!)

During this project, everything worked smooth and I only came up with the following issue:

  • I can not use the error- and ifError-tag like mentioned in the documentation. I have to pass the field name like:{#ifError it='title'} to make it work. When I only use {#ifError = 'title'} I receive the following error:
    io.quarkus.qute.TemplateException: Entry \"title\" not found in the data map in expression {title}

Additionally, during the startup of the project, I receive the following "wrong" Warnings:

  • Quarkus detected the use of JSON in JAX-RS method 'MyController#myMethod' but no JSON extension has been added. -> Even if I annotate my Controller with @Produces(MediaType.TEXT_HTML)
  • Unrecognized configuration key "quarkus.oidc.******.authentication.force-redirect-https-scheme" was provided; it will be ignored; verify that the dependency extension for this configuration is set -> I don't use OIDC in this project.

How to define the home.html page ?

Question

How can we define the home.html page which is pointing to resources/templates/home.html?

I tried using an ApplicationScope class and @Resource(name="home.html") without success

package io.halkyon;

import io.quarkus.qute.Template;

import javax.annotation.Resource;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

@ApplicationScoped
public class App {

    @Inject
    @Resource(name="home.html")
    Template main;
}

jakarta.ws.rs.BadRequestException: Malformed quality value

I just compiled the project from the main branch on c0894e5 and tried the same process as the one below:

mvn archetype:generate \
       -DarchetypeGroupId=io.quarkus \
       -DarchetypeArtifactId=quarkus-amazon-lambda-archetype \
       -DarchetypeVersion=3.0.2.Final

And simply added Renarde like this:

quarkus ext add io.quarkiverse.renarde:quarkus-renarde

Originally posted by @omidontop in #116 (comment)

This time I get:

e431dc3f-35: jakarta.ws.rs.BadRequestException: Malformed quality value.
        at org.jboss.resteasy.reactive.server.core.request.QualityValue.parseAsInteger(QualityValue.java:86)
        at org.jboss.resteasy.reactive.server.core.request.QualityValue.valueOf(QualityValue.java:33)
        at org.jboss.resteasy.reactive.server.core.request.AcceptHeaders.evaluateAcceptParameters(AcceptHeaders.java:250)
        at org.jboss.resteasy.reactive.server.core.request.AcceptHeaders.getMediaTypeQualityValues(AcceptHeaders.java:154)
        at org.jboss.resteasy.reactive.server.core.request.ServerDrivenNegotiation.setAcceptHeaders(ServerDrivenNegotiation.java:35)
        at io.quarkus.resteasy.reactive.server.runtime.NotFoundExceptionMapper.selectVariant(NotFoundExceptionMapper.java:259)
        at io.quarkus.resteasy.reactive.server.runtime.NotFoundExceptionMapper.respond(NotFoundExceptionMapper.java:102)
        at io.quarkus.resteasy.reactive.server.runtime.NotFoundExceptionMapper.toResponse(NotFoundExceptionMapper.java:92)
        at io.quarkus.resteasy.reactive.server.runtime.NotFoundExceptionMapper$GeneratedExceptionHandlerFor$Throwable$OfMethod$toResponse.toResponse(Unknown Source)
        at org.jboss.resteasy.reactive.server.core.RuntimeExceptionMapper.mapException(RuntimeExceptionMapper.java:97)
        at org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext.mapExceptionIfPresent(ResteasyReactiveRequestContext.java:337)
        at org.jboss.resteasy.reactive.server.handlers.ExceptionHandler.handle(ExceptionHandler.java:15)
        at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:150)
        at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
        at org.jboss.resteasy.reactive.server.handlers.RestInitialHandler.beginProcessing(RestInitialHandler.java:48)
        at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveVertxHandler.handle(ResteasyReactiveVertxHandler.java:23)
        at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveVertxHandler.handle(ResteasyReactiveVertxHandler.java:10)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
        at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:58)
        at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:36)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
        at io.quarkiverse.renarde.util.AuthenticationFailedExceptionMapper.myFilter(AuthenticationFailedExceptionMapper.java:97)
        at io.quarkiverse.renarde.util.AuthenticationFailedExceptionMapper_RouteHandler_myFilter_dc247f9502a33787ac476eab0f2e905053c2515c.invoke(Unknown Source)
        at io.quarkus.vertx.web.runtime.RouteHandler.handle(RouteHandler.java:97)
        at io.quarkus.vertx.web.runtime.RouteHandler.handle(RouteHandler.java:22)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
        at io.quarkus.vertx.http.runtime.security.AbstractHttpAuthorizer.doPermissionCheck(AbstractHttpAuthorizer.java:110)
        at io.quarkus.vertx.http.runtime.security.AbstractHttpAuthorizer.checkPermission(AbstractHttpAuthorizer.java:93)
        at io.quarkus.vertx.http.runtime.security.HttpAuthorizer.checkPermission(HttpAuthorizer.java:15)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$2.handle(HttpSecurityRecorder.java:85)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$2.handle(HttpSecurityRecorder.java:77)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
        at io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveRecorder$13.handle(ResteasyReactiveRecorder.java:380)
        at io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveRecorder$13.handle(ResteasyReactiveRecorder.java:373)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$AbstractAuthenticationHandler$3$1.onItem(HttpSecurityRecorder.java:438)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$AbstractAuthenticationHandler$3$1.onItem(HttpSecurityRecorder.java:428)
        at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:60)
        at io.smallrye.mutiny.operators.uni.builders.DefaultUniEmitter.complete(DefaultUniEmitter.java:37)
        at io.smallrye.mutiny.groups.UniOnNull.lambda$failWith$1(UniOnNull.java:46)
        at io.smallrye.context.impl.wrappers.SlowContextualBiConsumer.accept(SlowContextualBiConsumer.java:21)
        at io.smallrye.mutiny.groups.UniOnItem.lambda$transformToUni$4(UniOnItem.java:177)
        at io.smallrye.context.impl.wrappers.SlowContextualConsumer.accept(SlowContextualConsumer.java:21)
        at io.smallrye.mutiny.operators.uni.builders.UniCreateWithEmitter.subscribe(UniCreateWithEmitter.java:22)
        at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
        at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:81)
        at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
        at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.forward(UniCreateFromKnownItem.java:38)
        at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem.subscribe(UniCreateFromKnownItem.java:23)
        at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
        at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
        at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
        at io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:51)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$AbstractAuthenticationHandler$3.onItem(HttpSecurityRecorder.java:428)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$AbstractAuthenticationHandler$3.onItem(HttpSecurityRecorder.java:414)
        at io.smallrye.mutiny.operators.uni.UniMemoizeOp.drain(UniMemoizeOp.java:160)
        at io.smallrye.mutiny.operators.uni.UniMemoizeOp.onItem(UniMemoizeOp.java:180)
        at io.smallrye.mutiny.operators.uni.builders.UniCreateFromItemSupplier.subscribe(UniCreateFromItemSupplier.java:29)
        at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
        at io.smallrye.mutiny.operators.uni.UniMemoizeOp.subscribe(UniMemoizeOp.java:84)
        at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
        at io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:51)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$AbstractAuthenticationHandler.handle(HttpSecurityRecorder.java:414)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$AbstractAuthenticationHandler.handle(HttpSecurityRecorder.java:368)
       vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
        at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup.handleHotReplacementRequest(VertxHttpHotReplacementSetup.java:135)
        at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:437)
        at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:433)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
        at io.vertx.ext.web.impl.RouterImpl.handle(RouterImpl.java:68)
        at io.vertx.ext.web.impl.RouterImpl.handle(RouterImpl.java:37)
        at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$2.handle(HttpServerCommonHandlers.java:82)
        at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$2.handle(HttpServerCommonHandlers.java:65)
        at io.quarkus.vertx.http.runtime.VertxHttpRecorder$1.handle(VertxHttpRecorder.java:180)
        at io.quarkus.vertx.http.runtime.VertxHttpRecorder$1.handle(VertxHttpRecorder.java:156)
        at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:55)
        at io.vertx.core.impl.DuplicatedContext.emit(DuplicatedContext.java:158)
        at io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:167)
        at io.vertx.core.net.impl.ConnectionBase.read(ConnectionBase.java:158)
        at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:153)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.vertx.core.http.impl.Http1xUpgradeToH2CHandler.channelRead(Http1xUpgradeToH2CHandler.java:124)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.vertx.core.http.impl.Http1xOrH2CHandler.end(Http1xOrH2CHandler.java:61)
        at io.vertx.core.http.impl.Http1xOrH2CHandler.channelRead(Http1xOrH2CHandler.java:38)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:833)

Cookies should have secure attribute enabled when served over secure connection (HTTPS)

Currently all cookies have the attribute "Secure" set to false (the default value). That is expected for tests and dev mode, but usualy in production people serve the app over HTTPS; and that shouldn't be the case.

cookie

AFAIK the standard approach is to call Cookie.setSecure(HttpServerRequest.isSSL()) when creating new cookies. That should work well for all the above cases, without the need for additional configuration.

Quote from OWASP:
The secure attribute is an option that can be set by the application server when sending a new cookie to the user within an HTTP Response. The purpose of the secure attribute is to prevent cookies from being observed by unauthorized parties due to the transmission of the cookie in clear text. To accomplish this goal, browsers which support the secure attribute will only send cookies with the secure attribute when the request is going to an HTTPS page. Said in another way, the browser will not send a cookie with the secure attribute set over an unencrypted HTTP request. By setting the secure attribute, the browser will prevent the transmission of a cookie over an unencrypted channel.

Persistent RememberMe Cookies?

If I'd like to store the JWT token permanently (or at least, longer than the current session), what is the Quarkus/Renarde way of doing that?

IllegalArgumentException when adding renarde as a dependency

I've just create a simple Quarkus project which started fine. As soon as I added the renarde dependency (version 1.0.0) in the pom.xml, I've started getting following error which doesn't seem to disappear no matter what I do:

022-05-09 10:09:48,360 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (main) Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors [error]: Build step io.quarkus.qute.deployment.QuteProcessor#collectTemplates threw an exception: java.lang.IllegalArgumentException at jdk.zipfs/jdk.nio.zipfs.ZipPath.relativize(ZipPath.java:230) at io.quarkus.qute.deployment.QuteProcessor.scan(QuteProcessor.java:2301) at io.quarkus.qute.deployment.QuteProcessor.scan(QuteProcessor.java:2313) at io.quarkus.qute.deployment.QuteProcessor.collectTemplates(QuteProcessor.java:1291) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:925) at io.quarkus.builder.BuildContext.run(BuildContext.java:277) at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18) at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478) at java.base/java.lang.Thread.run(Thread.java:834) at org.jboss.threads.JBossThread.run(JBossThread.java:501) at io.quarkus.runner.bootstrap.AugmentActionImpl.runAugment(AugmentActionImpl.java:330) at io.quarkus.runner.bootstrap.AugmentActionImpl.createInitialRuntimeApplication(AugmentActionImpl.java:252) at io.quarkus.runner.bootstrap.AugmentActionImpl.createInitialRuntimeApplication(AugmentActionImpl.java:60) at io.quarkus.deployment.dev.IsolatedDevModeMain.firstStart(IsolatedDevModeMain.java:95) at io.quarkus.deployment.dev.IsolatedDevModeMain.accept(IsolatedDevModeMain.java:485) at io.quarkus.deployment.dev.IsolatedDevModeMain.accept(IsolatedDevModeMain.java:68) at io.quarkus.bootstrap.app.CuratedApplication.runInCl(CuratedApplication.java:142) at io.quarkus.bootstrap.app.CuratedApplication.runInAugmentClassLoader(CuratedApplication.java:97) at io.quarkus.deployment.dev.DevModeMain.start(DevModeMain.java:132) at io.quarkus.deployment.dev.DevModeMain.main(DevModeMain.java:62)

Any idea how to fix this? I used Quarkus 2.8.2.Final and then saw that the 2.8.3.Final was out and moved to it but without any success.

D.

Codestart dev seed data should not be in prod code

in the codestart we have:

// in DEV mode we seed some data
    if(LaunchMode.current() == LaunchMode.DEVELOPMENT) {
        Note a = new Note();
        a.task = "First item";
        a.persist();

        Note b = new Note();
        b.task = "Second item";
        b.completed = new Date();
        b.persist();
    }
}

could we have an sql data seed file instead (that we configure to be enabled just in dev mode)?

I believe it's a bad practice to have dev/test code in the actual production code.

How to handle array/list of user roles in a single method on User?

Hi,

I have a method on my User class which is a RenardeUser, etc.

I have a method called hasUserRole(String... roleNames) that I'd like to pass in a list of roles to check from my Qute templates in a single method call instead of multiple calls.

This works IF I pass in a list of roles like {#if inject:user && inject:user.hasUserRole("webadmin", "admin", "support")} but I get an exception during RUNTIME if I try to pass in a single value, ie. {#if inject:user && inject:user.hasUserRole("admin")}

The project compiles and starts up just fine but dies when I access the page with the single permission check.

Any ideas?

2023-02-26 17:27:11,348 ERROR [org.jbo.res.rea.com.cor.AbstractResteasyReactiveContext] (executor-thread-1) Request failed: java.lang.ClassCastException: class java.lang.String cannot be cast to class [Ljava.lang.String; (java.lang.String and [Ljava.lang.String; are in module java.base of loader 'bootstrap')

Redirect URIs duplicating context root when changed in Quarkus with `quarkus.http.root-path`

Not sure how to explain this but, I changed my context path from / to /support so my urls look like http://localhost:8080/support to access my HTML/QUTE/RENARDE app.

quarkus.http.root-path=/support

When I generate the redirect URIS according to the docs, I'm getting duplicate context roots:

The code below generates a URI of: http://localhost:8080/support/support/

 // All good, set the JWT cookie
        NewCookie cookie = security.makeUserCookie(user);
        return Response.seeOther(Router.getURI(Application::index)).cookie(cookie).build();

All my paths on my endpoints are defined as @path("") at the top of the class and @path("/") for index page and @path("/login") for example. All of them start with '/'

Any ideas?

validation errors not copied to flash

Manually added validation errors added through the addError(field, message) method are not copied to the flash error map immediately for use in the response template.

Attached is an example project. To recreate:

  1. ./mvnw clean compile quarkus:dev
  2. navigate to http://localhost:8080
  3. enter an email address in the registration form, and click Submit
  4. on the registration page, do not fill out the name or nickname fields, then click Submit
  5. registration page should be displayed again, but with error messages about needing to fill out the name or nickname fields; the error messages are missing

code-with-quarkus.zip

Find an elegant way to show that a redirect stop the method flow

Currently, it works like this:

    @POST
    public void add(@RestForm @NotBlank String title, @RestForm @NotBlank String note) {
        // If validation fails, redirect to the todos page (with errors propagated)
        if(validationFailed()) {
            // redirect to the todos page by just calling the method: it does not return!
            todos();
        }
        // save the new Todo
        Note todo = new Note();
        todo.task = task;
        todo.persist();
        // redirect to the todos page
        todos();
    }

Some could argue that it is not obvious in a java world that todos(); is stopping the flow of the method. It would be nice to offer an alternate more declarative way of doing it. Something like 👇 would make me happy :) :

    @POST
    public void add(@RestForm @NotBlank String title, @RestForm @NotBlank String note) {
        if(validationFailed()) {
            redirect(Todos::todos);
			return;
        }

        Note todo = new Note();
        todo.task = task;
        todo.persist();

        redirect(Todos::todos);
    }

Can Renarde OIDC automatically redirect an @Authenticated method to Login upon an HTTP 401?

I searched throughout the entire documentation, but could not find an easy option to do so. As a result, hitting an @Authenticated method simply returns a default browser error page (HTTP 401). In my opinion, the graceful behavior in this case should be redirecting to the login page (specified via a property).

I temporarily solved this by extending and overriding parts of the JWTAuthMechanism class:

@Alternative
@Priority(1)
@ApplicationScoped
public class JWTAuth extends JWTAuthMechanism {

   @Override
   public Uni<ChallengeData> getChallenge(RoutingContext context) {
      return Uni.createFrom().item(new ChallengeData(302, "Location", "/login"));
   }
}

I suppose this is something that could make it to a future release of Renarde.

Really support async controller return types

ATM we generate @Transactional for @POST/@PUT/@DELETE endpoints, but that's a dependency on narayana-jta, which is only supported by Hibernate ORM.
We should generate @ReactiveTransactional if the return type is async, such as Uni, but that also means updating ReactiveTransactionalInterceptor to support a new @Rollback annotation, because that one is in narayana-jta and there's no common module to both, and we need to annotate our RedirectException with this.

This will require some thinking.

Incorrect URL Encoding for Optional Parameters

Hi there,

I hope you're doing well. I encountered an issue while using the quarkus-renarde project. When binding Optional parameters and performing a redirect, the URL encoding for the Optional values seems to be incorrect, resulting in unexpected behavior.

Steps to Reproduce:

  1. Define a method with Optional parameters like this:
public TemplateInstance shops(@RestQuery(value = "id") Optional<Long> optionalId, @RestQuery(value = "page") Optional<Integer> optionalPageNumber) {
  // Method implementation...
}
  1. Call the shops method from another method for a redirect:
return this.shops(Optional.of(shop.id), Optional.empty());

The URL is generated incorrectly, and the Optional values are not properly encoded, leading to URLs like:

http://localhost:8080/admin/shops?id=Optional%5B501%5D&page=Optional.empty

where %5B and %5D represent [ and ], respectively, and 501 is the id of the shop.

Thank you.

Handle validation exceptions using `Referer` header

ATM we tell users to handle validation themselves because we want to allow more complex validation use-cases, and we want them to be able to control where to redirect to, but in some cases it may be useful to catch ConstraintViolationException such as thrown at the end of the transaction, and redirect to the Referer header URI, after pushing all errors in the flash scope.

That should work automatically, no?

java.util.Date ParamConverterProvider overriding custom one

I was trying to use my custom java.util.Date ParamConverterProvider in my application but it is never being called, well, I should say it's not being passed in any instances of java.util.Date from my form POJO that I pass into my JAX-RS methods with the @BeanParam annotation.

I have the need to use a POJO for my HTML FORM which uses the url-encoded method so I don't have to list out every single parameter in my method signature.

I made a POJO like this:

public class UserFormData {

 @FormParam("expireDate")
 Date expireDate;

 @FormParam("firstName")
 String firstName;

 .... More Fields

}

Then in my POST method in my controller I have something like:

@POST
public void handle(@BeanParam UserFormData userData) {
  log.info("Got my data: {}", userData);
}

I posted this to the Quarkus StackOverflow group and they responded telling me to use the @BeanParam annotation. This works fine as long as I don't have any Date parameters in my bean (which is not what I want)

https://stackoverflow.com/questions/73912142/how-to-handle-form-url-encoded-to-pojo-with-quarkus/73931334#73931334

Doing an experiment and eliminating dependencies out of my project I found that removing Renarde itself fixes the issue BUT I need to use it :)

Looking at the source for Renarde it looks like you're registering a default provider for java.util.Date already?
https://github.com/quarkiverse/quarkus-renarde/blob/main/runtime/src/main/java/io/quarkiverse/renarde/util/MyParamConverters.java

Can I override this version to use my version so I can define my own date formats? I don't see a priority attribute on the Provider annotation.

When I leave the Date fields in my class I get a 400 Bad Request response and no errors on the server. Commenting out the date fields lets the form submission process but obviously is not what I want since I can't use my Date fields.

Thanks!

Quarkus 3.1.1-Final compile error

When updating to Quarkus 3.1.1-Final using Rendered 3.0.2 I get the compiler error below.

Quarkus 3.0.4-Final works fine... once you get into 3.1.x-Final it breaks. I tried both 3.1.0-Final and 3.1.1-Final

[ERROR] 	[error]: Build step io.quarkus.arc.deployment.ArcProcessor#registerBeans threw an exception: jakarta.enterprise.inject.spi.DefinitionException: Declaring class of a managed bean is generic, its scope must be @Dependent: com.rajant.support.site.rest.BaseControllerWithUser
[ERROR] 	at io.quarkus.arc.processor.Beans$ClassBeanFactory.create(Beans.java:1282)
[ERROR] 	at io.quarkus.arc.processor.Beans.createClassBean(Beans.java:52)
[ERROR] 	at io.quarkus.arc.processor.BeanDeployment.findBeans(BeanDeployment.java:1121)
[ERROR] 	at io.quarkus.arc.processor.BeanDeployment.registerBeans(BeanDeployment.java:266)
[ERROR] 	at io.quarkus.arc.processor.BeanProcessor.registerBeans(BeanProcessor.java:142)
[ERROR] 	at io.quarkus.arc.deployment.ArcProcessor.registerBeans(ArcProcessor.java:443)
[ERROR] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
[ERROR] 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR] 	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
[ERROR] 	at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:909)
[ERROR] 	at io.quarkus.builder.BuildContext.run(BuildContext.java:282)
[ERROR] 	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
[ERROR] 	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
[ERROR] 	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
[ERROR] 	at java.base/java.lang.Thread.run(Thread.java:833)
[ERROR] 	at org.jboss.threads.JBossThread.run(JBossThread.java:501)

This is my BaseControllerWithUser class which I've been using just fine in previous releases. I'm including it here since the error called out this class.

/**
 * Extension of Renarde Controller to provide convience methods
 *
 * @param <U> User type
 */
public class BaseControllerWithUser<U extends RenardeUser> extends ControllerWithUser<U> {


    protected Response ok(Object entity) {
        return Response.ok(entity).build();
    }

    protected Response internalError(Throwable cause) {
        throw new WebApplicationException(cause, Response.Status.INTERNAL_SERVER_ERROR);
    }
    protected Response internalError(String message) {
        throw new WebApplicationException(
                RestResponse.ResponseBuilder.create(RestResponse.Status.INTERNAL_SERVER_ERROR, message).build().toResponse());
    }
    protected Response notFound(String message) {
        throw new WebApplicationException(
                RestResponse.ResponseBuilder.create(RestResponse.Status.NOT_FOUND, message).build().toResponse());
    }
    protected Response unauthorized(String message) {
        throw new WebApplicationException(
                RestResponse.ResponseBuilder.create(RestResponse.Status.UNAUTHORIZED, message).build().toResponse());
    }

//    protected Response badRequest(String message) {
//        throw new WebApplicationException(
//                RestResponse.ResponseBuilder.create(RestResponse.Status.BAD_REQUEST, message).build().toResponse());
//    }

    protected Response badRequest(Object entity) {
        throw new WebApplicationException(
                RestResponse.ResponseBuilder.create(RestResponse.Status.BAD_REQUEST, entity).build().toResponse());
    }

}

Accessing user info in Class extending ControllerWithUser

Hi,
this is not an issue but a question that I've been struggling the last days and don't seem to find a solution.
So far everything is good with Renarde, I implemented a login mechanism using the database as it was the previous mean we used (I am porting the application we had).
I based my login mechanism on the todo example and my code looks like this

@POST
public Response manualLogin(@RestForm String username, @RestForm String password) {
	var action = (this.getClass().getSimpleName() + "." + getInstance().walk(frames -> frames.findFirst().map(StackWalker.StackFrame::getMethodName)).get()).replace("_Subclass", "");
	var timer = registry.timer(applicationName + "." + action);
	return timer.record(() -> {
		var user = User.findByUsername(username);
		if (user == null || !matches(password, user.credentials.password)) {
			validation.addError("username", "Invalid username/password");
			prepareForErrorRedirect();
			login();
		}
		var cookie = security.makeUserCookie(user);
		URI uri = null;

		if (ADMINISTRATOR.equalsIgnoreCase(user.credentials.role)) {
			uri = getURI(Administrators::display_dashboard);
		} else if (INSURANCE.equalsIgnoreCase(user.credentials.role) || INSURANCE_EMPLOYEE.equalsIgnoreCase(user.credentials.role)) {
			uri = getURI(Insurances::display_dashboard);
		} else if (MECHANIC.equalsIgnoreCase(user.credentials.role) || MECHANIC_EMPLOYEE.equalsIgnoreCase(user.credentials.role)) {
			uri = getURI(Mechanics:: display_dashboard);
		} else if (EXPERT.equalsIgnoreCase(user.credentials.role) || EXPERT_EMPLOYEE.equalsIgnoreCase(user.credentials.role)) {
			uri = getURI(Experts:: display_dashboard);
		}
		return Response.seeOther(uri).cookie(cookie).build();
	});
}

Everything works fine, in the browser panel I can see the cookie value and all that.

I am now trying to get the user data in an Class extending the ControllerWithUser one.
I tried this

@POST
@Consumes(MULTIPART_FORM_DATA)
public TemplateInstance search(final SearchCompanies request) {
	var action = (this.getClass().getSimpleName() + "." + getInstance().walk(frames -> frames.findFirst().map(StackWalker.StackFrame::getMethodName)).get()).replace("_Subclass", "");
	logEntry(LOGGER, applicationName, profile, action, request);
	var timer = registry.timer(applicationName + "." + action);
	return timer.record(() -> {
                String requestUser = security.getUser().getUserId(); // <-- from @Inject RenardeSecurity security;
		request.requestUser = requestUser;
		GatewayResponse response = client.search(request);
		TemplateInstance templateInstance = Templates.search()
			                                    .data(UI_USER, userUtility.getUIUser(requestUser))
			                                    .data("insurances", response.entity)
			                                   .data("request", request);
		count(registry, applicationName, profile, action, response);
		logExit(LOGGER, applicationName, profile, action, request, response.entity != null ? response.entity : response.errorMessage);
		return templateInstance;
	});
}

and this

@POST
@Consumes(MULTIPART_FORM_DATA)
public TemplateInstance search(final SearchCompanies request) {
	var action = (this.getClass().getSimpleName() + "." + getInstance().walk(frames -> frames.findFirst().map(StackWalker.StackFrame::getMethodName)).get()).replace("_Subclass", "");
	logEntry(LOGGER, applicationName, profile, action, request);
	var timer = registry.timer(applicationName + "." + action);
	return timer.record(() -> {
                String requestUser = getUser().getUserId(); // <-- difference between the two implementations
		request.requestUser = security.getUser().getUserId();
		GatewayResponse response = client.search(request);
		TemplateInstance templateInstance = Templates.search()
				                                    .data(UI_USER, userUtility.getUIUser(requestUser))
				                                    .data("insurances", response.entity)
				                                    .data("request", request);
		count(registry, applicationName, profile, action, response);
		logExit(LOGGER, applicationName, profile, action, request, response.entity != null ? response.entity : response.errorMessage);
		return templateInstance;
	});
}

But the value for requestUser is always returning null or an NPE is thrown. I need the data of the user to be set in a Request that I have to forward to some other microservices. The Class extending ControllerWithUser was first annotated with @authenticated and then not but it doesn't seem to make any difference.

Any idea on what I am missing?

Regards,
D.

Prepare for Jandex 3

As seen on quarkus-dev, we may have to check our processors for usage of two methods:

There's a few breaking changes in Jandex 3.0 and the 2.4.3 release is supposed to make migration easier (or at least require less coordination).

Specifically, Jandex 2.4.3 deprecates these 2 methods because they have a different return type in 3.0:

  • ClassInfo.annotations()
  • MethodInfo.parameters()

Replacements are, respectively:

  • ClassInfo.annotationsMap()
  • MethodInfo.parameterTypes()

These 2 replacement methods are present both in Jandex 2.4.3 and 3.0.0[-RC1].

Additionally, certain usages of MethodInfo.parameters() can be simplified using MethodInfo.parametersCount() and parameterType(int). These 2 methods are also present both in 2.4.3 and 3.0.0[-RC1].

devmode fails with missing private keys?

I just have a controller class and index.html (the hello world from docs) and it works when I package/run it, but when I run in devmode I get this error:

java.io.FileNotFoundException: target/classes/dev.privateKey.pem (No such file or directory)
	at java.base/java.io.FileOutputStream.open0(Native Method)
	at java.base/java.io.FileOutputStream.open(FileOutputStream.java:293)
	at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:235)
	at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:184)
	at java.base/java.io.FileWriter.<init>(FileWriter.java:96)
	at io.quarkiverse.renarde.deployment.RenardeProcessor.setupJWT(RenardeProcessor.java:228)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:925)
	at io.quarkus.builder.BuildContext.run(BuildContext.java:277)
	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
	at java.base/java.lang.Thread.run(Thread.java:833)
	at org.jboss.threads.JBossThread.run(JBossThread.java:501)
Resulted in: java.lang.IllegalStateException: java.io.FileNotFoundException: target/classes/dev.privateKey.pem (No such file or directory)
	at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:934)
	... 6 more
Resulted in: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
	[error]: Build step io.quarkiverse.renarde.deployment.RenardeProcessor#setupJWT threw an exception: java.lang.IllegalStateException: java.io.FileNotFoundException: target/classes/dev.privateKey.pem (No such file or directory)
	at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:934)
	at io.quarkus.builder.BuildContext.run(BuildContext.java:277)
	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
	at java.base/java.lang.Thread.run(Thread.java:833)
	at org.jboss.threads.JBossThread.run(JBossThread.java:501)
Resulted in: java.io.FileNotFoundException: target/classes/dev.privateKey.pem (No such file or directory)
	at java.base/java.io.FileOutputStream.open0(Native Method)
	at java.base/java.io.FileOutputStream.open(FileOutputStream.java:293)
	at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:235)
	at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:184)
	at java.base/java.io.FileWriter.<init>(FileWriter.java:96)
	at io.quarkiverse.renarde.deployment.RenardeProcessor.setupJWT(RenardeProcessor.java:228)

I haven't configured any JWT (yet) and also don't need it just yet ...shouldn't renarde be resilient and let me get started without JWT setup?

Are nested tag replacement supported for custom tags?

Hi,

Sorry if this is a simple question but using your Todo example as a reference for my custom tags on my forms, I would like to pass in a value to the custom tag that is parsed from the parent tag.

For example:

My FormElement Tag: (tags/FormElement.html)

<label class="form-label control-label" for="{name}">{label}</label>
<div class="mb-3 {class??}">
    {nested-content}
{#ifError name}
    <span class="invalid-feedback">​{#error name/}</span>​
{/ifError}
</div>

My form using the custom tag: (login.html):

<div class="col-sm-7">
        {#form uri:Application.doLogin()}
        <fieldset>
            {#formElement name="email" label="{i18n:['auth.login.email.placeholder']}" class="form-group"}
                {#input id="email" name="email" type="email"/}
            {/formElement}
            {#formElement name="password" label="Password"}
                {#input id="password" name="password" type="password"/}
            {/formElement}
            <br/>
            <br/>
            <input type="submit" value="{i18n:['auth.login.now']}" class="btn btn-primary">
        </fieldset>
       {/form}
       
        <br/>
        <a href="@routes.Signup.forgotPassword()">{i18n:['auth.login.forgot.password']}</a>
    </div>

I'd like to pass in the LABEL value from my LOGIN form which has been read from my Template extension ('i18n') which reads the value from a message bundle. This way I don't have to hard code the value and I can still have a generic custom tag and be able to pass in localized messages.

When the page is currently rendered, it simply displays {i18n:['auth.login.email.placeholder']} and not the value from the message bundle.

Thanks again..
Is this possible?

Add or test internationalisation

We should try to internationalise the sample TODO app and see if we have all the required bits from Qute/Quarkus in order to be able to set the language and get translations in the views.

https://www.playframework.com/documentation/1.4.x/guide12 can be used for inspiration, and for http://rivieradev.fr (code at https://github.com/FroMage/RivieraDEV/blob/master/app/controllers/Application.java#L55) we had these controller actions to change the language from the top menu:

    public static void fr(String url) {
        Lang.change("fr");
        redirect(url);
    }

    public static void en(String url) {
        Lang.change("en");
        redirect(url);
    }

So a way to change the current language from a Controller would be great. I'm pretty sure this sets a language cookie that overrides the browser language headers when set.

Rename CRSF to CSRF

The acronym for Cross-Site Request Forgery is CSRF not CRSF

The class CRSF.java should be renamed as well as all mentions of crsf in the documentation.

Custom Tags: Issue with Boolean and NOT (!) operation

Hi,

I have a custom tag which build a label and a textfield with a variety of parameters.
One of those being the ability to disable the field with the 'disabled' parameter.

I'm getting an error when trying to pass in a boolean and take the opposite of it using the (!) operation.
You can see in the error message below that the canEdit parameter is included in the list of params available to the template.

In my Templates instance I have the method defined as:
public static native TemplateInstance orgEdit(OrgFormData orgForm, Long orgId, boolean canEdit);

If I take out the (!) and just make it disabled=canEdit the build succeeds but then my form element is always disabled.

So, I'm not sure why it's not working.. any ideas? is the boolean operation (!) supported inside custom tags?

Thanks again!

Template Use:

{#text name="name" value=orgForm.name label=i18n:['label.orgName'] placeholder="Org Name"
            label_class="control-label form-label f-required"
            input_class="form-control input-sm"
            disabled=!canEdit
          /}

text.html (Custom Tag)

<div class="form-group {#ifError name}has-error{/ifError}">
  <label class="{label_class??}" for="{name}">{label??}</label>
  <div class="mb-3">
    <input name="{name}" id="{name} type="{type ?: 'text'}"
           {#if placeholder??}placeholder="{placeholder}"{/if}
           class="{input_class??} {#ifError name}is-invalid{/ifError}"
           value="{inject:flash.get(name) ?: value??}"
           {#if readOnly??}readonly{/if}
           {#if disabled??}disabled{/if}
    />
    {#ifError name}
      <span class="has-error">​{#error name/}</span>​
    {/ifError}
  </div>
</div>

Error:

 Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[ERROR]         [error]: Build step io.quarkus.qute.deployment.QuteProcessor#processTemplateErrors threw an exception: io.quarkus.qute.TemplateException: Found incorrect expressions (1):
[ERROR]         [1] Orgs/orgEdit.html:162:11 - {!canEdit}: Only type-safe expressions are allowed in the checked template defined via: com.rajant.support.site.rest.Orgs$Templates.orgEdit(); an expression must be based on a checked template parameter [orgForm, canEdit, orgId], or bound via a param declaration, or the requirement must be relaxed via @CheckedTemplate(requireTypeSafeExpressions = false)
[ERROR] 
[ERROR]         at io.quarkus.qute.deployment.QuteProcessor.processTemplateErrors(QuteProcessor.java:233)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
[ERROR]         at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]         at java.base/java.lang.reflect.Method.invoke(Method.java:568)
[ERROR]         at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:909)
[ERROR]         at io.quarkus.builder.BuildContext.run(BuildContext.java:281)
[ERROR]         at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
[ERROR]         at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
[ERROR]         at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
[ERROR]         at java.base/java.lang.Thread.run(Thread.java:833)
[ERROR]         at org.jboss.threads.JBossThread.run(JBossThread.java:501)
[ERROR]         Suppressed: io.quarkus.qute.TemplateException: Orgs/orgEdit.html:162:11 - {!canEdit}: Only type-safe expressions are allowed in the checked template defined via: com.rajant.support.site.rest.Orgs$Templates.orgEdit(); an expression must be based on a checked template parameter [orgForm, canEdit, orgId], or bound via a param declaration, or the requirement must be relaxed via @CheckedTemplate(requireTypeSafeExpressions = false)
[ERROR]                 at io.quarkus.qute.TemplateException$Builder.build(TemplateException.java:168)
[ERROR]                 at io.quarkus.qute.deployment.QuteProcessor.processTemplateErrors(QuteProcessor.java:198)
[ERROR]                 ... 11 more

How to configure opensource OIDC providers?

Hello,
I am really unsatisified with the choice of preconfigured providers. Maybe it's easy for those who are using these providers. There is no documentation on how to configure OpenSource OIDC providers. I think that it will be better without this list of known providers and give more possibility for opensource providers.

quarkus.oidc.provider=xxxx
quarkus.oidc.client-id=
quarkus.oidc.credentials.secret=

Any explication why offering only the fixed providers and how can it be used for other unknown provider?

How to add dynamic content to the page ?

Hello,

I have a page with a list, when user select one from this list and submit, the form get submitted. I have to inject some response from REST API according to the selection. I didn't find a way to add this response to the same page.

Any example ? I searched a lot. I don't know how to accomplish it. I don't want a new page

Thanks

JWT vs JWE with Renarde

I have an existing Quarkus project that is set up to use a JWT for securing REST endpoints, configured with mp.jwt.verify.publickey and mp.jwt.verify.publickey.algorithm (it integrates with an existing system that is generating the tokens). I would like to add Renarde to the project for generating a UI for it, however, when the quarkus-renarde dependency is added, it causes the existing endpoints to fail authentication:

2022-11-06 14:22:15,949 DEBUG [org.jbo.res.rea.com.cor.AbstractResteasyReactiveContext] (vert.x-eventloop-thread-0) Restarting handler chain for exception exception: io.quarkus.security.AuthenticationFailedException
...
Caused by: io.smallrye.jwt.auth.principal.ParseException: SRJWT07013: Encrypted token sequence is invalid
...
Caused by: org.jose4j.lang.JoseException: A JWE Compact Serialization must have exactly 5 parts separated by period ('.') characters

Is there any way to configure Renarde to use the existing public key for the un-encrypted JWTs, instead of generating key files and expecting encrypted JWTs?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.