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