Skip to content

Commit

Permalink
Support oauth token endpoint, add wiki verification support, fix bug …
Browse files Browse the repository at this point in the history
…with toggleable heading type (#438)
  • Loading branch information
rhart92 authored Aug 11, 2023
1 parent 34dd778 commit 0877d34
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 6 deletions.
3 changes: 2 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"sendgrid",
"blackmad",
"octokit",
"printf"
"printf",
"is_toggleable"
],
// flagWords - list of words to be always considered incorrect
// This is useful for offensive words and common spelling errors.
Expand Down
55 changes: 53 additions & 2 deletions src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ import {
ListCommentsParameters,
ListCommentsResponse,
listComments,
OauthTokenResponse,
OauthTokenParameters,
oauthToken,
} from "./api-endpoints"
import nodeFetch from "node-fetch"
import {
Expand All @@ -98,7 +101,17 @@ export interface RequestParameters {
method: Method
query?: QueryParams
body?: Record<string, unknown>
auth?: string
/**
* To authenticate using public API token, `auth` should be passed as a
* string. If you are trying to complete OAuth, then `auth` should be an object
* containing your integration's client ID and secret.
*/
auth?:
| string
| {
client_id: string
client_secret: string
}
}

export default class Client {
Expand Down Expand Up @@ -165,8 +178,23 @@ export default class Client {
}
}

// Allow both client ID / client secret based auth as well as token based auth.
let authorizationHeader: Record<string, string>
if (typeof auth === "object") {
// Client ID and secret based auth is **ONLY** supported when using the
// `/oauth/token` endpoint. If this is the case, handle formatting the
// authorization header as required by `Basic` auth.
const unencodedCredential = `${auth.client_id}:${auth.client_secret}`
const encodedCredential =
Buffer.from(unencodedCredential).toString("base64")
authorizationHeader = { authorization: `Basic ${encodedCredential}` }
} else {
// Otherwise format authorization header as `Bearer` token auth.
authorizationHeader = this.authAsHeaders(auth)
}

const headers: Record<string, string> = {
...this.authAsHeaders(auth),
...authorizationHeader,
"Notion-Version": this.#notionVersion,
"user-agent": this.#userAgent,
}
Expand Down Expand Up @@ -525,6 +553,29 @@ export default class Client {
})
}

public readonly oauth = {
/**
* Get token
*/
token: (
args: OauthTokenParameters & {
client_id: string
client_secret: string
}
): Promise<OauthTokenResponse> => {
return this.request<OauthTokenResponse>({
path: oauthToken.path(),
method: oauthToken.method,
query: pick(args, oauthToken.queryParams),
body: pick(args, oauthToken.bodyParams),
auth: {
client_id: args.client_id,
client_secret: args.client_secret,
},
})
},
}

/**
* Emits a log message to the console.
*
Expand Down
132 changes: 129 additions & 3 deletions src/api-endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,57 @@ type FormulaPropertyResponse =
| NumberFormulaPropertyResponse
| BooleanFormulaPropertyResponse

type VerificationPropertyUnverifiedResponse = {
state: "unverified"
date: null
verified_by: null
}

type VerificationPropertyResponse = {
state: "verified" | "expired"
date: DateResponse | null
verified_by:
| { id: IdRequest }
| null
| {
person: { email?: string }
id: IdRequest
type?: "person"
name?: string | null
avatar_url?: string | null
object?: "user"
}
| null
| {
bot:
| EmptyObject
| {
owner:
| {
type: "user"
user:
| {
type: "person"
person: { email: string }
name: string | null
avatar_url: string | null
id: IdRequest
object: "user"
}
| PartialUserObjectResponse
}
| { type: "workspace"; workspace: true }
workspace_name: string | null
}
id: IdRequest
type?: "bot"
name?: string | null
avatar_url?: string | null
object?: "user"
}
| null
}

type AnnotationResponse = {
bold: boolean
italic: boolean
Expand Down Expand Up @@ -4405,6 +4456,15 @@ export type PageObjectResponse = {
unique_id: { prefix: string | null; number: number | null }
id: string
}
| {
type: "verification"
verification:
| VerificationPropertyUnverifiedResponse
| null
| VerificationPropertyResponse
| null
id: string
}
| { type: "title"; title: Array<RichTextItemResponse>; id: string }
| { type: "rich_text"; rich_text: Array<RichTextItemResponse>; id: string }
| {
Expand Down Expand Up @@ -4790,7 +4850,11 @@ export type ParagraphBlockObjectResponse = {

export type Heading1BlockObjectResponse = {
type: "heading_1"
heading_1: { rich_text: Array<RichTextItemResponse>; color: ApiColor }
heading_1: {
rich_text: Array<RichTextItemResponse>
color: ApiColor
is_toggleable: boolean
}
parent:
| { type: "database_id"; database_id: string }
| { type: "page_id"; page_id: string }
Expand All @@ -4808,7 +4872,11 @@ export type Heading1BlockObjectResponse = {

export type Heading2BlockObjectResponse = {
type: "heading_2"
heading_2: { rich_text: Array<RichTextItemResponse>; color: ApiColor }
heading_2: {
rich_text: Array<RichTextItemResponse>
color: ApiColor
is_toggleable: boolean
}
parent:
| { type: "database_id"; database_id: string }
| { type: "page_id"; page_id: string }
Expand All @@ -4826,7 +4894,11 @@ export type Heading2BlockObjectResponse = {

export type Heading3BlockObjectResponse = {
type: "heading_3"
heading_3: { rich_text: Array<RichTextItemResponse>; color: ApiColor }
heading_3: {
rich_text: Array<RichTextItemResponse>
color: ApiColor
is_toggleable: boolean
}
parent:
| { type: "database_id"; database_id: string }
| { type: "page_id"; page_id: string }
Expand Down Expand Up @@ -5688,6 +5760,17 @@ export type UniqueIdPropertyItemObjectResponse = {
id: string
}

export type VerificationPropertyItemObjectResponse = {
type: "verification"
verification:
| VerificationPropertyUnverifiedResponse
| null
| VerificationPropertyResponse
| null
object: "property_item"
id: string
}

export type TitlePropertyItemObjectResponse = {
type: "title"
title: RichTextItemResponse
Expand Down Expand Up @@ -5749,6 +5832,7 @@ export type PropertyItemObjectResponse =
| LastEditedTimePropertyItemObjectResponse
| FormulaPropertyItemObjectResponse
| UniqueIdPropertyItemObjectResponse
| VerificationPropertyItemObjectResponse
| TitlePropertyItemObjectResponse
| RichTextPropertyItemObjectResponse
| PeoplePropertyItemObjectResponse
Expand Down Expand Up @@ -10645,3 +10729,45 @@ export const listComments = {
bodyParams: [],
path: (): string => `comments`,
} as const

type OauthTokenBodyParameters = {
grant_type: string
code: string
redirect_uri?: string
external_account?: { key: string; name: string }
}

export type OauthTokenParameters = OauthTokenBodyParameters

export type OauthTokenResponse = {
access_token: string
token_type: "bearer"
bot_id: string
workspace_icon: string | null
workspace_name: string | null
workspace_id: string
owner:
| {
type: "user"
user:
| {
type: "person"
person: { email: string }
name: string | null
avatar_url: string | null
id: IdRequest
object: "user"
}
| PartialUserObjectResponse
}
| { type: "workspace"; workspace: true }
duplicated_template_id: string | null
}

export const oauthToken = {
method: "post",
pathParams: [],
queryParams: [],
bodyParams: ["grant_type", "code", "redirect_uri", "external_account"],
path: (): string => `oauth/token`,
} as const

0 comments on commit 0877d34

Please sign in to comment.