Adds migration docs to 0.13 (#1890)

This commit is contained in:
Mihovil Ilakovac 2024-03-18 13:09:37 +01:00
parent 0880556592
commit 8beec5928a
9 changed files with 284 additions and 66 deletions

View File

@ -26,7 +26,7 @@ Enabling GitHub Authentication comes down to a series of steps:
1. Enabling GitHub authentication in the Wasp file.
1. Adding the `User` entity.
1. Creating a GitHub OAuth app.
1. Adding the neccessary Routes and Pages
1. Adding the necessary Routes and Pages
1. Using Auth UI components in our Pages.
<WaspFileStructureNote />
@ -41,7 +41,7 @@ Let's start by properly configuring the Auth object:
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -66,7 +66,7 @@ app myApp {
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -135,8 +135,8 @@ width="400px"
/>
- For **Authorization callback URL**:
- For development, put: `http://localhost:3000/auth/login/github`.
- Once you know on which URL your app will be deployed, you can create a new app with that URL instead e.g. `https://someotherhost.com/auth/login/github`.
- For development, put: `http://localhost:3001/auth/github/callback`.
- Once you know on which URL your API server will be deployed, you can create a new app with that URL instead e.g. `https://your-server-url.com/auth/github/callback`.
4. Hit **Register application**.
5. Hit **Generate a new client secret** on the next page.
@ -255,7 +255,7 @@ export function Layout({ children }: { children: React.ReactNode }) {
</TabItem>
</Tabs>
We imported the generated Auth UI component and used them in our pages. Read more about the Auth UI components [here](../../auth/ui).
We imported the generated Auth UI components and used them in our pages. Read more about the Auth UI components [here](../../auth/ui).
### Conclusion
@ -276,7 +276,7 @@ Add `gitHub: {}` to the `auth.methods` dictionary to use it with default setting
```wasp title=main.wasp
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -296,7 +296,7 @@ app myApp {
```wasp title=main.wasp
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -319,7 +319,52 @@ app myApp {
<OverrideIntro />
### Using the User's Provider Account Details
### Data Received From GitHub
We are using GitHub's API and its `/user` and `/user/emails` endpoints to get the user data.
:::info We combine the data from the two endpoints
You'll find the emails in the `emails` property in the object that you receive in `userSignupFields`.
This is because we combine the data from the `/user` and `/user/emails` endpoints **if the `user` or `user:email` scope is requested.**
:::
The data we receive from GitHub on the `/user` endpoint looks something this:
```json
{
"login": "octocat",
"id": 1,
"name": "monalisa octocat",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
// ...
}
```
And the data from the `/user/emails` endpoint looks something like this:
```json
[
{
"email": "octocat@github.com",
"verified": true,
"primary": true,
"visibility": "public"
}
]
```
The fields you receive will depend on the scopes you requested. By default we don't specify any scopes. If you want to get the emails, you need to specify the `user` or `user:email` scope in the `configFn` function.
<small>
For an up to date info about the data received from GitHub, please refer to the [GitHub API documentation](https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-the-authenticated-user).
</small>
### Using the Data Received From GitHub
<OverrideExampleIntro />
@ -329,7 +374,7 @@ app myApp {
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -358,14 +403,12 @@ psl=}
```js title=src/auth/github.js
export const userSignupFields = {
username: () => "hardcoded-username",
displayName: (data) => data.profile.displayName,
displayName: (data) => data.profile.name,
};
export function getConfig() {
return {
clientID // look up from env or elsewhere
clientSecret // look up from env or elsewhere
scope: [],
scopes: ['user'],
};
}
```
@ -376,7 +419,7 @@ export function getConfig() {
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -407,14 +450,12 @@ import { defineUserSignupFields } from 'wasp/server/auth'
export const userSignupFields = defineUserSignupFields({
username: () => "hardcoded-username",
displayName: (data) => data.profile.displayName,
displayName: (data: any) => data.profile.name,
})
export function getConfig() {
return {
clientID, // look up from env or elsewhere
clientSecret, // look up from env or elsewhere
scope: [],
scopes: ['user'],
}
}
```
@ -438,7 +479,7 @@ export function getConfig() {
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -462,7 +503,7 @@ app myApp {
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -487,7 +528,7 @@ The `gitHub` dict has the following properties:
- #### `configFn: ExtImport`
This function should return an object with the Client ID, Client Secret, and scope for the OAuth provider.
This function should return an object with the scopes for the OAuth provider.
<Tabs groupId="js-ts">
<TabItem value="js" label="JavaScript">
@ -495,9 +536,7 @@ The `gitHub` dict has the following properties:
```js title=src/auth/github.js
export function getConfig() {
return {
clientID, // look up from env or elsewhere
clientSecret, // look up from env or elsewhere
scope: [],
scopes: [],
}
}
```
@ -508,9 +547,7 @@ The `gitHub` dict has the following properties:
```ts title=src/auth/github.ts
export function getConfig() {
return {
clientID, // look up from env or elsewhere
clientSecret, // look up from env or elsewhere
scope: [],
scopes: [],
}
}
```
@ -521,4 +558,5 @@ The `gitHub` dict has the following properties:
- #### `userSignupFields: ExtImport`
<UserSignupFieldsExplainer />
Read more about the `userSignupFields` function [here](../overview#1-defining-extra-fields).

View File

@ -26,7 +26,7 @@ Enabling Google Authentication comes down to a series of steps:
1. Enabling Google authentication in the Wasp file.
1. Adding the `User` entity.
1. Creating a Google OAuth app.
1. Adding the neccessary Routes and Pages
1. Adding the necessary Routes and Pages
1. Using Auth UI components in our Pages.
<WaspFileStructureNote />
@ -41,7 +41,7 @@ Let's start by properly configuring the Auth object:
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -64,7 +64,7 @@ app myApp {
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -167,12 +167,12 @@ To use Google as an authentication method, you'll first need to create a Google
![Google Console Screenshot 12](/img/integrations-google-12.jpg)
- Under Authorized redirect URIs, put in: `http://localhost:3000/auth/login/google`
- Under Authorized redirect URIs, put in: `http://localhost:3001/auth/google/callback`
![Google Console Screenshot 13](/img/integrations-google-13.jpg)
- Once you know on which URL(s) your API server will be deployed, also add those URL(s).
- For example: `https://someotherhost.com/auth/login/google`
- For example: `https://your-server-url.com/auth/google/callback`
- When you save, you can click the Edit icon and your credentials will be shown.
@ -317,7 +317,7 @@ Add `google: {}` to the `auth.methods` dictionary to use it with default setting
```wasp title=main.wasp
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -337,7 +337,7 @@ app myApp {
```wasp title=main.wasp
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -360,7 +360,37 @@ app myApp {
<OverrideIntro />
### Using the User's Provider Account Details
### Data Received From Google
We are using Google's API and its `/userinfo` endpoint to fetch the user's data.
The data received from Google is an object which can contain the following fields:
```json
[
"name",
"given_name",
"family_name",
"email",
"email_verified",
"aud",
"exp",
"iat",
"iss",
"locale",
"picture",
"sub"
]
```
The fields you receive depend on the scopes you request. The default scope is set to `profile` only. If you want to get the user's email, you need to specify the `email` scope in the `configFn` function.
<small>
For an up to date info about the data received from Google, please refer to the [Google API documentation](https://developers.google.com/identity/openid-connect/openid-connect#an-id-tokens-payload).
</small>
### Using the Data Received From Google
<OverrideExampleIntro />
@ -370,7 +400,7 @@ app myApp {
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -399,14 +429,12 @@ psl=}
```js title=src/auth/google.js
export const userSignupFields = {
username: () => "hardcoded-username",
displayName: (data) => data.profile.displayName,
displayName: (data) => data.profile.name,
}
export function getConfig() {
return {
clientID, // look up from env or elsewhere
clientSecret, // look up from env or elsewhere
scope: ['profile', 'email'],
scopes: ['profile', 'email'],
}
}
```
@ -417,7 +445,7 @@ export function getConfig() {
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -448,14 +476,12 @@ import { defineUserSignupFields } from 'wasp/server/auth'
export const userSignupFields = defineUserSignupFields({
username: () => "hardcoded-username",
displayName: (data) => data.profile.displayName,
displayName: (data: any) => data.profile.name,
})
export function getConfig() {
return {
clientID, // look up from env or elsewhere
clientSecret, // look up from env or elsewhere
scope: ['profile', 'email'],
scopes: ['profile', 'email'],
}
}
```
@ -479,7 +505,7 @@ export function getConfig() {
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -503,7 +529,7 @@ app myApp {
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -528,7 +554,7 @@ The `google` dict has the following properties:
- #### `configFn: ExtImport`
This function must return an object with the Client ID, the Client Secret, and the scope for the OAuth provider.
This function must return an object with the scopes for the OAuth provider.
<Tabs groupId="js-ts">
<TabItem value="js" label="JavaScript">
@ -536,9 +562,7 @@ The `google` dict has the following properties:
```js title=src/auth/google.js
export function getConfig() {
return {
clientID, // look up from env or elsewhere
clientSecret, // look up from env or elsewhere
scope: ['profile', 'email'],
scopes: ['profile', 'email'],
}
}
```
@ -549,9 +573,7 @@ The `google` dict has the following properties:
```ts title=src/auth/google.ts
export function getConfig() {
return {
clientID, // look up from env or elsewhere
clientSecret, // look up from env or elsewhere
scope: ['profile', 'email'],
scopes: ['profile', 'email'],
}
}
```
@ -562,4 +584,5 @@ The `google` dict has the following properties:
- #### `userSignupFields: ExtImport`
<UserSignupFieldsExplainer />
Read more about the `userSignupFields` function [here](../overview#1-defining-extra-fields).

View File

@ -36,7 +36,7 @@ Here's what the full setup looks like:
```wasp title=main.wasp
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -62,7 +62,7 @@ psl=}
```wasp title=main.wasp
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -152,7 +152,7 @@ Declare an import under `app.auth.methods.google.userSignupFields` (the example
```wasp title=main.wasp
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {
@ -184,7 +184,7 @@ export const userSignupFields = {
```wasp title=main.wasp
app myApp {
wasp: {
version: "^0.11.0"
version: "^0.13.0"
},
title: "My App",
auth: {

View File

@ -4,6 +4,14 @@ title: Migration from 0.11.X to 0.12.X
import { EmailPill, UsernameAndPasswordPill, GithubPill, GooglePill } from "./auth/Pills";
:::note The latest version of Wasp is 0.13.X
To fully migrate from 0.11.X to the latest version of Wasp, you should first migrate to **0.12.X and then to 0.13.X**.
Make sure to read the [migration guide from 0.12.X to 0.13.X](./migrate-from-0-12-to-0-13.md) after you finish this one.
:::
## What's new in Wasp 0.12.0?
### New project structure

View File

@ -0,0 +1,134 @@
---
title: Migration from 0.12.X to 0.13.X
---
:::note Are you on 0.11.X or earlier?
This guide only covers the migration from **0.12.X to 0.13.X**. If you are migrating from 0.11.X or earlier, please read the [migration guide from 0.11.X to 0.12.X](./migrate-from-0-11-to-0-12.md) first.
:::
## What's new in 0.13.0?
### OAuth providers got an overhaul
Wasp 0.13.0 switches away from using Passport for our OAuth providers in favor of [Arctic](https://arctic.js.org/) from the [Lucia](https://lucia-auth.com/) ecosystem. This change simplifies the codebase and makes it easier to add new OAuth providers in the future.
### We added Keycloak as an OAuth provider
Wasp now supports using [Keycloak](https://www.keycloak.org/) as an OAuth provider.
## How to migrate?
### Migrate your OAuth setup
We had to make some breaking changes to upgrade the OAuth setup to the new Arctic lib.
Follow the steps below to migrate:
1. **Define the `WASP_SERVER_URL` server env variable**
In 0.13.0 Wasp introduces a new server env variable `WASP_SERVER_URL` that you need to define. This is the URL of your Wasp server and it's used to generate the redirect URL for the OAuth providers.
```bash title="Server env variables"
WASP_SERVER_URL=https://your-wasp-server-url.com
```
In development, Wasp sets the `WASP_SERVER_URL` to `http://localhost:3001` by default.
:::info Migrating a deployed app
If you are migrating a deployed app, you will need to define the `WASP_SERVER_URL` server env variable in your deployment environment.
Read more about setting env variables in production [here](./project/env-vars#defining-env-vars-in-production).
:::
2. **Update the redirect URLs** for the OAuth providers
The redirect URL for the OAuth providers has changed. You will need to update the redirect URL for the OAuth providers in the provider's dashboard.
<Tabs>
<TabItem value="before" label="Before">
```
{clientUrl}/auth/login/{provider}
```
</TabItem>
<TabItem value="after" label="After">
```
{serverUrl}/auth/{provider}/callback
```
</TabItem>
</Tabs>
Check the new redirect URLs for [Google](./auth/social-auth/google.md#3-creating-a-google-oauth-app) and [GitHub](./auth/social-auth/github.md#3-creating-a-github-oauth-app) in Wasp's docs.
3. **Update the `configFn`** for the OAuth providers
If you didn't use the `configFn` option, you can skip this step.
If you used the `configFn` to configure the `scope` for the OAuth providers, you will need to rename the `scope` property to `scopes`.
Also, the object returned from `configFn` no longer needs to include the Client ID and the Client Secret. You can remove them from the object that `configFn` returns.
<Tabs>
<TabItem value="before" label="Before">
```ts title="google.ts"
export function getConfig() {
return {
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
scope: ['profile', 'email'],
}
}
```
</TabItem>
<TabItem value="after" label="After">
```ts title="google.ts"
export function getConfig() {
return {
scopes: ['profile', 'email'],
}
}
```
</TabItem>
</Tabs>
4. **Update the `userSignupFields` fields** to use the new `profile` format
If you didn't use the `userSignupFields` option, you can skip this step.
The data format for the `profile` that you receive from the OAuth providers has changed. You will need to update your code to reflect this change.
<Tabs>
<TabItem value="before" label="Before">
```ts title="google.ts"
import { defineUserSignupFields } from 'wasp/server/auth'
export const userSignupFields = defineUserSignupFields({
displayName: (data: any) => data.profile.displayName,
})
```
</TabItem>
<TabItem value="after" label="After">
```ts title="google.ts"
import { defineUserSignupFields } from 'wasp/server/auth'
export const userSignupFields = defineUserSignupFields({
displayName: (data: any) => data.profile.name,
})
```
</TabItem>
</Tabs>
Wasp now directly forwards what it receives from the OAuth providers. You can check the data format for [Google](./auth/social-auth/google.md#data-received-from-google) and [GitHub](./auth/social-auth/github.md#data-received-from-github) in Wasp's docs.
That's it!
You should now be able to run your app with the new Wasp 0.13.0.

2
web/package-lock.json generated
View File

@ -38,7 +38,7 @@
"remark-validate-links": "^12.1.1"
},
"engines": {
"node": "^18.12.0"
"node": ">=18.12.0"
}
},
"node_modules/@algolia/autocomplete-core": {

View File

@ -48,7 +48,7 @@
"remark-validate-links": "^12.1.1"
},
"engines": {
"node": "^18.12.0"
"node": ">=18.12.0"
},
"browserslist": {
"production": [

View File

@ -139,6 +139,7 @@ module.exports = {
'vision',
'contact',
'migrate-from-0-11-to-0-12',
'migrate-from-0-12-to-0-13',
],
},
],

View File

@ -1,10 +1,24 @@
// Copied from
// Copied from
// https://github.com/redwoodjs/redwood/blob/bd903c5755925ea7174775a2fdaba371b700c910/docs/src/remark/auto-import-tabs.js
// and modified to work with nested tab usage.
const needImports = (tree) =>
tree.children.some(
(child) => child.type === 'jsx' && /^<Tabs\b/.test(child.value)
)
const needImports = (tree) => {
const checkChildren = (children) => {
for (const child of children) {
if (child.type === 'jsx' && /^<Tabs\b/.test(child.value)) {
return true;
}
if (child.children && child.children.length > 0) {
if (checkChildren(child.children)) {
return true;
}
}
}
return false;
};
return checkChildren(tree.children);
};
const plugin = () => (tree, _file) => {
if (needImports(tree)) {