Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/api/src/api/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,29 @@ export type GithubAuthStatus = {
readonly tokens: ReadonlyArray<GithubAuthTokenStatus>
}

export type GitlabAuthTokenStatus = {
readonly key: string
readonly label: string
readonly status: "valid" | "invalid" | "unknown"
readonly login: string | null
}

export type GitlabAuthStatus = {
readonly summary: string
readonly tokens: ReadonlyArray<GitlabAuthTokenStatus>
}

export type GithubAuthLoginRequest = {
readonly label?: string | null | undefined
readonly token?: string | null | undefined
readonly scopes?: string | null | undefined
}

export type GitlabAuthLoginRequest = {
readonly label?: string | null | undefined
readonly token?: string | null | undefined
}

export type AuthMenuFlow =
| "GithubRemove"
| "GitSet"
Expand Down Expand Up @@ -197,6 +214,10 @@ export type GithubAuthLogoutRequest = {
readonly label?: string | null | undefined
}

export type GitlabAuthLogoutRequest = {
readonly label?: string | null | undefined
}

export type CodexAuthImportRequest = {
readonly label?: string | null | undefined
readonly authText: string
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/api/errors.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Data } from "effect"

export class ApiAuthRequiredError extends Data.TaggedError("ApiAuthRequiredError")<{
readonly provider: "github"
readonly provider: "github" | "gitlab"
readonly message: string
readonly command: string
}> {}
Expand Down
11 changes: 11 additions & 0 deletions packages/api/src/api/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ export const GithubAuthLoginRequestSchema = Schema.Struct({
scopes: OptionalNullableString
})

export const GitlabAuthLoginRequestSchema = Schema.Struct({
label: OptionalNullableString,
token: OptionalNullableString
})

export const AuthMenuFlowSchema = Schema.Literal(
"GithubRemove",
"GitSet",
Expand Down Expand Up @@ -74,6 +79,10 @@ export const GithubAuthLogoutRequestSchema = Schema.Struct({
label: OptionalNullableString
})

export const GitlabAuthLogoutRequestSchema = Schema.Struct({
label: OptionalNullableString
})

export const CodexAuthImportRequestSchema = Schema.Struct({
label: OptionalNullableString,
authText: Schema.String
Expand Down Expand Up @@ -282,9 +291,11 @@ export const TerminalSessionSchema = Schema.Struct({

export type CreateProjectRequestInput = Schema.Schema.Type<typeof CreateProjectRequestSchema>
export type GithubAuthLoginRequestInput = Schema.Schema.Type<typeof GithubAuthLoginRequestSchema>
export type GitlabAuthLoginRequestInput = Schema.Schema.Type<typeof GitlabAuthLoginRequestSchema>
export type AuthMenuRequestInput = Schema.Schema.Type<typeof AuthMenuRequestSchema>
export type AuthTerminalSessionRequestInput = Schema.Schema.Type<typeof AuthTerminalSessionRequestSchema>
export type GithubAuthLogoutRequestInput = Schema.Schema.Type<typeof GithubAuthLogoutRequestSchema>
export type GitlabAuthLogoutRequestInput = Schema.Schema.Type<typeof GitlabAuthLogoutRequestSchema>
export type CodexAuthImportRequestInput = Schema.Schema.Type<typeof CodexAuthImportRequestSchema>
export type CodexAuthLoginRequestInput = Schema.Schema.Type<typeof CodexAuthLoginRequestSchema>
export type CodexAuthLogoutRequestInput = Schema.Schema.Type<typeof CodexAuthLogoutRequestSchema>
Expand Down
45 changes: 45 additions & 0 deletions packages/api/src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import {
CreateProjectRequestSchema,
ExchangePollRequestSchema,
ExchangeSubscribeRequestSchema,
GitlabAuthLoginRequestSchema,
GitlabAuthLogoutRequestSchema,
GithubAuthLoginRequestSchema,
GithubAuthLogoutRequestSchema,
ProjectDatabaseProfileRequestSchema,
Expand All @@ -40,13 +42,17 @@ import { defaultProjectsRoot } from "@effect-template/lib/usecases/menu-helpers"
import { resolveWorkspaceRoot } from "@effect-template/lib/shell/workspace-root"
import {
importCodexAuth,
loginGitlabAuth,
loginGithubAuth,
logoutCodexAuth,
logoutGitlabAuth,
logoutGithubAuth,
readCodexAuthStatus,
readGitlabAuthStatus,
readGithubAuthStatus,
} from "./services/auth.js"
import { readAuthMenuSnapshot, runAuthMenuFlow } from "./services/auth-menu.js"
import { streamGitlabAuthLogin } from "./services/auth-gitlab-login-stream.js"
import { streamGithubAuthLogin } from "./services/auth-github-login-stream.js"
import { createAuthTerminalSession, deleteAuthTerminalSession } from "./services/auth-terminal-sessions.js"
import { streamCodexAuthLogin } from "./services/auth-codex-login-stream.js"
Expand Down Expand Up @@ -352,6 +358,8 @@ const readCreateProjectRequest = () => HttpServerRequest.schemaBodyJson(CreatePr
const readCreateFollowRequest = () => HttpServerRequest.schemaBodyJson(CreateFollowRequestSchema)
const readGithubAuthLoginRequest = () => HttpServerRequest.schemaBodyJson(GithubAuthLoginRequestSchema)
const readGithubAuthLogoutRequest = () => HttpServerRequest.schemaBodyJson(GithubAuthLogoutRequestSchema)
const readGitlabAuthLoginRequest = () => HttpServerRequest.schemaBodyJson(GitlabAuthLoginRequestSchema)
const readGitlabAuthLogoutRequest = () => HttpServerRequest.schemaBodyJson(GitlabAuthLogoutRequestSchema)
const readAuthMenuRequest = () => HttpServerRequest.schemaBodyJson(AuthMenuRequestSchema)
const readAuthTerminalSessionRequest = () => HttpServerRequest.schemaBodyJson(AuthTerminalSessionRequestSchema)
const readCodexAuthImportRequest = () => HttpServerRequest.schemaBodyJson(CodexAuthImportRequestSchema)
Expand Down Expand Up @@ -502,6 +510,13 @@ export const makeRouter = () => {
return yield* _(jsonResponse({ status }, 200))
}).pipe(Effect.catchAll(errorResponse))
),
HttpRouter.get(
"/auth/gitlab/status",
Effect.gen(function*(_) {
const status = yield* _(readGitlabAuthStatus())
return yield* _(jsonResponse({ status }, 200))
}).pipe(Effect.catchAll(errorResponse))
),
HttpRouter.get(
"/auth/menu",
Effect.gen(function*(_) {
Expand Down Expand Up @@ -531,6 +546,28 @@ export const makeRouter = () => {
return yield* _(jsonResponse({ ok: true, status }, 201))
}).pipe(Effect.catchAll(errorResponse))
),
HttpRouter.post(
"/auth/gitlab/login/stream",
Effect.gen(function*(_) {
const request = yield* _(readGitlabAuthLoginRequest())
const outputStream = yield* _(streamGitlabAuthLogin(request))
return HttpServerResponse.stream(outputStream, {
status: 200,
headers: {
"content-type": "text/plain; charset=utf-8",
"cache-control": "no-cache"
}
})
}).pipe(Effect.catchAll(errorResponse))
),
HttpRouter.post(
"/auth/gitlab/login",
Effect.gen(function*(_) {
const request = yield* _(readGitlabAuthLoginRequest())
const status = yield* _(loginGitlabAuth(request))
return yield* _(jsonResponse({ ok: true, status }, 201))
}).pipe(Effect.catchAll(errorResponse))
),
HttpRouter.post(
"/auth/menu",
Effect.gen(function*(_) {
Expand Down Expand Up @@ -575,6 +612,14 @@ export const makeRouter = () => {
return yield* _(jsonResponse({ ok: true, status }, 200))
}).pipe(Effect.catchAll(errorResponse))
),
HttpRouter.post(
"/auth/gitlab/logout",
Effect.gen(function*(_) {
const request = yield* _(readGitlabAuthLogoutRequest())
const status = yield* _(logoutGitlabAuth(request))
return yield* _(jsonResponse({ ok: true, status }, 200))
}).pipe(Effect.catchAll(errorResponse))
),
HttpRouter.get(
"/auth/codex/status",
Effect.gen(function*(_) {
Expand Down
Loading
Loading