Compare commits

..

No commits in common. "fc9035148c7eec7383374fc36ea77dc8426056f7" and "80b4028ec73c731cedcff935e804dd65e3b728e0" have entirely different histories.

3 changed files with 95 additions and 89 deletions

View file

@ -1,16 +1,11 @@
import { BaseApi } from "./base-api.ts"; import { BaseApi } from "./base-api.ts";
export type Oauth2ApplicationCreateParams = {
name: string,
redirect_uris: string[],
confidential_client?: boolean,
}
export type Oauth2Application = { export type Oauth2Application = {
id: number, id: number,
name: string, name: string,
redirect_uris: string[], redirect_uris: string[],
client_id: string, client_id: string,
client_secret: string,
confidential_client: boolean, confidential_client: boolean,
/** /**
* @format date-time * @format date-time
@ -18,10 +13,6 @@ export type Oauth2Application = {
created: string, created: string,
} }
export type Oauth2ApplicationResponse = {
client_secret: string,
} & Oauth2Application
export class OAuth2Api extends BaseApi { export class OAuth2Api extends BaseApi {
private token: string; private token: string;
@ -30,8 +21,17 @@ export class OAuth2Api extends BaseApi {
this.token = token; this.token = token;
} }
async createOauth2Application(params: Oauth2ApplicationCreateParams): Promise<Oauth2ApplicationResponse> { // Method to update token if needed later
return await this.request<Oauth2ApplicationResponse>(`/api/v1/user/applications/oauth2`, { 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`, {
method: "POST", method: "POST",
headers: { headers: {
"Authorization": `Bearer ${this.token}`, "Authorization": `Bearer ${this.token}`,
@ -41,7 +41,7 @@ export class OAuth2Api extends BaseApi {
}); });
} }
async getOauth2Applications(): Promise<Oauth2Application[]> { async getOauth2Applications(): Promise<Oauth2Application[] | undefined> {
return await this.request<Oauth2Application[]>(`/api/v1/user/applications/oauth2`, { return await this.request<Oauth2Application[]>(`/api/v1/user/applications/oauth2`, {
method: "GET", method: "GET",
headers: { headers: {
@ -65,8 +65,12 @@ export class OAuth2Api extends BaseApi {
}); });
} }
async updateOauth2Application(id: number, params: Oauth2ApplicationCreateParams): Promise<Oauth2ApplicationResponse> { async updateOauth2Application(id: number, params: {
return await this.request<Oauth2ApplicationResponse>(`/api/v1/user/applications/oauth2/${id}`, { name: string,
redirect_uris: string[],
confidential_client?: boolean,
}): Promise<Oauth2Application | undefined> {
return await this.request<Oauth2Application>(`/api/v1/user/applications/oauth2/${id}`, {
method: "PATCH", method: "PATCH",
headers: { headers: {
"Authorization": `Bearer ${this.token}`, "Authorization": `Bearer ${this.token}`,

62
app.ts
View file

@ -21,7 +21,7 @@ async function main() {
.version("0.1.0") .version("0.1.0")
.description("Interactive client credentials generator for Forgejo.") .description("Interactive client credentials generator for Forgejo.")
.command("login", "Authenticate with Forgejo interactively") .command("login", "Authenticate with Forgejo interactively")
.action(async () => { .action(async() => {
const username = await prompt("Enter your username: "); const username = await prompt("Enter your username: ");
if (!username) { if (!username) {
console.error("Username is required."); console.error("Username is required.");
@ -89,8 +89,7 @@ async function main() {
console.log("Logout successful! Credentials removed."); console.log("Logout successful! Credentials removed.");
}) })
.command("list, ls", "List all OAuth2 applications") .command("list, ls", "List all OAuth2 applications")
.option("--pretty, -p", "Pretty print the output") .action(async () => {
.action(async (opt) => {
const credentials = await credentialManager.getCredentials(); const credentials = await credentialManager.getCredentials();
if (!credentials) return; if (!credentials) return;
@ -103,29 +102,14 @@ async function main() {
console.log("No OAuth2 applications found."); console.log("No OAuth2 applications found.");
return; return;
} }
if (opt.pretty) {
console.log("OAuth2 applications:"); console.log("OAuth2 applications:");
console.log(apps.map(prettyOauth2Application).join("\n\n")); 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") .command("create", "Create new OAuth2 application")
.action(async () => { .action(async () => {
const credentials = await credentialManager.getCredentials(); const credentials = await credentialManager.getCredentials();
if (!credentials) { if (!credentials) return;
console.error("Credentials not found. Please login first.");
return;
}
// Create OAuth2Api with token // Create OAuth2Api with token
const oauth2Api = new OAuth2Api(URL_BASE, credentials.token); const oauth2Api = new OAuth2Api(URL_BASE, credentials.token);
@ -158,28 +142,33 @@ async function main() {
await saveSecretKeys(path, app.client_id, app.client_secret); await saveSecretKeys(path, app.client_id, app.client_secret);
} }
}) })
.command("remove, rm", "Remove OAuth2 application") .command("delete", "Delete OAuth2 application")
.arguments("<id:number>") .action(async () => {
.action(async (_opt, appId) => {
const credentials = await credentialManager.getCredentials(); const credentials = await credentialManager.getCredentials();
if (!credentials) { if (!credentials) return;
console.error("Credentials not found. Please login first.");
return;
}
// Create OAuth2Api with token // Create OAuth2Api with token
const oauth2Api = new OAuth2Api(URL_BASE, credentials.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); await oauth2Api.deleteOauth2Application(appId);
console.log("OAuth2 application deleted successfully!"); console.log("OAuth2 application deleted successfully!");
}) })
.command("update", "Update OAuth2 application") .command("update", "Update OAuth2 application")
.action(async () => { .action(async () => {
const credentials = await credentialManager.getCredentials(); const credentials = await credentialManager.getCredentials();
if (!credentials) { if (!credentials) return;
console.error("Credentials not found. Please login first.");
return;
}
// Create OAuth2Api with token // Create OAuth2Api with token
const oauth2Api = new OAuth2Api(URL_BASE, credentials.token); const oauth2Api = new OAuth2Api(URL_BASE, credentials.token);
@ -224,17 +213,6 @@ async function main() {
await saveSecretKeys(path, app.client_id, app.client_secret); 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); .parse(Deno.args);
} catch (error) { } catch (error) {
if (error instanceof Error) { if (error instanceof Error) {

24
types.ts Normal file
View file

@ -0,0 +1,24 @@
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,
}