config husky
This commit is contained in:
parent
2544ce8031
commit
34e2a94fce
|
@ -1,9 +1,9 @@
|
|||
import { authClient } from "../helpers/auth_client";
|
||||
import { generators } from 'openid-client';
|
||||
import { configKeys } from "..";
|
||||
import { authClient } from '../helpers/auth_client'
|
||||
import { generators } from 'openid-client'
|
||||
import { configKeys } from '..'
|
||||
|
||||
const code_verifier = generators.codeVerifier();
|
||||
const code_challenge = generators.codeChallenge(code_verifier);
|
||||
const code_verifier = generators.codeVerifier()
|
||||
const code_challenge = generators.codeChallenge(code_verifier)
|
||||
|
||||
export default () => {
|
||||
const authurl = authClient.authorizationUrl({
|
||||
|
@ -12,14 +12,11 @@ export default () => {
|
|||
code_challenge_method: 'S256',
|
||||
client_id: configKeys.KEYCLOAK_CLIENT_ID,
|
||||
redirect_uri: configKeys.KEYCLOAK_REDIRECT_URI,
|
||||
});
|
||||
})
|
||||
|
||||
return {
|
||||
authurl,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
code_challenge,
|
||||
code_verifier,
|
||||
}
|
||||
export { code_challenge, code_verifier }
|
||||
|
|
|
@ -1,32 +1,37 @@
|
|||
import { NextFunction, Response } from "express";
|
||||
import {authClient} from "../helpers/auth_client";
|
||||
import { ModRequest } from "../types";
|
||||
import { CustomError } from "../libs/error";
|
||||
import { NextFunction, Response } from 'express'
|
||||
import { authClient } from '../helpers/auth_client'
|
||||
import { ModRequest } from '../types'
|
||||
import { CustomError } from '../libs/error'
|
||||
|
||||
const middleware = async (req: ModRequest | any, res: Response, next: NextFunction) => {
|
||||
const middleware = async (
|
||||
req: ModRequest | any,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
try {
|
||||
const authHeader = req.headers?.authorization?.split(' ');
|
||||
const authHeader = req.headers?.authorization?.split(' ')
|
||||
if (!authHeader) {
|
||||
throw new Error("No authorization header");
|
||||
throw new Error('No authorization header')
|
||||
}
|
||||
const token : string = authHeader[1];
|
||||
const token: string = authHeader[1]
|
||||
const user = await authClient.userinfo(token, {
|
||||
method: 'GET',
|
||||
tokenType: 'Bearer',
|
||||
params: {
|
||||
access_token: token
|
||||
access_token: token,
|
||||
},
|
||||
via: 'header'
|
||||
});
|
||||
req.user = user;
|
||||
next();
|
||||
}
|
||||
catch (err) {
|
||||
next(new CustomError({
|
||||
message: "Invalid token",
|
||||
statusCode: 401
|
||||
}))
|
||||
via: 'header',
|
||||
})
|
||||
req.user = user
|
||||
next()
|
||||
} catch (err) {
|
||||
next(
|
||||
new CustomError({
|
||||
message: 'Invalid token',
|
||||
statusCode: 401,
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default middleware
|
||||
export default middleware
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {authClient} from "../helpers/auth_client";
|
||||
import { authClient } from '../helpers/auth_client'
|
||||
import { code_verifier } from './check'
|
||||
|
||||
export default async (session_state: string, code: string) => {
|
||||
return authClient.callback(
|
||||
'http://localhost:4038/auth/signin/callback',
|
||||
{ code_verifier, code, session_state, expires_in: "1d" },
|
||||
{ code_verifier, code, session_state, expires_in: '1d' },
|
||||
{ code_verifier }
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import fs from 'fs'
|
||||
import { parse as parseFile } from 'envfile'
|
||||
import { Issuer } from 'openid-client';
|
||||
import { Issuer } from 'openid-client'
|
||||
|
||||
const keyCloakIssuer : Issuer = await Issuer.discover(process.env.KEYCLOAK_AUTH_SERVER_URL!);
|
||||
console.log('🔐 Connected to Keycloak');
|
||||
const keyCloakIssuer: Issuer = await Issuer.discover(
|
||||
process.env.KEYCLOAK_AUTH_SERVER_URL!
|
||||
)
|
||||
console.log('🔐 Connected to Keycloak')
|
||||
|
||||
type IconfigStore = 'development' | 'production'
|
||||
|
||||
|
@ -48,7 +50,7 @@ export interface IConfigKeys {
|
|||
export default class ConfigStoreFactory {
|
||||
public configStoreType: IconfigStore
|
||||
|
||||
constructor(isProd: boolean = false) {
|
||||
constructor(isProd = false) {
|
||||
if (isProd) {
|
||||
this.configStoreType = 'production'
|
||||
} else {
|
||||
|
@ -57,8 +59,8 @@ export default class ConfigStoreFactory {
|
|||
}
|
||||
|
||||
public async getConfigStore() {
|
||||
const publicKEY = fs.readFileSync('./jwtRS256.key', 'utf8');
|
||||
const privateKEY = fs.readFileSync('./jwtRS256.key.pub', 'utf8');
|
||||
const publicKEY = fs.readFileSync('./jwtRS256.key', 'utf8')
|
||||
const privateKEY = fs.readFileSync('./jwtRS256.key.pub', 'utf8')
|
||||
if (this.configStoreType === 'development') {
|
||||
const envContent = await fs.readFileSync(`./.env`, 'utf8')
|
||||
const env: Partial<IConfigKeys> = await parseFile(envContent)
|
||||
|
@ -73,8 +75,8 @@ export default class ConfigStoreFactory {
|
|||
)
|
||||
reqEnvContent = reqEnvContent.replaceAll('=', '')
|
||||
reqEnvContent = reqEnvContent.split('\n')
|
||||
let missingKeys: string[] = []
|
||||
let env: Partial<IConfigKeys> = {}
|
||||
const missingKeys: string[] = []
|
||||
const env: Partial<IConfigKeys> = {}
|
||||
env.PUBLIC_KEY = publicKEY
|
||||
env.PRIVATE_KEY = privateKEY
|
||||
env.KEYCLOAK_ISSUER = keyCloakIssuer
|
||||
|
|
|
@ -11,11 +11,14 @@ export default class AuthController {
|
|||
}
|
||||
|
||||
public callback = async (req: Request, res: Response) => {
|
||||
const { session_state, code } = req.query as { session_state: string, code: string}
|
||||
const { session_state, code } = req.query as {
|
||||
session_state: string
|
||||
code: string
|
||||
}
|
||||
res.send(makeResponse(await verify(session_state, code)))
|
||||
}
|
||||
|
||||
public me = (req: ModRequest, res: Response) => {
|
||||
res.send(makeResponse(req.user))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,10 @@ import { Request, Response } from 'express'
|
|||
|
||||
export default class MastodonController extends MastodonService {
|
||||
public fetchMastodonProfile = async (req: Request, res: Response) => {
|
||||
try{
|
||||
try {
|
||||
const data = await this.getMastodonProfile()
|
||||
return res.send(makeResponse(data))
|
||||
}
|
||||
catch (err: any){
|
||||
} catch (err: any) {
|
||||
res.send(makeResponse(err.message, {}, 'Failed', true))
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +16,7 @@ export default class MastodonController extends MastodonService {
|
|||
try {
|
||||
const data = await this.getMastodonStatuses()
|
||||
return res.send(makeResponse(data))
|
||||
}
|
||||
catch (err: any) {
|
||||
} catch (err: any) {
|
||||
res.send(makeResponse(err.message, {}, 'Failed', true))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { configKeys } from "..";
|
||||
import { configKeys } from '..'
|
||||
|
||||
const { KEYCLOAK_ISSUER } = configKeys
|
||||
|
||||
|
@ -7,7 +7,9 @@ const authConfig = {
|
|||
'auth-server-url': configKeys.KEYCLOAK_AUTH_SERVER_URL,
|
||||
'ssl-required': 'all',
|
||||
resource: configKeys.KEYCLOAK_CLIENT_ID,
|
||||
credentials: { 'secret-jwt': { secret: configKeys.KEYCLOAK_CLIENT_SECRET } },
|
||||
credentials: {
|
||||
'secret-jwt': { secret: configKeys.KEYCLOAK_CLIENT_SECRET },
|
||||
},
|
||||
'confidential-port': 0,
|
||||
redirect_uri: configKeys.KEYCLOAK_REDIRECT_URI,
|
||||
client_secret: configKeys.KEYCLOAK_CLIENT_SECRET,
|
||||
|
@ -16,4 +18,4 @@ const authConfig = {
|
|||
|
||||
const authClient = new KEYCLOAK_ISSUER.Client(authConfig)
|
||||
|
||||
export { authClient }
|
||||
export { authClient }
|
||||
|
|
|
@ -5,30 +5,30 @@ import morgan from 'morgan'
|
|||
import helmet from 'helmet'
|
||||
|
||||
import { hgqlInit } from './helpers'
|
||||
import cacheClient from './helpers/cache.factory';
|
||||
import cacheClient from './helpers/cache.factory'
|
||||
import routes from './routes'
|
||||
import { errorHandler, notFoundHandler } from './libs'
|
||||
import pkg from './package.json' assert { type: 'json' }
|
||||
import configStore, { IConfigKeys } from './configs';
|
||||
import configStore, { IConfigKeys } from './configs'
|
||||
|
||||
export const app: express.Application = express()
|
||||
|
||||
console.log('🚀', '@b68/api', 'v' + pkg.version)
|
||||
|
||||
hgqlInit()
|
||||
cacheClient.init();
|
||||
cacheClient.init()
|
||||
|
||||
const isDev: boolean = process.env.NODE_ENV == 'production'
|
||||
console.log(isDev ? '🚀 Production Mode' : '👷 Development Mode')
|
||||
const configs = new configStore(isDev)
|
||||
const configKeys: IConfigKeys = await configs.getConfigStore() as IConfigKeys
|
||||
const configKeys: IConfigKeys = (await configs.getConfigStore()) as IConfigKeys
|
||||
|
||||
app.use(cors())
|
||||
app.use(helmet())
|
||||
app.use(morgan('dev'))
|
||||
app.use(express.json())
|
||||
app.use(express.urlencoded({ extended: true, limit: '50mb' }))
|
||||
app.set('view engine', 'ejs');
|
||||
app.set('view engine', 'ejs')
|
||||
|
||||
console.log('☄ ', 'Base Route', '/')
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ router.get('/signin/callback', authController.callback)
|
|||
|
||||
router.get('/me', middleware, authController.me as any)
|
||||
|
||||
router.get('/', function(req, res) {
|
||||
res.render('pages/auth');
|
||||
});
|
||||
router.get('/', function (req, res) {
|
||||
res.render('pages/auth')
|
||||
})
|
||||
|
||||
export default router
|
||||
|
|
|
@ -2,11 +2,10 @@ import { Router } from 'express'
|
|||
|
||||
const router = Router()
|
||||
|
||||
router.use('/health',
|
||||
(req, res) => {
|
||||
router.use('/health', (req, res) => {
|
||||
return res.status(200).json({
|
||||
status: "OK",
|
||||
app: "B68 API",
|
||||
status: 'OK',
|
||||
app: 'B68 API',
|
||||
request_ip: req.ip,
|
||||
uptime: process.uptime(),
|
||||
hrtime: process.hrtime(),
|
||||
|
|
|
@ -49,12 +49,12 @@ baseDir = path.resolve(baseDir)
|
|||
|
||||
loadRoutes(baseDir)
|
||||
|
||||
router.get('/', function(req, res) {
|
||||
res.render('pages/index');
|
||||
});
|
||||
router.get('/', function (req, res) {
|
||||
res.render('pages/index')
|
||||
})
|
||||
|
||||
router.get('/favicon.ico', function(req, res) {
|
||||
res.sendFile(path.join(__dirname, '../public', 'favicon.ico'));
|
||||
});
|
||||
router.get('/favicon.ico', function (req, res) {
|
||||
res.sendFile(path.join(__dirname, '../public', 'favicon.ico'))
|
||||
})
|
||||
|
||||
export default router
|
||||
|
|
|
@ -12,7 +12,7 @@ export default class MastodonService {
|
|||
const { data } = await axiosInstance.get(
|
||||
'https://fosstodon.org/api/v1/accounts/109612266657666903/statuses',
|
||||
{
|
||||
timeout: 10000
|
||||
timeout: 10000,
|
||||
}
|
||||
)
|
||||
return data
|
||||
|
|
|
@ -10,4 +10,4 @@ export interface PaginationType {
|
|||
|
||||
export interface ModRequest extends Request {
|
||||
user: any
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue