Bolt CMS: Route no match, try next route - url-routing

I'm having two contenttypes, but in both I don't want the contenttype slug in the URL. So both contenttypes should match /{slug}, but take the content from a differtent contenttype.
So I though, I create two routes, if the first fails, it will try the second:
# match on any landingpage created as a contenttype landingpage
landingpagebinding:
path: /{slug}
defaults:
_controller: controller.frontend:record
contenttypeslug: landingpage
contenttype: landingpage
# match on any actionpage created as a contenttype actionpage
actionpagebinding:
path: /{slug}
defaults:
_controller: controller.frontend:record
contenttypeslug: actionpage
contenttype: actionpage
So I have:
a landingpage "/this-is-my-landingspage"
a actionpage "/this-is-my-actionpage"
The landingpage is working, the actionpage gives a 404 error
landingpage/this-is-my-actionpage not found.
Why do I get a 404 on the landingpagebinding? I expected it would continue to the next route, actionpagebinding and tries to match on that. If that is also not found, then I want a 404 error!
Note: I know that when both contenttypes have the same slug, the first one will match. But that is not an issue.

I had the same problem with this. you will have to write a function that picks up the next slug if the one before has not been found.
what bolt does is just check the first option and then stops. you have to write some function that lets it continue reading until it found the wanted file.

Related

Next-Auth EmailProvider and FaunaAdapter "Unable to Sign In"

I've followed the next-auth docs to hook up its EmailProvider and FaunaAdapter in a brand new Next.js project, but I am unable to sign in.
My dependencies:
"#next-auth/fauna-adapter": "^1.0.2"
"faunadb": "^4.5.2"
"next": "^12.1.0"
"next-auth": "^4.2.1"
"nodemailer": "^6.7.2"
"react": "^17.0.2"
"react-dom": "^17.0.2"
I've wrapped my pages/_app.jsx in SessionProvider, so I can use useSession() in pages/index.jsx.
The real work happens in the only other file in the repo, pages/api/auth/[...nextauth].js:
import NextAuth from 'next-auth';
import EmailProvider from 'next-auth/providers/email'
import { Client as FaunaClient } from 'faunadb';
import { FaunaAdapter } from '#next-auth/fauna-adapter';
const client = new FaunaClient({
secret: process.env.FAUNA_CLIENT_SECRET,
scheme: 'https',
domain: 'db.fauna.com',
port: 443,
});
export default NextAuth({
providers: [
EmailProvider({
server: {
host: process.env.EMAIL_SERVER_HOST,
port: process.env.EMAIL_SERVER_PORT,
auth: {
user: process.env.EMAIL_SERVER_USER,
pass: process.env.EMAIL_SERVER_PASSWORD
}
},
from: process.env.EMAIL_FROM,
maxAge: 10 * 60 * 60,
}),
],
adapter: FaunaAdapter(client),
secret: process.env.AUTH_SECRET,
});
The Problem
When I attempt to sign in, I successfully receive the email in my inbox and the Fauna dashboard shows a new entry in the verification_tokens collection. The expires property in the new token is ten hours in the future and the identifier is the correct email address.
However, when I click the link in the email, I'm redirected to http://localhost:3000/api/auth/error?error=Verification and I see the message "Unable to sign in. The sign in link is no longer valid. It may have been used already or it may have expired."
In the Fauna dashboard, both users and sessions collections remain empty.
I'm using Postmark to handle the SMTP email – I'm curious whether it may pre-click the link when it sends the email?
Gmail is the receiving email client, but I doubt it's pre-clicking the link?
My local node version is 16.14.0, and to eliminate complications I've reverted from yarn to npm. I have a demo repository here: https://github.com/tatwater/nextauth-fauna
Thanks for the help!
So, I had a better look and I found out that the adapter is calling the fauna Match(Index('verification_token_by_identifier_and_token'), [identifier, token]) in this specific order while the Index is expecting to receive the terms the other way around [token, identifier].
Looks like when the index is created through the Fauna Shell it always sets the terms in the "wrong" way. A temporary solution is to delete the index and recreate it manually setting the identifier as the first term and token as the second.
A more permanent solution would probably be update the adapter so that it uses the index in the same way it is created from the Shell.

Change Camel's basic /camel url

Issue:
I would need to change the basic /camel url which camel uses by default, but when i try to change it in application.yml nothing happens to it.
Would like to keep other systems intact without changing their urls, from what they already have (would require quiet a bit of work in back-end systems)
Current URL: http://localhost:8080/camel/hello
Desired URL: http://localhost:8080/service/hello
Checked links which are NOT working for me:
Link1
Link2
Link3
EG: application.yml
camel:
springboot:
name: CamelRestContext
component:
servlet:
mapping:
enabled: true
context-path: /service
So apparently this way works:
camel:
springboot:
name: RestDSLContext
servlet:
mapping:
context-path: /service/*
rest:
context-path: /service

Zuul url parameters to Solr Query parameters

I am trying to rewrite request with zuul and forward them to an old solr server.
My application.yml looks like this:
zuul:
prefix: /api/v1
routes:
peoples:
path: path: /peoples/**
url: http://solr/api/select?
So far the /people route is working fine, i get the incoming request, pass the correct parameters to the request via a Zuulfilter and forward to solr. The redirected request looks:
http://sorl/api/select?q=*&wt=json&indent=true&collection=MyCollection&fl=Filter1,Filter2,Filter3,Filter4&rows=10
I don't understand how i can define a new route like : peoples/{id}.
I need to pass the {id} route to another ZuulFilter and append it to com.netflix.zuul.context.RequestContext.getCurrentContext().setRequestQueryParams()
Am i missing something in Zuul or is it just no possible to get a param from the requestcontext, and transform it to a query param ?

Symfony3 and Sonata-adminBundle:dev-master Admin route is not automatically generated

I'm using symfony3 and sonata-project/admin-bundle:dev-master. my problem is that when I generate an Admin class by the command line: sonata:admin:generate, now when I try to access the admin dashboard in order to see my admin class...I get the following error: An exception has been thrown during the rendering of a template ("Unable to generate a URL for the named route "admin_pa_pacomplaint_create" as such route does not exist.") in SonataAdminBundle:Block:block_admin_list.html.twig at line 39.
Edit: Event bin/console debug:router does not show the route of the newly created admin class
Sorry for my question where so easy: I just needed to update the app/config/routing.yml file with the following:
_sonata_admin:
resource: .
type: sonata_admin
prefix: /admin

Symfony2: allow all unmatched routes to be accessed anonymously

I have Symfony2 application separated into 2 bundles: BackendBundle for API and FrontendBundle for AngularJS "client". Everything works under firewall.
BackendBundle has entities, handles API routes; FrontendBundle has Angular views, routing etc. and has only one controller with wildcard:
class AngularController extends Controller {
/**
* #Route("/{route}", name="angular_index_all_unmatched_routes", requirements={"route" = ".*"})
* #Template("FrontendBundle::index.html.twig")
*/
public function angularIndexAction($route) {
return ['route' => $route];
}
}
FrontendBundle routing is defined as last resource in app/config/routing.yml, to be invoked only if any other route was not matched. Thanks to that, it can handle Angular HTML5-mode routes if they're accessed directly (for example copy-paste) - and it works ok.
What I want to do, is define firewall and/or access control in way that all those unmatched routes (handled by AngularController::angularIndexAction()) could be accessible by anonymous user.
Why? I want to open some API routes (via frontend proxy) to be accessible by non-users (for example confirmation URLs sent by email, with some message to user).
I don't want to hardcode access control list for every anonymous "Angular" route, I would like to do it only for API routes. At the end, those unmatched routes should open Angular's index which should know if user is logged in (for displaying full or simplified layout) and should handle Angular routes and display some kind of "Access denied" message if request failed (there is Symfony listener and Angular's $provide interceptor for that).
Any suggestions?
Edit: #Security annotation on AngularController::angularIndexAction() does not work, it still redirects to firewall entry point.
Edit2: Here is fragment of security.yml
firewalls:
unsecured:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
anonymous: true
secured:
pattern: '^.*$'
form_login:
login_path: /our-provider/login
check_path: /our-provider/callback/
anonymous: true
entry_point: our_provider.entry_point
access_control:
- { path: '^/our-provider/(login(/[a-zA-Z]+)?|logout|redirect|callback)', roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: '^/', roles: ROLE_USER }
I know that { path: '^/', roles: ROLE_USER } will redirect all routes to login page if user is not logged in. I assumed it's obvious and did not mentioned it. What I want is force ROLE_USER for matched routes and let IS_AUTHENTICATED_ANONYMOUSLY for those unmatched, without explicitely defining each frontend "proxy-route". In my case there is not 404 Symfony page, because everything goes to angular_index_all_unmatched_routes route and there Angular routing definition decides if there is something to handle or not.
I haven't tried this, and I cannot begin to guess your existing security/route setup in security.yml but I guess you could whitelist the method with IS_AUTHENTICATED_ANONYMOUSLY. From the Symfony docs:
All users (even anonymous ones) have this - this is useful when whitelisting URLs to guarantee access - some details are in How Does the Security access_control Work?.
So, for example, if you were using the #Security annotation you could do something like (not tested):
class AngularController extends Controller {
/**
* #Route("/{route}", name="route", requirements={"route" = ".*"})
* #Template("FrontendBundle::index.html.twig")
* #Security("has_role('IS_AUTHENTICATED_ANONYMOUSLY')")
*/
public function angularIndexAction($route) {
return ['route' => $route];
}
}
More on the #Security annotation here.
Hope this helps :)
Edit
All that said, when you define/restrict your routes under access_control in security.yml, the matching process stops on the first match. I assume that you have some role-restricted paths, which you should define explicitly - and put them first, so if they match the process stops.
Otherwise, you should be able to add a catch-all route, enforced by role IS_AUTHENTICATED_ANONYMOUSLY. Since the path definition of a route is a regex, something like ^/ should catch anything that is not explicitly defined. Just make sure and place it after your restricted route definitions.
You would not need for the #Security annotation in this case.
Edit 2
I tried mocking this out using a clean instance and HTTP BasicAuth but what I was trying to achieve was the following, which I understand as similar to your use case:
Create a backend controller with routes / and /api/ and trigger a HTTP BasicAuth authentication popup
Create a frontend controller with route /{route} that would match everything else and authenticate anonymously.
My firewall and access_control configuration looks like this:
security:
encoders:
# encoder config here
providers:
# provider config here
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured:
anonymous: ~
http_basic: ~
access_control:
- { path: ^/$, roles: ROLE_USER }
- { path: ^/api/, roles: ROLE_USER }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
Access control paths are regexes, so ^/$ and ^/ are not the same. The former will only match exactly to route /. The latter will match any route that begins with /; e.g: /home, /products, /contact etc.
Indeed, the latter will match and anonymously authenticate /api, but it will not match /api/, or /api/1 etc. as these are explicitly defined and restricted to ROLE_USER.
So the general idea is to explicitly and (if possible) exactly match the routes you want to restrict, and declare those first. The last declaration ^/ should openly catch any other route that falls through.

Resources