Implement Github authentication to show repositories list (#45)

* Use react-oauth-popup for github authentication popup

* Fetch auth token and use in app to fetch list of repositories

* Get client id and secret from config

* Use GitHub search API for fetching repos

* Use debounce for searching repos and projects
This commit is contained in:
2024-02-01 11:37:57 +05:30
committed by Ashwin Phatak
parent 2f8d21baf5
commit e1e9a7063e
21 changed files with 647 additions and 86 deletions
+4
View File
@@ -5,3 +5,7 @@
[database]
dbPath = "db/snowball"
[githubOauth]
clientId = ""
clientSecret = ""
+2 -1
View File
@@ -5,6 +5,7 @@
"dependencies": {
"@graphql-tools/schema": "^10.0.2",
"@graphql-tools/utils": "^10.0.12",
"@octokit/oauth-app": "^6.1.0",
"@types/debug": "^4.1.5",
"@types/express": "^4.17.21",
"@types/node": "^20.11.0",
@@ -36,8 +37,8 @@
"@types/fs-extra": "^11.0.4",
"@typescript-eslint/eslint-plugin": "^6.18.1",
"@typescript-eslint/parser": "^6.18.1",
"copyfiles": "^2.4.1",
"better-sqlite3": "^9.2.2",
"copyfiles": "^2.4.1",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-semistandard": "^15.0.1",
+6
View File
@@ -8,7 +8,13 @@ export interface DatabaseConfig {
dbPath: string;
}
export interface GithubOauthConfig {
clientId: string;
clientSecret: string;
}
export interface Config {
server: ServerConfig;
database: DatabaseConfig;
githubOauth: GithubOauthConfig;
}
+11 -2
View File
@@ -3,6 +3,8 @@ import debug from 'debug';
import fs from 'fs';
import path from 'path';
import { OAuthApp } from '@octokit/oauth-app';
import { Database } from './database';
import { createAndStartServer } from './server';
import { createResolvers } from './resolvers';
@@ -14,13 +16,20 @@ const log = debug('snowball:server');
export const main = async (): Promise<void> => {
// TODO: get config path using cli
const { server, database } = await getConfig<Config>(DEFAULT_CONFIG_FILE_PATH);
const { server, database, githubOauth } = await getConfig<Config>(DEFAULT_CONFIG_FILE_PATH);
const db = new Database(database);
await db.init();
// TODO: Move to Service class
const app = new OAuthApp({
clientType: 'oauth-app',
clientId: githubOauth.clientId,
clientSecret: githubOauth.clientSecret
});
const typeDefs = fs.readFileSync(path.join(__dirname, 'schema.gql')).toString();
const resolvers = await createResolvers(db);
const resolvers = await createResolvers(db, app);
await createAndStartServer(typeDefs, resolvers, server);
};
+14 -1
View File
@@ -1,13 +1,15 @@
import debug from 'debug';
import assert from 'assert';
import { OAuthApp } from '@octokit/oauth-app';
import { Database } from './database';
import { deploymentToGqlType, projectMemberToGqlType, projectToGqlType, environmentVariableToGqlType, isUserOwner } from './utils';
import { Environment } from './entity/Deployment';
const log = debug('snowball:database');
export const createResolvers = async (db: Database): Promise<any> => {
export const createResolvers = async (db: Database, app: OAuthApp): Promise<any> => {
return {
Query: {
// TODO: add custom type for context
@@ -203,6 +205,17 @@ export const createResolvers = async (db: Database): Promise<any> => {
log(err);
return false;
}
},
authenticateGithub: async (_: any, { code }: { code: string }) => {
// TOO: Move to Service class
const { authentication: { token } } = await app.createToken({
code
});
// TODO: Save bearer token in DB for user
return { token };
}
}
};
+5
View File
@@ -126,6 +126,10 @@ type Query {
domains(projectId: String!): [Domain!]
}
type AuthResult {
token: String!
}
type Mutation {
removeMember(memberId: String!): Boolean!
addEnvironmentVariables(projectId: String!, environmentVariables: [AddEnvironmentVariableInput!]): Boolean!
@@ -136,6 +140,7 @@ type Mutation {
rollbackDeployment(projectId: String!, deploymentId: String!): Boolean!
addDomain(projectId: String!, domainDetails: AddDomainInput!): Boolean!
updateDomain(domainId: String!, domainDetails: UpdateDomainInput!): Boolean!
authenticateGithub(code: String!): AuthResult!
}
input AddEnvironmentVariableInput {