I try to use the Laravel/Sanctum in a custom Laravel package.
As in a default Laravel application, I added it to the composer file, added the migration and set it up in the routes file.
The next error message appears:
"Auth guard [sanctum] is not defined."
I hope it is even possible to use sanctum in another package?
Composer.json file:
"require": {
"php": "7.4.*",
"laravel/sanctum": "^2.2"
},
routes file:
Route::group(['middleware' => 'auth:sanctum'], function () {
Route::post('/approve', ['uses' => 'MemberRequestController#response', 'response' => 'approve'])->name('approve_member_request');
}
ServiceProvider
/**
*
*/
private function registerRoutes()
{
Route::group($this->routeConfig(), function () {
$this->loadRoutesFrom(__DIR__ . '/../../routes/api.php');
});
}
/**
* #return string[]
*/
private function routeConfig(): array
{
return [
'prefix' => ums::path(),
'namespace' => 'martijn\UMS\Http\Controllers',
'middleware' => ['api', 'auth:sanctum']
];
}
You should publish the Laravel\Sanctum\SanctumServiceProvider.
It will register the missing guard.
Started work after me removed content of folder bootstrap/cache/ manually
No cache/view/routes clearings helped
In my host DirectAdmin, I manually reuploaded vendor folder and after facing this error
Auth guard [sanctum] is not defined
I reuploaded bootstrap folder.
Everything works fine right now.
In my case problem was in RouteServiceProvider, default sign in was redirecting to RouteServiceProvider::HOME and public const HOME = '/dashboard';
Which I didn't had anymore, so replace it just with existing view.
Related
Our Angular 14 app is configured to use Angular Universal for SSR, and is integrated with our .NET 6 back end. The Universal guide incorrectly states (per this bug) that relative URLs will "automatically" be converted to absolute if you're using Express, but we still get relative URL errors from SSR even after updating our app.server.module.ts to include the necessary setting .useAbsoluteUrl = true (and providing the base URL), which fixes the issue for some per the bug thread:
export class AppServerModule {
constructor(
#Inject(INITIAL_CONFIG) private config: PlatformConfig,
private baseUrlService: BaseUrlService
) {
this.config.baseUrl = this.baseUrlService.getBaseUrl();
this.config.useAbsoluteUrl = true;
}
}
We've also tried implementing a custom HTTP Interceptor to handle the conversion, which doesn't seem to work either when declared as a provider in app.server.module.ts. This must be a misconfiguration issue, right? Our main.server.ts file imports the aspnet-prerendering package and has a default createServerRenderer() method, which calls renderModule(AppServerModule, options), but is something else missing with this approach? The main.server.ts is:
....
export default createServerRenderer(params => {
const { AppServerModule } = (module as any).exports;
const options = {
document: params.data.originalHtml,
url: params.url,
extraProviders: [
{ provide: APP_BASE_HREF, useValue: params.baseUrl },
{ provide: 'BASE_URL', useValue: params.origin }
]
};
// Bypass ssr api call cert warnings in development
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
const renderPromise = renderModule(AppServerModule, options);
return renderPromise.then(html => ({ html }));
});
export { renderModule } from '#angular/platform-server';
export { AppServerModule } from './app/app.server.module';
Microsoft's now-deprecated NodeServices implementation(?) apparently requires the use of commonjs for Node (in tsconfig.server.json), if that's relevant.
I need to serve a blog created with create-react-blog in the /blog subdirectory on my main site. It is served alongside other separate projects created w/ create-react-app (the NodeJS code looks like this):
app.use("/blog", express.static(path.join(__dirname, "projects/blog")))
app.get("/blog", (req, res) => {
res.sendFile(path.join(__dirname, "projects/blog/index.html"));
});
app.get("/blog*", (req, res) => {
res.sendFile(path.join(__dirname, "projects/blog/index.html"));
});
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function (req,res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
Where the 'build' folder contains the react production build for the main site and 'projects/blog' contains the build files for the blog created with create-react-blog
Navigating to http://localhost:3001/blog with this system does indeed render the blog project, but presumably because Navi was built to used from the head directory the blog returns its 404 page. I can then only view the blog if I use the return link on the 404 page to navigate to http://localhost:3001/ (note: just navigating to http://localhost:3001/ without going through the blog page properly renders the other react project)
I've tried changing the homepage in the package.json of the blog to both /blog and ., changing the basename of the Router in the blog project's index.js to /blog, changing the PUBLIC_URL environment variable to blog and http://localhost:3000/blog, and changing the navi.config.js file to add /blog in front of each item in the getPagePathname function (from
import path from 'path'
export const renderPageToString = require.resolve('./src/renderPageToString')
/**
* Get the file to write each URL to during the build
*/
export function getPagePathname({ url }) {
if (url.pathname === '/rss') {
return 'rss.xml'
}
if (url.pathname === '/') {
return 'index.html'
}
return path.join(url.pathname.slice(1), 'index.html')
}
to
import path from 'path'
export const renderPageToString = require.resolve('./src/renderPageToString')
/**
* Get the file to write each URL to during the build
*/
export function getPagePathname({ url }) {
if (url.pathname === '/blog/rss') {
return 'rss.xml'
}
if (url.pathname === '/blog/') {
return 'index.html'
}
return path.join('/blog/', url.pathname.slice(1), 'index.html')
}
), none of which worked. I've also tried random combinations of the above approaches, which were also unsuccessful.
Please let me know how this would be accomplished. Thanks
After many hours, I was able to move the blog in a fairly roundabout way.
Starting from the template found in the main Github repo mentioned in the first paragraph of the question, I had to do the following combination of things:
Change all '/' routes in routes/index.js to /blog/<route> (i.e. / became /blog, /page became /blog/page etc.
Change the blogRoot in the withContext statement to just state /blog
Change isViewingIndex to req.path === '/blog' || /^\/page\/\d+$/.test(req.path)
In the crawlRoutes function in tags.js, add root='/' to the beginning of the function
Change navi.config.js to
import path from 'path'
export const renderPageToString = require.resolve('./src/renderPageToString')
/**
* Get the file to write each URL to during the build
*/
export function getPagePathname({ url }) {
if (url.pathname === '/blog/rss') {
return 'rss.xml'
}
if (url.pathname === '/blog') {
return 'index.html'
}
return path.join('/blog', url.pathname.slice(1), 'index.html')
}
Change renderPageToString.js to
import renderReactPageToString from 'react-navi/create-react-app'
import renderRSSFeedToString from './renderRSSFeedToString'
/**
* navi-scripts will call this function for each of your site's pages
* to produce its statically rendered HTML.
*/
async function renderPageToString(props) {
if (props.url.pathname === '/blog/rss') {
return await renderRSSFeedToString(props)
}
return renderReactPageToString(props)
}
export default renderPageToString
Of course, you can make this cleaner by changing /blog to be an environment variable (which I highly recommend).
If there is any better solution I am also open to it.
I have the following apolloClient
/**
* Initializes an ApolloClient instance. For configuration values refer to the following page
* https://www.apollographql.com/docs/react/api/core/ApolloClient/#the-apolloclient-constructor
*
* #returns ApolloClient
*/
const createApolloClient = (authToken: string | null) => {
const httpLinkHeaders = {
...(authToken && { Authorization: `Bearer ${authToken}` })
};
console.log('CREATING APOLLO CLIENT WITH HEADERS >>>>', httpLinkHeaders);
console.log(
'Graph Env Variable URL >>>>>',
publicRuntimeConfig.GRAPHQL_URL
);
return new ApolloClient({
name: 'client',
ssrMode: typeof window === 'undefined',
link: createHttpLink({
uri: publicRuntimeConfig.GRAPHQL_URL,
credentials: 'same-origin',
headers: httpLinkHeaders
}),
cache: new InMemoryCache()
});
};
/**
* Initializes the apollo client with data restored from the cache for pages that fetch data
* using either getStaticProps or getServerSideProps methods
*
* #param accessToken
* #param initialState
*
* #returns ApolloClient
*/
export const initializeApollo = (
accessToken: string,
initialState = null,
forceNewInstane = false
): ApolloClient<NormalizedCacheObject> => {
// Regenerate client?
if (forceNewInstane) {
apolloClient = null;
}
const _apolloClient = apolloClient || createApolloClient(accessToken);
// for pages that have Next.js data fetching methods that use Apollo Client,
// the initial state gets hydrated here
if (initialState) {
// Get existing cache, loaded during client side data fetching
const existingCache = _apolloClient.extract();
// Restore the cache using the data passed from
// getStaticProps/getServerSideProps combined with the existing cached data
_apolloClient.cache.restore({ ...existingCache, ...initialState });
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient;
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient;
return _apolloClient;
};
/**
* Hook to initialize the apollo client only when state has changed.
*
* #param initialState
*
* #returns
*/
export const useApollo = (
initialState: any
): ApolloClient<NormalizedCacheObject> => {
return useMemo(() => {
if (process.browser) {
const accessToken = extractCookie(document.cookie, 'access_token');
return initializeApollo(accessToken, initialState);
}
// document is not present and we can't retrieve the token but ApolloProvider requires to pass a client
return initializeApollo(null, initialState);
}, [initialState]);
};
That is initialized in the _app.tsx file like so
const updateApolloWithNewToken = useCallback(
(accessToken: string) => {
// Initialize apollo client with new access token
setClient(
initializeApollo(accessToken, pageProps.initialApolloState, true)
);
// Show the dashboard
router.replace('/dashboard');
},
[router]
);
With the following Next Config
const { PHASE_DEVELOPMENT_SERVER } = require('next/constants');
module.exports = (phase, { defaultConfig }) => {
console.log('Phase >>>>', phase);
if (phase === PHASE_DEVELOPMENT_SERVER) {
console.log('RETURNING DEVELOPMENT CONFIGURATION...');
return {
publicRuntimeConfig: {
GRAPHQL_URL: process.env.GRAPHQL_URL
}
};
}
console.log('RETURNING PRODUCTION CONFIGURATION...');
console.log('GRAPHQL_URL', process.env.GRAPHQL_URL);
return {
publicRuntimeConfig: {
GRAPHQL_URL: process.env.GRAPHQL_URL
}
};
};
This is my _app.tsx
function MyApp({ Component, pageProps }: AppProps) {
// Grab the apollo client instance with state hydration from the pageProps
const router = useRouter();
const apolloClient = useApollo(pageProps.initialApolloState);
const [client, setClient] = useState(apolloClient);
React.useEffect(() => {
// Refresh token on browser load or page regresh
handleAcquireTokenSilent();
// We also set up an interval of 5 mins to check if token needs to be refreshed
const refreshTokenInterval = setInterval(() => {
handleAcquireTokenSilent();
}, REFRESH_TOKEN_SILENTLY_INTERVAL);
return () => {
clearInterval(refreshTokenInterval);
};
}, []);
const updateApolloWithNewToken = useCallback(
(accessToken: string) => {
// Initialize apollo client with new access token
setClient(
initializeApollo(accessToken, pageProps.initialApolloState, true)
);
// Show the dashboard
router.replace('/dashboard');
},
[router]
);
return pageProps.isAuthenticated || pageProps.shouldPageHandleUnAuthorize ? (
<ApolloProvider client={client}>
<ThemeProvider theme={theme}>
<SCThemeProvider theme={theme}>
<StylesProvider injectFirst>
<Component
{...pageProps}
updateAuthToken={updateApolloWithNewToken}
/>
</StylesProvider>
</SCThemeProvider>
</ThemeProvider>
</ApolloProvider>
) : (
<UnAuthorize />
);
}
/**
* Fetches the Me query so that pages/components can grab it from the cache in the
* client.
*
* Note: This disables the ability to perform automatic static optimization, causing
* every page in the app to be server-side rendered.
*/
MyApp.getInitialProps = async (appContext: AppContext) => {
const appProps = await App.getInitialProps(appContext);
const req = appContext.ctx.req;
// Execute Me query and handle all scenarios including, unauthorized response, caching data so pages can grab
// data from the cache
return await handleMeQuery(appProps, req);
};
export default MyApp;
My problem is that when I run yarn build I get a server error generating 500 page. I know it is because when creating the Apollo Client it doesn't have access to the publicRuntimeConfig, it seems like Next is trying to build the ApolloClient when I run yarn build, I am using getInitialProps and getServerSideProps so I just want to access all the env variables on runtime not on build, because we want one build for our pipeline.
All other env variables in my app that are using publicRuntimeConfig are working, I tested by removing the env vars on build and adding them back on start and the app functioned as normal.
If there isn't a way to do this with apollo client, what would be reccomended to be able to pass different uri's as env variables on start of the app not on build for Apollo Client or alternate solution?
Thanks for any help ahead of time
So I don't know if I have explained the problem well enough.
Basically the graphql URL is different depending on the environment it is in in development, staging, and production however they are supposed to use the same build so I need to access the GRAPHQL_URL via a runtime variable, but in my current setup it is just undefined.
Generally you don't want to use publicRuntimeConfig because it adds overhead and is unnecessary for your use-case. It also disables automatic static optimization.
Traditionally, environment variables are the way to handle dynamic settings based on the environment. Next.js has three default environments – development, test, and production.
Your Next.js app will automatically grab (and merge) the correct variables depending on the environment.
.env.local
GRAPHQL_URL = localhost:8000/graphql
.env.test
GRAPHQL_URL = test.example.com/graphql
.env or .env.production
GRAPHQL_URL = production.example.com/graphql
Apollo config
new ApolloClient({
link: createHttpLink({
uri: process.env.GRAPHQL_URL,
})
});
Environment variable files
In your project root you can create files named
.env
.env.local
.env.test
.env.test.local
.env.production
I believe you can append .local to any environment to create a local only version .env.production.local - this has limited use in your case
Next.js Environment variables
All environments - .env
loaded in development, test, and production environments. This file is used for defaults across all environments. The variables in this file will be overroad if another environment variable file has a variable with the same name.
Development environment .env.local
loaded only when NODE_ENV = development (next dev)
Test environment .env.test
loaded only when NODE_ENV = test
Test environment .env.test.local
loaded only when NODE_ENV = test and local
Production environment .env.production
loaded only when NODE_ENV = production (next start)
Example production only variable
Create a .env.production and add the variable there. You can repeat the same for test and local only variables.
Notes
It's good practice to add your .env to your .gitignore so you don't accidently commit secrets to your repositories. At a minimum you should omit .env*.local files from git.
Depending on your CI/CD setup you can set your environment variables in the deployment platform like vercel, github actions, etc. This would allow you to set the test and production variables in the hosting platform and not in your code.
If you need an environment variable accessible in the browser you need to prefix the variabel with NEXT_PUBLIC_
First, there is redundant code and inefficiency. Primarily the hooks updateApolloWithNewToken and useApollo but also in the way you inject the accessToken.
I would recommend throwing the ApolloClient in it's own separate file and using it's configurable links for your use-case.
However, the real problem most likely lies in the initialization of the client and your attempt at memoizing the client.
First, try updating the following,
link: createHttpLink({
uri: publicRuntimeConfig.GRAPHQL_URL,
credentials: 'same-origin',
headers: httpLinkHeaders
}),
to
link: createHttpLink({
// ...your other stuff
uri: () => getConfig().publicRuntimeConfig.GRAPHQL_URL
})
If that doesn't work right away, I would recommend trying with the outmost minimal example.
Create a client you export, a provider and a component that uses it (without using state, useEffect or anything else). We can go from there if that still doesn't work.
I'm coding for an API connection area, that's predominately graphql but needs to have some REST connections for certain things, and have equivalent to the following code:
foo.js
module.exports = {
routes: () => {
return [
{
method: 'GET',
path: '/existing_endpoint',
handler: module.exports.existing_endpoint
},
{
method: 'POST',
path: '/new_endpoint',
handler: module.exports.new_endpoint // <--- this not passing variables
}
]
},
existing_endpoint: async () => {
/* endpoint that isn't the concern of this */
},
new_endpoint: async (req, res) => {
console.log({req, res})
return 1
}
}
The existing GET endpoint works fine, but my POST endpoint always errors out with the console of {} where {req, res} should have been passed in by the router, I suspect because the POST isn't receiving. I've tried changing the POST declaration in the routes to module.exports.new_endpoint(req, res), but it tells me the variables aren't found, and the lead-in server.js does have the file (it looks more like this...), and doing similar with the server.js, also getting similar results, implying that's probably wrong too. Also, we have a really strict eslint setup, so I can't really change the format of the call.
Every example I've seen online using these libraries is some short form, or includes the function in the routes call, and isn't some long form like this. How do I do a POST in this format?
/* hapi, environment variables, apollog server, log engine, etc. */
/* preceeding library inclusions */
const foo = require('./routes/foo')
const other_route = require('./routes/other_route')
const startServer = async () => {
const server = Hapi.server({port, host})
server.route(other_route.routes())
server.route(foo.routes())
}
This is a bug with Hapi in node v16. I just opened an issue.
Your current solutions are either:
Upgrade to Hapi v20
Use n or another method to downgrade to node v14.16 for this project. I can confirm that POST requests do not hang in this version.
I have added Workbox to Angular in first production deploy everything works fine, but after updating a module and rebuilding angular and injecting Workbox then visiting the site i see the service worker updates to the new version and refreshes the page, but now trying to use the updated module I get errors
Refused to execute script from 'https://example.com/8-es2015.203674bf0547eff7ff27.js'
because its MIME type ('text/html') is not executable,
and strict MIME type checking is enabled.
main-es2015.45ba4a512f87eefb1b3a.js:1 ERROR Error: Uncaught (in promise): ChunkLoadError:
Loading chunk 8 failed.(error: https://example.com/8-es2015.203674bf0547eff7ff27.js)
ChunkLoadError: Loading chunk 8 failed......
I looked at the network in chrome and I see that the file 8-es2015.203674bf0547eff7ff27.js is being served from the (disk cache) unlike the rest of the files which get served by (ServiceWorker), its content is the index.html file I don't know where it came from its not even part of the new build ? chrome places it in top frame section under scripts
Whats the reason for this Error, in the angular.json I have "outputHashing": "all", I delete everything and rebuild but still this errors, its until I clear the browser cash remove the ServiceWorker and hard refresh that the error stops happening until I reload page and it returns. Do I need to delete all the cache after every update, I thought Workbox does this automatically.Do I add something like so in the sw.js
self.addEventListener('activate', event => event.waitUntil(
caches.keys().then(cacheNames => cacheNames.forEach(name => caches.delete(name)))
)
);
Am using express, so I have set the maxAge on the sw.js to 0 and even change the public route to static files to a deep route but nothing
app.use('/sw.js', express.static(path.resolve('./public/dist/static/sw.js'), {maxAge: 0}));
app.use('/', express.static(path.resolve('./public/dist/static/'), {maxAge: 86400000}));
tools: angular 8.2.4 - workbox 4.3.1
Update
Removed workbox and the app worked, am guessing its cause of their new package workbox-window or the way am trying to use it. I have placed it in module service that is loaded from app.module then the service is called from a AppComponent ngOnInit. This could be the wrong way of initializing it.
code setup:
import {Workbox} from 'workbox-window';
#Injectable()
export class WorkerService {
supportWorker: boolean;
supportPush: boolean;
constructor(#Inject(WINDOW) private window: any, private loggerService: LoggerService) {
this.supportWorker = ('serviceWorker' in navigator);
this.supportPush = (this.supportWorker && 'PushManager' in window);
}
initWorker() {
if (this.supportWorker && environment.production) {
const wb = new Workbox('sw.js');
if (wb) {
wb.addEventListener('installed', event => {
if (event.isUpdate) {
// output a toast translated message to users
this.loggerService.info('App.webWorkerUpdate', 10000);
setTimeout(() => this.window.location.reload(), 10000);
}
});
wb.addEventListener('activated', event => {
if (!event.isUpdate) {
this.loggerService.success('App.webWorkerInit', 10000);
}
});
wb.register();
}
}
}
}
This the app component, i thought it would be best to add it to main.ts after bootstrapModule.then() but I don't know how inject a service in this method
#Component({
selector: 'app-root',
template: '<route-handler></route-handler>'
})
export class AppComponent implements OnInit {
constructor(private ws: WorkerService) {
}
ngOnInit(): void {
this.ws.initWorker();
}
}
After setting up Workbox in a different way it worked, the problem effected even chrome which failed to clear all cache after each build when testing it, had to use incognito to make sure everything works.
Here is the solution thanks to Ralph Schaer article a must read. His method is not to Cache-Bust the chunks angular build generates, also he globs in all the production scripts of workbox used by the app into the build folder and finally in the index.html he calls on workbox-window to register the service-worker.