mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
Fixes #210 - this isPR implements `coder login` in the case where the default user is already created. This change adds: - A prompt in the case where there is not an initial user that opens the server URL + requests a session token - This ports over some code from v1 for the `openURL` and `isWSL` functions to support opening the browser - A `/api/v2/api-keys` endpoint that can be `POST`'d to in order to request a new api key for a user - This route was inspired by the v1 functionality - A `cli-auth` route + page that shows the generated api key - Tests for the new code + storybook for the new UI The `/cli-auth` route, like in v1, is very minimal: <img width="624" alt="Screen Shot 2022-02-16 at 5 05 07 PM" src="https://user-images.githubusercontent.com/88213859/154384627-78ab9841-27bf-490f-9bbe-23f8173c9e97.png"> And the terminal UX looks like this: 
155 lines
3.2 KiB
TypeScript
155 lines
3.2 KiB
TypeScript
import { mutate } from "swr"
|
|
|
|
interface LoginResponse {
|
|
session_token: string
|
|
}
|
|
|
|
/**
|
|
* `Organization` must be kept in sync with the go struct in organizations.go
|
|
*/
|
|
export interface Organization {
|
|
id: string
|
|
name: string
|
|
created_at: string
|
|
updated_at: string
|
|
}
|
|
|
|
export interface Provisioner {
|
|
id: string
|
|
name: string
|
|
}
|
|
|
|
export const provisioners: Provisioner[] = [
|
|
{
|
|
id: "terraform",
|
|
name: "Terraform",
|
|
},
|
|
{
|
|
id: "cdr-basic",
|
|
name: "Basic",
|
|
},
|
|
]
|
|
|
|
// This must be kept in sync with the `Project` struct in the back-end
|
|
export interface Project {
|
|
id: string
|
|
created_at: string
|
|
updated_at: string
|
|
organization_id: string
|
|
name: string
|
|
provisioner: string
|
|
active_version_id: string
|
|
}
|
|
|
|
export interface CreateProjectRequest {
|
|
name: string
|
|
organizationId: string
|
|
provisioner: string
|
|
}
|
|
|
|
export namespace Project {
|
|
export const create = async (request: CreateProjectRequest): Promise<Project> => {
|
|
const response = await fetch(`/api/v2/projects/${request.organizationId}/`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(request),
|
|
})
|
|
|
|
const body = await response.json()
|
|
await mutate("/api/v2/projects")
|
|
if (!response.ok) {
|
|
throw new Error(body.message)
|
|
}
|
|
|
|
return body
|
|
}
|
|
}
|
|
|
|
export interface CreateWorkspaceRequest {
|
|
name: string
|
|
project_id: string
|
|
}
|
|
|
|
// Must be kept in sync with backend Workspace struct
|
|
export interface Workspace {
|
|
id: string
|
|
created_at: string
|
|
updated_at: string
|
|
owner_id: string
|
|
project_id: string
|
|
name: string
|
|
}
|
|
|
|
export namespace Workspace {
|
|
export const create = async (request: CreateWorkspaceRequest): Promise<Workspace> => {
|
|
const response = await fetch(`/api/v2/workspaces/me`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(request),
|
|
})
|
|
|
|
const body = await response.json()
|
|
if (!response.ok) {
|
|
throw new Error(body.message)
|
|
}
|
|
|
|
// Let SWR know that both the /api/v2/workspaces/* and /api/v2/projects/*
|
|
// endpoints will need to fetch new data.
|
|
const mutateWorkspacesPromise = mutate("/api/v2/workspaces")
|
|
const mutateProjectsPromise = mutate("/api/v2/projects")
|
|
await Promise.all([mutateWorkspacesPromise, mutateProjectsPromise])
|
|
|
|
return body
|
|
}
|
|
}
|
|
|
|
export const login = async (email: string, password: string): Promise<LoginResponse> => {
|
|
const response = await fetch("/api/v2/login", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
email,
|
|
password,
|
|
}),
|
|
})
|
|
|
|
const body = await response.json()
|
|
if (!response.ok) {
|
|
throw new Error(body.message)
|
|
}
|
|
|
|
return body
|
|
}
|
|
|
|
export const logout = async (): Promise<void> => {
|
|
const response = await fetch("/api/v2/logout", {
|
|
method: "POST",
|
|
})
|
|
|
|
if (!response.ok) {
|
|
const body = await response.json()
|
|
throw new Error(body.message)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
export const getApiKey = async (): Promise<{ key: string }> => {
|
|
const response = await fetch("/api/v2/users/me/keys", {
|
|
method: "POST",
|
|
})
|
|
|
|
if (!response.ok) {
|
|
const body = await response.json()
|
|
throw new Error(body.message)
|
|
}
|
|
|
|
return await response.json()
|
|
}
|