store token_expires_at in DB
This commit is contained in:
parent
6b7e6a5c01
commit
0f52823461
@ -47,10 +47,8 @@ authRouter.get("/callback", async (req: Request, res: Response) => {
|
||||
|
||||
try {
|
||||
const forge = createForge(forgeType);
|
||||
const { accessToken } = await forge.exchangeCodeForToken(
|
||||
code,
|
||||
codeVerifier,
|
||||
);
|
||||
const { accessToken, accessTokenExpiresAt } =
|
||||
await forge.exchangeCodeForToken(code, codeVerifier);
|
||||
|
||||
const forgeUser = await forge.getUserInfo(accessToken);
|
||||
|
||||
@ -58,6 +56,7 @@ authRouter.get("/callback", async (req: Request, res: Response) => {
|
||||
forgeType,
|
||||
forgeUser.id.toString(),
|
||||
accessToken,
|
||||
accessTokenExpiresAt,
|
||||
);
|
||||
|
||||
req.session.userId = internalUser.user_id;
|
||||
|
||||
@ -33,13 +33,17 @@ export class GiteaForge implements Forge {
|
||||
async exchangeCodeForToken(
|
||||
code: string,
|
||||
codeVerifier: string,
|
||||
): Promise<{ accessToken: string }> {
|
||||
): Promise<{ accessToken: string; accessTokenExpiresAt?: Date }> {
|
||||
try {
|
||||
const tokens = await this.gitea.validateAuthorizationCode(
|
||||
code,
|
||||
codeVerifier,
|
||||
);
|
||||
return { accessToken: tokens.accessToken() };
|
||||
|
||||
return {
|
||||
accessToken: tokens.accessToken(),
|
||||
accessTokenExpiresAt: tokens.accessTokenExpiresAt(),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Failed to exchange code for token:", error);
|
||||
throw new Error("Failed to exchange authorisation code for token");
|
||||
|
||||
@ -7,7 +7,10 @@ export interface Forge {
|
||||
exchangeCodeForToken(
|
||||
code: string,
|
||||
codeVerifier: string,
|
||||
): Promise<{ accessToken: string }>;
|
||||
): Promise<{
|
||||
accessToken: string;
|
||||
accessTokenExpiresAt?: Date;
|
||||
}>;
|
||||
|
||||
getUserInfo(accessToken: string): Promise<ForgeUser>;
|
||||
|
||||
|
||||
347
server/src/types/openapi.d.ts
vendored
347
server/src/types/openapi.d.ts
vendored
@ -1,162 +1,209 @@
|
||||
import type {
|
||||
Context,
|
||||
UnknownParams,
|
||||
} from 'openapi-backend';
|
||||
import type { Context, UnknownParams } from "openapi-backend";
|
||||
|
||||
declare namespace Components {
|
||||
namespace Schemas {
|
||||
export interface Error {
|
||||
/**
|
||||
* Error message
|
||||
* example:
|
||||
* Repository not found
|
||||
*/
|
||||
error: string;
|
||||
/**
|
||||
* Error code for programmatic handling
|
||||
* example:
|
||||
* REPO_NOT_FOUND
|
||||
*/
|
||||
code: string;
|
||||
/**
|
||||
* Additional error details
|
||||
*/
|
||||
details?: {
|
||||
[name: string]: any;
|
||||
};
|
||||
}
|
||||
export interface Repository {
|
||||
id?: number;
|
||||
/**
|
||||
* example:
|
||||
* molci
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* example:
|
||||
* gitea
|
||||
*/
|
||||
forge?: "gitea";
|
||||
}
|
||||
export interface RepositoryConfig {
|
||||
repo?: Repository;
|
||||
configured_at?: string; // date-time
|
||||
webhook_id?: string;
|
||||
}
|
||||
export interface RepositoryConfigInput {
|
||||
settings: {
|
||||
[name: string]: any;
|
||||
};
|
||||
}
|
||||
}
|
||||
namespace Schemas {
|
||||
export interface Error {
|
||||
/**
|
||||
* Error message
|
||||
* example:
|
||||
* Repository not found
|
||||
*/
|
||||
error: string;
|
||||
/**
|
||||
* Error code for programmatic handling
|
||||
* example:
|
||||
* REPO_NOT_FOUND
|
||||
*/
|
||||
code: string;
|
||||
/**
|
||||
* Additional error details
|
||||
*/
|
||||
details?: {
|
||||
[name: string]: any;
|
||||
};
|
||||
}
|
||||
export interface Repository {
|
||||
id?: number;
|
||||
/**
|
||||
* example:
|
||||
* molci
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* example:
|
||||
* gitea
|
||||
*/
|
||||
forge?: "gitea";
|
||||
}
|
||||
export interface RepositoryConfig {
|
||||
repo?: Repository;
|
||||
configured_at?: string; // date-time
|
||||
webhook_id?: string;
|
||||
}
|
||||
export interface RepositoryConfigInput {
|
||||
settings: {
|
||||
[name: string]: any;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
declare namespace Paths {
|
||||
namespace ConfigureRepo {
|
||||
namespace Parameters {
|
||||
export type Id = number;
|
||||
}
|
||||
export interface PathParameters {
|
||||
id: Parameters.Id;
|
||||
}
|
||||
export type RequestBody = Components.Schemas.RepositoryConfigInput;
|
||||
namespace Responses {
|
||||
export type $200 = Components.Schemas.RepositoryConfig;
|
||||
export type $400 = Components.Schemas.Error;
|
||||
export type $401 = Components.Schemas.Error;
|
||||
export type $404 = Components.Schemas.Error;
|
||||
export type $500 = Components.Schemas.Error;
|
||||
}
|
||||
}
|
||||
namespace GetRepo {
|
||||
namespace Parameters {
|
||||
export type Id = string;
|
||||
}
|
||||
export interface PathParameters {
|
||||
id: Parameters.Id;
|
||||
}
|
||||
namespace Responses {
|
||||
export type $200 = Components.Schemas.RepositoryConfig;
|
||||
export type $400 = Components.Schemas.Error;
|
||||
export type $401 = Components.Schemas.Error;
|
||||
export type $404 = Components.Schemas.Error;
|
||||
export type $500 = Components.Schemas.Error;
|
||||
}
|
||||
}
|
||||
namespace ListAvailableRepos {
|
||||
namespace Responses {
|
||||
export type $200 = Components.Schemas.Repository[];
|
||||
export type $401 = Components.Schemas.Error;
|
||||
export type $403 = Components.Schemas.Error;
|
||||
export type $500 = Components.Schemas.Error;
|
||||
}
|
||||
}
|
||||
namespace ListConfiguredRepos {
|
||||
namespace Responses {
|
||||
export type $200 = Components.Schemas.RepositoryConfig[];
|
||||
export type $401 = Components.Schemas.Error;
|
||||
export type $500 = Components.Schemas.Error;
|
||||
}
|
||||
}
|
||||
namespace ConfigureRepo {
|
||||
namespace Parameters {
|
||||
export type Id = number;
|
||||
}
|
||||
export interface PathParameters {
|
||||
id: Parameters.Id;
|
||||
}
|
||||
export type RequestBody = Components.Schemas.RepositoryConfigInput;
|
||||
namespace Responses {
|
||||
export type $200 = Components.Schemas.RepositoryConfig;
|
||||
export type $400 = Components.Schemas.Error;
|
||||
export type $401 = Components.Schemas.Error;
|
||||
export type $404 = Components.Schemas.Error;
|
||||
export type $500 = Components.Schemas.Error;
|
||||
}
|
||||
}
|
||||
namespace GetRepo {
|
||||
namespace Parameters {
|
||||
export type Id = string;
|
||||
}
|
||||
export interface PathParameters {
|
||||
id: Parameters.Id;
|
||||
}
|
||||
namespace Responses {
|
||||
export type $200 = Components.Schemas.RepositoryConfig;
|
||||
export type $400 = Components.Schemas.Error;
|
||||
export type $401 = Components.Schemas.Error;
|
||||
export type $404 = Components.Schemas.Error;
|
||||
export type $500 = Components.Schemas.Error;
|
||||
}
|
||||
}
|
||||
namespace ListAvailableRepos {
|
||||
namespace Responses {
|
||||
export type $200 = Components.Schemas.Repository[];
|
||||
export type $401 = Components.Schemas.Error;
|
||||
export type $403 = Components.Schemas.Error;
|
||||
export type $500 = Components.Schemas.Error;
|
||||
}
|
||||
}
|
||||
namespace ListConfiguredRepos {
|
||||
namespace Responses {
|
||||
export type $200 = Components.Schemas.RepositoryConfig[];
|
||||
export type $401 = Components.Schemas.Error;
|
||||
export type $500 = Components.Schemas.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export interface Operations {
|
||||
/**
|
||||
* GET /repos/available
|
||||
*/
|
||||
['listAvailableRepos']: {
|
||||
requestBody: any;
|
||||
params: UnknownParams;
|
||||
query: UnknownParams;
|
||||
headers: UnknownParams;
|
||||
cookies: UnknownParams;
|
||||
context: Context<any, UnknownParams, UnknownParams, UnknownParams, UnknownParams>;
|
||||
response: Paths.ListAvailableRepos.Responses.$200 | Paths.ListAvailableRepos.Responses.$401 | Paths.ListAvailableRepos.Responses.$403 | Paths.ListAvailableRepos.Responses.$500;
|
||||
}
|
||||
/**
|
||||
* GET /repos/configured
|
||||
*/
|
||||
['listConfiguredRepos']: {
|
||||
requestBody: any;
|
||||
params: UnknownParams;
|
||||
query: UnknownParams;
|
||||
headers: UnknownParams;
|
||||
cookies: UnknownParams;
|
||||
context: Context<any, UnknownParams, UnknownParams, UnknownParams, UnknownParams>;
|
||||
response: Paths.ListConfiguredRepos.Responses.$200 | Paths.ListConfiguredRepos.Responses.$401 | Paths.ListConfiguredRepos.Responses.$500;
|
||||
}
|
||||
/**
|
||||
* GET /repo/{id}
|
||||
*/
|
||||
['getRepo']: {
|
||||
requestBody: any;
|
||||
params: Paths.GetRepo.PathParameters;
|
||||
query: UnknownParams;
|
||||
headers: UnknownParams;
|
||||
cookies: UnknownParams;
|
||||
context: Context<any, Paths.GetRepo.PathParameters, UnknownParams, UnknownParams, UnknownParams>;
|
||||
response: Paths.GetRepo.Responses.$200 | Paths.GetRepo.Responses.$400 | Paths.GetRepo.Responses.$401 | Paths.GetRepo.Responses.$404 | Paths.GetRepo.Responses.$500;
|
||||
}
|
||||
/**
|
||||
* PUT /repo/{id}
|
||||
*/
|
||||
['configureRepo']: {
|
||||
requestBody: Paths.ConfigureRepo.RequestBody;
|
||||
params: Paths.ConfigureRepo.PathParameters;
|
||||
query: UnknownParams;
|
||||
headers: UnknownParams;
|
||||
cookies: UnknownParams;
|
||||
context: Context<Paths.ConfigureRepo.RequestBody, Paths.ConfigureRepo.PathParameters, UnknownParams, UnknownParams, UnknownParams>;
|
||||
response: Paths.ConfigureRepo.Responses.$200 | Paths.ConfigureRepo.Responses.$400 | Paths.ConfigureRepo.Responses.$401 | Paths.ConfigureRepo.Responses.$404 | Paths.ConfigureRepo.Responses.$500;
|
||||
}
|
||||
/**
|
||||
* GET /repos/available
|
||||
*/
|
||||
["listAvailableRepos"]: {
|
||||
requestBody: any;
|
||||
params: UnknownParams;
|
||||
query: UnknownParams;
|
||||
headers: UnknownParams;
|
||||
cookies: UnknownParams;
|
||||
context: Context<
|
||||
any,
|
||||
UnknownParams,
|
||||
UnknownParams,
|
||||
UnknownParams,
|
||||
UnknownParams
|
||||
>;
|
||||
response:
|
||||
| Paths.ListAvailableRepos.Responses.$200
|
||||
| Paths.ListAvailableRepos.Responses.$401
|
||||
| Paths.ListAvailableRepos.Responses.$403
|
||||
| Paths.ListAvailableRepos.Responses.$500;
|
||||
};
|
||||
/**
|
||||
* GET /repos/configured
|
||||
*/
|
||||
["listConfiguredRepos"]: {
|
||||
requestBody: any;
|
||||
params: UnknownParams;
|
||||
query: UnknownParams;
|
||||
headers: UnknownParams;
|
||||
cookies: UnknownParams;
|
||||
context: Context<
|
||||
any,
|
||||
UnknownParams,
|
||||
UnknownParams,
|
||||
UnknownParams,
|
||||
UnknownParams
|
||||
>;
|
||||
response:
|
||||
| Paths.ListConfiguredRepos.Responses.$200
|
||||
| Paths.ListConfiguredRepos.Responses.$401
|
||||
| Paths.ListConfiguredRepos.Responses.$500;
|
||||
};
|
||||
/**
|
||||
* GET /repo/{id}
|
||||
*/
|
||||
["getRepo"]: {
|
||||
requestBody: any;
|
||||
params: Paths.GetRepo.PathParameters;
|
||||
query: UnknownParams;
|
||||
headers: UnknownParams;
|
||||
cookies: UnknownParams;
|
||||
context: Context<
|
||||
any,
|
||||
Paths.GetRepo.PathParameters,
|
||||
UnknownParams,
|
||||
UnknownParams,
|
||||
UnknownParams
|
||||
>;
|
||||
response:
|
||||
| Paths.GetRepo.Responses.$200
|
||||
| Paths.GetRepo.Responses.$400
|
||||
| Paths.GetRepo.Responses.$401
|
||||
| Paths.GetRepo.Responses.$404
|
||||
| Paths.GetRepo.Responses.$500;
|
||||
};
|
||||
/**
|
||||
* PUT /repo/{id}
|
||||
*/
|
||||
["configureRepo"]: {
|
||||
requestBody: Paths.ConfigureRepo.RequestBody;
|
||||
params: Paths.ConfigureRepo.PathParameters;
|
||||
query: UnknownParams;
|
||||
headers: UnknownParams;
|
||||
cookies: UnknownParams;
|
||||
context: Context<
|
||||
Paths.ConfigureRepo.RequestBody,
|
||||
Paths.ConfigureRepo.PathParameters,
|
||||
UnknownParams,
|
||||
UnknownParams,
|
||||
UnknownParams
|
||||
>;
|
||||
response:
|
||||
| Paths.ConfigureRepo.Responses.$200
|
||||
| Paths.ConfigureRepo.Responses.$400
|
||||
| Paths.ConfigureRepo.Responses.$401
|
||||
| Paths.ConfigureRepo.Responses.$404
|
||||
| Paths.ConfigureRepo.Responses.$500;
|
||||
};
|
||||
}
|
||||
|
||||
export type OperationContext<operationId extends keyof Operations> = Operations[operationId]["context"];
|
||||
export type OperationResponse<operationId extends keyof Operations> = Operations[operationId]["response"];
|
||||
export type HandlerResponse<ResponseBody, ResponseModel = Record<string, any>> = ResponseModel & { _t?: ResponseBody };
|
||||
export type OperationHandlerResponse<operationId extends keyof Operations> = HandlerResponse<OperationResponse<operationId>>;
|
||||
export type OperationHandler<operationId extends keyof Operations, HandlerArgs extends unknown[] = unknown[]> = (...params: [OperationContext<operationId>, ...HandlerArgs]) => Promise<OperationHandlerResponse<operationId>>;
|
||||
|
||||
export type OperationContext<operationId extends keyof Operations> =
|
||||
Operations[operationId]["context"];
|
||||
export type OperationResponse<operationId extends keyof Operations> =
|
||||
Operations[operationId]["response"];
|
||||
export type HandlerResponse<
|
||||
ResponseBody,
|
||||
ResponseModel = Record<string, any>,
|
||||
> = ResponseModel & { _t?: ResponseBody };
|
||||
export type OperationHandlerResponse<operationId extends keyof Operations> =
|
||||
HandlerResponse<OperationResponse<operationId>>;
|
||||
export type OperationHandler<
|
||||
operationId extends keyof Operations,
|
||||
HandlerArgs extends unknown[] = unknown[],
|
||||
> = (
|
||||
...params: [OperationContext<operationId>, ...HandlerArgs]
|
||||
) => Promise<OperationHandlerResponse<operationId>>;
|
||||
|
||||
export type Error = Components.Schemas.Error;
|
||||
export type Repository = Components.Schemas.Repository;
|
||||
|
||||
@ -66,16 +66,18 @@ export const getOrCreateUser = async (
|
||||
): Promise<User> => {
|
||||
const forgeId = resolveForgeId(forgeType);
|
||||
|
||||
let user = await findUserByForge(forgeId, forgeUserId);
|
||||
if (!user) {
|
||||
user = await insertUser(
|
||||
forgeId,
|
||||
forgeUserId,
|
||||
access_token,
|
||||
token_expires_at,
|
||||
);
|
||||
}
|
||||
return user;
|
||||
const result = await pool.query(
|
||||
`INSERT INTO users (forge_id, forge_user_id, access_token, token_expires_at)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
ON CONFLICT (forge_id, forge_user_id)
|
||||
DO UPDATE SET
|
||||
access_token = EXCLUDED.access_token,
|
||||
token_expires_at = EXCLUDED.token_expires_at
|
||||
RETURNING *`,
|
||||
[forgeId, forgeUserId, access_token, token_expires_at],
|
||||
);
|
||||
|
||||
return result.rows[0];
|
||||
};
|
||||
|
||||
export const getAccessToken = async (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user