diff --git a/.github/workflows/packer.yaml b/.github/workflows/packer.yaml index 9026f7dca9..2d579bfb2e 100644 --- a/.github/workflows/packer.yaml +++ b/.github/workflows/packer.yaml @@ -46,7 +46,7 @@ jobs: CLOUDFLARE_TOKEN: ${{secrets.CLOUDFLARE_TOKEN}} SSL_CERT: ${{secrets.SSL_CERT}} SSL_KEY: ${{secrets.SSL_KEY}} - API_VERSION: 561d8d6b19c01a273b6b039628d1ff7b6b295b4e + API_VERSION: 439169b9522852b0582634b692260c7b8853eff2 # get the image information from gcloud - name: Get image information diff --git a/app/docs/nexus-openapi.json b/app/docs/nexus-openapi.json index 2014648694..e803b1718b 100644 --- a/app/docs/nexus-openapi.json +++ b/app/docs/nexus-openapi.json @@ -174,6 +174,28 @@ } } }, + "/login": { + "post": { + "operationId": "spoof_login", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginParams" + } + } + }, + "required": true + }, + "responses": {} + } + }, + "/logout": { + "post": { + "operationId": "logout", + "responses": {} + } + }, "/organizations": { "get": { "description": "List all organizations.", @@ -3110,6 +3132,15 @@ "minLength": 1, "maxLength": 11 }, + "LoginParams": { + "type": "object", + "properties": { + "username": { + "type": "string" + } + }, + "required": ["username"] + }, "Name": { "title": "A name used in the API", "description": "Names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'.", diff --git a/app/pages/LoginPage.tsx b/app/pages/LoginPage.tsx new file mode 100644 index 0000000000..d34b6183ba --- /dev/null +++ b/app/pages/LoginPage.tsx @@ -0,0 +1,101 @@ +import React from 'react' +import { useNavigate } from 'react-router' + +import { useApiMutation } from '@oxide/api' +import { Button, Warning12Icon, Success16Icon } from '@oxide/ui' +import { useToast } from '../hooks' + +/** + * Placeholder login page for demo purposes. + * + * The demo login form is only in the console bundle for the convenience of + * using existing tooling and using the generated API client. In the real rack, + * login will go through the customer's IdP; no form controlled by us will be + * involved. If Nexus *does* end up serving a login form, e.g., for use by + * admins before the IdP is set up, that will be a separate bundle with minimal + * JS (ideally so minimal we could inline it in the HTML response) and it would + * not use the generated API client at all. It could even use an HTML form POST. + * + * Login and logout endpoints are only a temporary addition to the OpenAPI spec. + */ +export default function LoginPage() { + const navigate = useNavigate() + const addToast = useToast() + const loginPost = useApiMutation('spoofLogin', { + onSuccess: () => { + addToast({ + title: 'Logged in', + icon: , + timeout: 4000, + }) + navigate('/') + }, + onError: () => { + addToast({ + title: 'Bad credentials', + icon: , + variant: 'error', + timeout: 4000, + }) + }, + }) + + const logout = useApiMutation('logout', { + onSuccess: () => { + addToast({ + title: 'Logged out', + icon: , + timeout: 4000, + }) + }, + }) + return ( +
+
+

Log in as

+ + + + +
+
+ ) +} diff --git a/app/pages/OrgPage.tsx b/app/pages/OrgPage.tsx index df2190bedb..67234b1534 100644 --- a/app/pages/OrgPage.tsx +++ b/app/pages/OrgPage.tsx @@ -22,7 +22,7 @@ export default function OrgPage() {
- + Create project
diff --git a/app/pages/ProjectsPage.tsx b/app/pages/ProjectsPage.tsx index 7a0923ee81..c0ab1b679d 100644 --- a/app/pages/ProjectsPage.tsx +++ b/app/pages/ProjectsPage.tsx @@ -46,10 +46,7 @@ const ProjectsPage = () => { }>Projects
- + New Project