Skip to content

Commit

Permalink
fix(runtime): fix proxy policy loading problem
Browse files Browse the repository at this point in the history
  • Loading branch information
maslow committed Feb 16, 2023
1 parent f24db6f commit 8127519
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 49 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"casdoor",
"chakra",
"Chakra",
"chatgpt",
"clsx",
"coll",
"compat",
Expand Down
4 changes: 2 additions & 2 deletions cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "laf-cli",
"version": "1.0.0-alpha.1",
"version": "1.0.0-alpha.2",
"description": "",
"main": "dist/main.js",
"bin": {
Expand Down
23 changes: 23 additions & 0 deletions runtimes/nodejs/env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

# get & check appid from $1
APPID=$1
if [ -z "$APPID" ]; then
echo "Usage: $0 <appid>"
exit 1
fi

NAMESPACE=${APPID}

# get server pod name
POD_NAME=$(kubectl get pods --namespace ${NAMESPACE} -l "laf.dev/appid=${APPID}" -o jsonpath="{.items[0].metadata.name}")

echo "POD_NAME: ${POD_NAME}"

# kubectl exec to get the pod env
kubectl exec -it ${POD_NAME} -n ${NAMESPACE} -- env > .env

# replace 'mongo.laf-system.svc.cluster.local' with '127.0.0.1'
sed -i '' 's/mongodb-0.mongo.laf-system.svc.cluster.local/127.0.0.1/g' .env

# replace 'w=majority' with 'w=majority&directConnection=true'
sed -i '' 's/w=majority/w=majority\&directConnection=true/g' .env
2 changes: 1 addition & 1 deletion runtimes/nodejs/src/handler/db-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export async function handleDatabaseProxy(req: IRequest, res: Response) {
const policy_name = req.params?.policy

// get corresponding policy
const policy_comp = PolicyAgent.get(policy_name)
const policy_comp = await PolicyAgent.get(policy_name)
if (!policy_comp) {
return res.status(404).send('Policy Not Found')
}
Expand Down
2 changes: 1 addition & 1 deletion runtimes/nodejs/src/handler/debug-func.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export async function handleDebugFunction(req: IRequest, res: Response) {
}
const auth = parseToken(token) || null
if (auth?.type !== 'develop') {
return res.status(403).send('permission denied: invalid debug token')
return res.status(403).send('permission denied: invalid develop token')
}

// get func_data from header
Expand Down
16 changes: 0 additions & 16 deletions runtimes/nodejs/src/handler/publish.ts

This file was deleted.

13 changes: 8 additions & 5 deletions runtimes/nodejs/src/handler/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { handleDatabaseProxy } from './db-proxy'
import { handlePackageTypings } from './typings'
import { generateUUID } from '../support/utils'
import { handleInvokeFunction } from './invoke-func'
import { handlePublishPolicies } from './publish'


/**
* multer uploader config
Expand All @@ -23,17 +23,20 @@ const uploader = multer({
const { ext } = path.parse(file.originalname)
cb(null, generateUUID() + ext)
}
})
}),
fileFilter(_req, file, callback) {
// solve the problem of garbled unicode names
file.originalname = Buffer.from(file.originalname, 'latin1').toString('utf8')
callback(null, true)
},
})

export const router = Router()


router.post('/proxy/:policy', handleDatabaseProxy)
router.get('/typing/package', handlePackageTypings)
router.get('/_/typing/package', handlePackageTypings)
router.get('/_/healthz', (_req, res) => res.status(200).send('ok'))
router.post('/_/publish/functions', (_req, res) => res.status(400).send('TODO'))
router.post('/_/publish/policies', handlePublishPolicies)

/**
* Invoke cloud function through HTTP request.
Expand Down
5 changes: 5 additions & 0 deletions runtimes/nodejs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import * as express from 'express'
import * as cors from 'cors'

import { parseToken, splitBearerToken } from './support/token'
import Config from './config'
Expand All @@ -22,6 +23,10 @@ import './support/cloud-sdk'

const app = express()

if (process.env.NODE_ENV === 'development') {
app.use(cors())
}

app.use(express.json({ limit: Config.REQUEST_LIMIT_SIZE }) as any)
app.use(
express.urlencoded({
Expand Down
81 changes: 59 additions & 22 deletions runtimes/nodejs/src/support/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@
* @Author: Maslow<wangfugen@126.com>
* @Date: 2021-08-04 00:31:53
* @LastEditTime: 2021-11-05 13:52:52
* @Description:
* @Description:
*/

import assert = require("assert")
import { Params, Policy } from "database-proxy"
import { logger } from "./logger"
import { CloudFunction } from "./function-engine"
import { DatabaseAgent } from "../db"
import { Constants } from "../constants"
import { generateUUID } from "./utils"

import assert = require('assert')
import { Params, Policy } from 'database-proxy'
import { logger } from './logger'
import { CloudFunction } from './function-engine'
import { DatabaseAgent } from '../db'
import { Constants } from '../constants'
import { generateUUID } from './utils'

export type InjectionGetter = (payload: any, params: Params) => Promise<any>

Expand All @@ -23,6 +22,7 @@ export interface PolicyComposition {
name: string
policy: Policy
injector_func: InjectionGetter
cached_at?: number
}

/**
Expand All @@ -38,7 +38,6 @@ export interface PolicyDataStruct {
updated_at: number
}


/**
* Policy Agent class
* - managing multiple policies
Expand All @@ -47,7 +46,6 @@ export interface PolicyDataStruct {
export class PolicyAgent {
private static _data: Map<string, PolicyComposition> = new Map()


public static async set(name: string, data: PolicyDataStruct) {
assert(data, 'policy data cannot be empty')

Expand All @@ -56,19 +54,42 @@ export class PolicyAgent {

const injector_func = await this.getInjector(data.injector)

this._data.set(name, { name, policy, injector_func })
const ret = { name, policy, injector_func, cached_at: Date.now() }
this._data.set(name, ret)
return ret
}

public static get(name: string) {
return this._data.get(name)
}
public static async get(name: string) {
// get from cache
const cached = this._data.get(name)

// TODO: consider a better cache policy ?
if (cached && Date.now() - cached.cached_at < 1000 * 5) {
return cached
}

// clear the stale cache
if (cached) {
this._data.delete(name)
}

// load from database
const data = await this.loadPolicy(name)
if (!data) {
return null
}

// cache & return
return this.set(name, data)
}

public static clear() {
this._data.clear()
}

private static async getInjector(injectorName: string): Promise<InjectionGetter> {
private static async getInjector(
injectorName: string,
): Promise<InjectionGetter> {
if (!injectorName) {
return defaultInjectionGetter
}
Expand All @@ -80,30 +101,46 @@ export class PolicyAgent {
const func = new CloudFunction(func_data)
const ret = await func.invoke({
__function_name: func.name,
requestId: generateUUID()
requestId: generateUUID(),
})
assert(typeof ret.data === 'function', 'function type needed')

return ret.data
} catch (error) {
logger.error(`failed to get injector by cloud function: ${injectorName}, now using default injector`, error)
logger.error(
`failed to get injector by cloud function: ${injectorName}, now using default injector`,
error,
)
return defaultInjectionGetter
}
}


/**
* Get all access policies
*/
public static async loadPolicies() {
const db = DatabaseAgent.db
const docs = await db.collection(Constants.policy_collection)
const docs = await db
.collection(Constants.policy_collection)
.find<PolicyDataStruct>({})
.toArray()

return docs
}

/**
* Get a policy by name
* @param name
* @returns
*/
public static async loadPolicy(name: string) {
const db = DatabaseAgent.db
const doc = await db
.collection(Constants.policy_collection)
.findOne<PolicyDataStruct>({ name })

return doc
}

/**
* Applying access policies
Expand All @@ -125,6 +162,6 @@ export class PolicyAgent {
async function defaultInjectionGetter(auth: any, _params: Params) {
auth = auth || {}
return {
...auth
...auth,
}
}
}
2 changes: 1 addition & 1 deletion web/src/components/Editor/typesResolve/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async function loadPackageTypings(packageName: string) {
const { currentApp } = useGlobalStore.getState();
const url = `//${currentApp?.domain?.domain}`;
const res = await axios({
url: `${url}/typing/package?packageName=${packageName}`,
url: `${url}/_/typing/package?packageName=${packageName}`,
method: "GET",
});

Expand Down

0 comments on commit 8127519

Please sign in to comment.