Compare commits
4 commits
80b4028ec7
...
fc9035148c
Author | SHA1 | Date | |
---|---|---|---|
fc9035148c | |||
21a2b5aa26 | |||
61d17a4dcd | |||
7ba57c13ef |
3 changed files with 89 additions and 95 deletions
|
@ -1,11 +1,16 @@
|
|||
import { BaseApi } from "./base-api.ts";
|
||||
|
||||
export type Oauth2ApplicationCreateParams = {
|
||||
name: string,
|
||||
redirect_uris: string[],
|
||||
confidential_client?: boolean,
|
||||
}
|
||||
|
||||
export type Oauth2Application = {
|
||||
id: number,
|
||||
name: string,
|
||||
redirect_uris: string[],
|
||||
client_id: string,
|
||||
client_secret: string,
|
||||
confidential_client: boolean,
|
||||
/**
|
||||
* @format date-time
|
||||
|
@ -13,6 +18,10 @@ export type Oauth2Application = {
|
|||
created: string,
|
||||
}
|
||||
|
||||
export type Oauth2ApplicationResponse = {
|
||||
client_secret: string,
|
||||
} & Oauth2Application
|
||||
|
||||
export class OAuth2Api extends BaseApi {
|
||||
private token: string;
|
||||
|
||||
|
@ -21,17 +30,8 @@ export class OAuth2Api extends BaseApi {
|
|||
this.token = token;
|
||||
}
|
||||
|
||||
// Method to update token if needed later
|
||||
updateToken(token: string): void {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
async createOauth2Application(params: {
|
||||
name: string,
|
||||
redirect_uris: string[],
|
||||
confidential_client?: boolean,
|
||||
}): Promise<Oauth2Application | undefined> {
|
||||
return await this.request<Oauth2Application>(`/api/v1/user/applications/oauth2`, {
|
||||
async createOauth2Application(params: Oauth2ApplicationCreateParams): Promise<Oauth2ApplicationResponse> {
|
||||
return await this.request<Oauth2ApplicationResponse>(`/api/v1/user/applications/oauth2`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Authorization": `Bearer ${this.token}`,
|
||||
|
@ -41,7 +41,7 @@ export class OAuth2Api extends BaseApi {
|
|||
});
|
||||
}
|
||||
|
||||
async getOauth2Applications(): Promise<Oauth2Application[] | undefined> {
|
||||
async getOauth2Applications(): Promise<Oauth2Application[]> {
|
||||
return await this.request<Oauth2Application[]>(`/api/v1/user/applications/oauth2`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
|
@ -65,12 +65,8 @@ export class OAuth2Api extends BaseApi {
|
|||
});
|
||||
}
|
||||
|
||||
async updateOauth2Application(id: number, params: {
|
||||
name: string,
|
||||
redirect_uris: string[],
|
||||
confidential_client?: boolean,
|
||||
}): Promise<Oauth2Application | undefined> {
|
||||
return await this.request<Oauth2Application>(`/api/v1/user/applications/oauth2/${id}`, {
|
||||
async updateOauth2Application(id: number, params: Oauth2ApplicationCreateParams): Promise<Oauth2ApplicationResponse> {
|
||||
return await this.request<Oauth2ApplicationResponse>(`/api/v1/user/applications/oauth2/${id}`, {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Authorization": `Bearer ${this.token}`,
|
||||
|
|
66
app.ts
66
app.ts
|
@ -21,7 +21,7 @@ async function main() {
|
|||
.version("0.1.0")
|
||||
.description("Interactive client credentials generator for Forgejo.")
|
||||
.command("login", "Authenticate with Forgejo interactively")
|
||||
.action(async() => {
|
||||
.action(async () => {
|
||||
const username = await prompt("Enter your username: ");
|
||||
if (!username) {
|
||||
console.error("Username is required.");
|
||||
|
@ -89,7 +89,8 @@ async function main() {
|
|||
console.log("Logout successful! Credentials removed.");
|
||||
})
|
||||
.command("list, ls", "List all OAuth2 applications")
|
||||
.action(async () => {
|
||||
.option("--pretty, -p", "Pretty print the output")
|
||||
.action(async (opt) => {
|
||||
const credentials = await credentialManager.getCredentials();
|
||||
if (!credentials) return;
|
||||
|
||||
|
@ -102,14 +103,29 @@ async function main() {
|
|||
console.log("No OAuth2 applications found.");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("OAuth2 applications:");
|
||||
console.log(apps.map(prettyOauth2Application).join("\n\n"));
|
||||
if (opt.pretty) {
|
||||
console.log("OAuth2 applications:");
|
||||
console.log(apps.map(prettyOauth2Application).join("\n\n"));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
const maxNameLength = Math.max(...apps.map(app => app.name.length), 6);
|
||||
console.log(apps.map(app => [
|
||||
app.id.toString().padEnd(5),
|
||||
app.confidential_client ? "c" : "o",
|
||||
app.name.padStart(maxNameLength),
|
||||
app.client_id,
|
||||
app.redirect_uris.join(", "),
|
||||
].join(" ").trim()).join("\n"));
|
||||
}
|
||||
})
|
||||
.command("create", "Create new OAuth2 application")
|
||||
.action(async () => {
|
||||
const credentials = await credentialManager.getCredentials();
|
||||
if (!credentials) return;
|
||||
if (!credentials) {
|
||||
console.error("Credentials not found. Please login first.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create OAuth2Api with token
|
||||
const oauth2Api = new OAuth2Api(URL_BASE, credentials.token);
|
||||
|
@ -142,33 +158,28 @@ async function main() {
|
|||
await saveSecretKeys(path, app.client_id, app.client_secret);
|
||||
}
|
||||
})
|
||||
.command("delete", "Delete OAuth2 application")
|
||||
.action(async () => {
|
||||
.command("remove, rm", "Remove OAuth2 application")
|
||||
.arguments("<id:number>")
|
||||
.action(async (_opt, appId) => {
|
||||
const credentials = await credentialManager.getCredentials();
|
||||
if (!credentials) return;
|
||||
if (!credentials) {
|
||||
console.error("Credentials not found. Please login first.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create OAuth2Api with token
|
||||
const oauth2Api = new OAuth2Api(URL_BASE, credentials.token);
|
||||
|
||||
const id = await prompt("Enter the ID of the application to delete: ");
|
||||
if (!id) {
|
||||
console.error("ID is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
const appId = parseInt(id);
|
||||
if (isNaN(appId)) {
|
||||
console.error("ID must be a number.");
|
||||
return;
|
||||
}
|
||||
|
||||
await oauth2Api.deleteOauth2Application(appId);
|
||||
console.log("OAuth2 application deleted successfully!");
|
||||
})
|
||||
.command("update", "Update OAuth2 application")
|
||||
.action(async () => {
|
||||
const credentials = await credentialManager.getCredentials();
|
||||
if (!credentials) return;
|
||||
if (!credentials) {
|
||||
console.error("Credentials not found. Please login first.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create OAuth2Api with token
|
||||
const oauth2Api = new OAuth2Api(URL_BASE, credentials.token);
|
||||
|
@ -213,6 +224,17 @@ async function main() {
|
|||
await saveSecretKeys(path, app.client_id, app.client_secret);
|
||||
}
|
||||
})
|
||||
.command("fetch-config", "Fetch OpenID configuration")
|
||||
.action(async () => {
|
||||
const response = await fetch(`${URL_BASE}/.well-known/openid-configuration`);
|
||||
if (!response.ok) {
|
||||
console.error("Failed to fetch OpenID configuration:", response.statusText);
|
||||
return;
|
||||
}
|
||||
|
||||
const config = await response.json();
|
||||
console.log("OpenID Configuration:", JSON.stringify(config, null, 2));
|
||||
})
|
||||
.parse(Deno.args);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
|
|
24
types.ts
24
types.ts
|
@ -1,24 +0,0 @@
|
|||
export const URL_BASE = "https://git.monoid.top";
|
||||
export const TOKEN_NAME = "oauth2cli";
|
||||
export const CREDENTIALS_FILE = `${Deno.env.get("HOME") || ""}/.oauth2cli-forgejo`;
|
||||
|
||||
export type Token = {
|
||||
id: number,
|
||||
name: string,
|
||||
scopes: string[],
|
||||
sha1: string,
|
||||
token_last_eight: string,
|
||||
}
|
||||
|
||||
export type Oauth2Application = {
|
||||
id: number,
|
||||
name: string,
|
||||
redirect_uris: string[],
|
||||
client_id: string,
|
||||
client_secret: string,
|
||||
confidential_client: boolean,
|
||||
/**
|
||||
* @format date-time
|
||||
*/
|
||||
created: string,
|
||||
}
|
Loading…
Add table
Reference in a new issue