Skip to content

Commit

Permalink
Merge branch 'main' into feat/time
Browse files Browse the repository at this point in the history
  • Loading branch information
puria authored Feb 29, 2024
2 parents 5f85158 + 703f979 commit b6fe8ab
Show file tree
Hide file tree
Showing 10 changed files with 318 additions and 11 deletions.
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "node_modules/@lerna-lite/cli/schemas/lerna-schema.json",
"version": "1.19.0",
"version": "1.20.0",
"command": {
"publish": {
"conventionalCommits": true
Expand Down
32 changes: 32 additions & 0 deletions pkg/helpers/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@slangroom/helpers",
"version": "1.20.0",
"dependencies": {
"@slangroom/core": "workspace:*",
"@slangroom/shared": "workspace:*",
"@types/lodash": "^4.14.202",
"lodash": "^4.17.21"
},
"repository": "https://github.com/dyne/slangroom",
"license": "AGPL-3.0-only",
"type": "module",
"main": "./build/esm/src/index.js",
"types": "./build/esm/src/index.d.ts",
"exports": {
".": {
"import": {
"types": "./build/esm/src/index.d.ts",
"default": "./build/esm/src/index.js"
}
},
"./*": {
"import": {
"types": "./build/esm/src/*.d.ts",
"default": "./build/esm/src/*.js"
}
}
},
"publishConfig": {
"access": "public"
}
}
2 changes: 2 additions & 0 deletions pkg/helpers/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '@slangroom/helpers/plugin';

49 changes: 49 additions & 0 deletions pkg/helpers/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Plugin } from '@slangroom/core';
import _ from 'lodash';

const p = new Plugin()

class HelperError extends Error {
constructor(e: Error) {
super(e.message)
this.name = 'Slangroom @slangroom/helper Error'
}
}

// export const assign = p.new(['target', 'source'], 'manipulate and assign', async (ctx) => {
// const target = ctx.fetch('target');
// const source = ctx.fetch('source');
// try {
// return ctx.pass(_.assign(target as {}, source as {}));
// } catch (e) {
// throw new HelperError(e);
// }
// });

// export const omit = p.new(['object', 'properties'], 'manipulate and omit', async (ctx) => {
// const properties = ctx.fetch('properties');
// const obj = ctx.fetch('object');
// try {
// return ctx.pass(_.omit(obj as {}, properties as string[]));
// } catch (e) {
// throw new HelperError(e);
// }
// });

export const pick = p.new(['object', 'properties'], 'manipulate and pick', async (ctx) => {
const properties = ctx.fetch('properties') as string[] | string;
const obj = ctx.fetch('object') as {};
try {
const manipulated = _.pick(obj, properties);
if (Object.keys(manipulated).length === 0) {
throw new Error(`MANIPULATION ERRROR: \nNone of the properties \n\n ${JSON.stringify(properties)} \n\n exist in the object: \n\n ${JSON.stringify(obj, null, 3)}`);
}
return ctx.pass(manipulated);
} catch (e) {
throw new HelperError(e);
}
});

export const helpers = p


192 changes: 192 additions & 0 deletions pkg/helpers/test/pick.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import { Slangroom } from '@slangroom/core';
import { helpers } from '@slangroom/helpers';
import test from 'ava';

const expected = {
r: {
a: 'b',
c: {
d: {
e: '42',
},
},
},
}

test('@slangroom/helpers 😆 pick object', async (t) => {
const picked = `Rule unknown ignore
Given I send object 'complex_object' and send properties 'props' and manipulate and pick and output into 'r'
Given I have a 'string dictionary' named 'complex_object'
Given I have a 'string dictionary' named 'r'
Then print 'r'
`;

const slangroom = new Slangroom(helpers);
const res = await slangroom.execute(picked, {
data: {
props: ["a", "c.d"],
complex_object: {
"a": "b",
"c": {
"d": {
"e": 42
},
"f": "g"
}
}
},
});
t.deepEqual(res.result, expected, res.logs)
});

test('@slangroom/helpers 😆 pick object with params not in order', async (t) => {
const picked = `Rule unknown ignore
Given I send properties 'props' and send object 'complex_object' and manipulate and pick and output into 'r'
Given I have a 'string dictionary' named 'complex_object'
Given I have a 'string dictionary' named 'r'
Then print 'r'
`;

const slangroom = new Slangroom(helpers);
const res = await slangroom.execute(picked, {
data: {
props: ["a", "c.d"],
complex_object: {
"a": "b",
"c": {
"d": {
"e": 42
},
"f": "g"
}
}
},
});
t.deepEqual(res.result, expected, res.logs)
});


test('@slangroom/helpers 😆 pick object with one string params ', async (t) => {
const picked = `Rule unknown ignore
Given I send properties 'props' and send object 'complex_object' and manipulate and pick and output into 'r'
Given I have a 'string dictionary' named 'complex_object'
Given I have a 'string dictionary' named 'r'
Then print 'r'
`;

const slangroom = new Slangroom(helpers);
const res = await slangroom.execute(picked, {
data: {
props: "a",
complex_object: {
"a": "b",
"c": {
"d": {
"e": 42
},
"f": "g"
}
}
},
});
t.deepEqual(res.result, { r: { a: 'b' } }, res.logs)
});

test('@slangroom/helpers 😆 pick object with one string as an array of one element', async (t) => {
const picked = `Rule unknown ignore
Given I send properties 'props' and send object 'complex_object' and manipulate and pick and output into 'r'
Given I have a 'string dictionary' named 'complex_object'
Given I have a 'string dictionary' named 'r'
Then print 'r'
`;

const slangroom = new Slangroom(helpers);
const res = await slangroom.execute(picked, {
data: {
props: ["a"],
complex_object: {
"a": "b",
"c": {
"d": {
"e": 42
},
"f": "g"
}
}
},
});
t.deepEqual(res.result, { r: { a: 'b' } }, res.logs)
});
test('@slangroom/helpers 😆 pick handle fuzzy input', async (t) => {
const picked = `Rule unknown ignore
Given I send properties 'props' and send object 'complex_object' and manipulate and pick and output into 'r'
Given I have a 'string dictionary' named 'complex_object'
Given I have a 'string dictionary' named 'r'
Then print 'r'
`;

const slangroom = new Slangroom(helpers);
const res = await slangroom.execute(picked, {
data: {
props: ["a", "c.d", "random", 123, null, {}],
complex_object: {
"a": "b",
"c": {
"d": {
"e": 42
},
"f": "g"
},
"random": "value",
"123": 123,
"null": null,
"object": {}
}
},
});
const reuslt = { ...expected.r, random: "value", 123: "123" }
t.deepEqual(res.result, { r: reuslt }, res.logs);
});

test('@slangroom/helpers 😆 pick breaks when not found', async (t) => {
const picked = `Rule unknown ignore
Given I send properties 'props' and send object 'complex_object' and manipulate and pick and output into 'r'
Given I have a 'string dictionary' named 'complex_object'
Given I have a 'string dictionary' named 'r'
Then print 'r'
`;

const slangroom = new Slangroom(helpers);
const fn = slangroom.execute(picked, {
data: {
props: "a", // wrong type
complex_object: expected
},
});
const error = await t.throwsAsync(fn);
t.is((error as Error).message, `MANIPULATION ERRROR:
None of the properties
"a"
exist in the object:
{
"r": {
"a": "b",
"c": {
"d": {
"e": "42"
}
}
}
}`);
});

1 change: 1 addition & 0 deletions pkg/helpers/tsconfig.json
12 changes: 6 additions & 6 deletions pkg/oauth/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export class InMemoryCache implements AuthorizationCodeModel {

const codeSaved: AuthorizationCode = {
authorizationCode: code['authorizationCode'],
expiresAt: new Date(code['expiresAt']),
expiresAt: new Date(code['expiresAt'] * 1000),
redirectUri: code['redirectUri'],
client: code['client'],
user: code['user'],
Expand All @@ -112,7 +112,7 @@ export class InMemoryCache implements AuthorizationCodeModel {

var keys = Object.keys(code);
keys.forEach((key: string) => {
if(!codeSaved[key]) {
if (!codeSaved[key]) {
codeSaved[key] = code[key];
}
});
Expand Down Expand Up @@ -244,7 +244,7 @@ export class InMemoryCache implements AuthorizationCodeModel {
//TODO: problem with authorization_details
var keys = Object.keys(token);
keys.forEach((key: string) => {
if(!tokenSaved[key]) {
if (!tokenSaved[key]) {
tokenSaved[key] = token[key];
}
});
Expand All @@ -261,14 +261,14 @@ export class InMemoryCache implements AuthorizationCodeModel {
* the input string is set as the audience parameter.
*/

async createServerJWS(clientId: string){
async createServerJWS(clientId: string) {
if (this.serverData.jwk == null) throw Error("Missing server private JWK");
let privateKey = await importJWK(this.serverData.jwk);
let alg = this.serverData.jwk.alg || 'ES256';

const jws = new SignJWT({ sub: randomBytes(20).toString('hex') })
.setProtectedHeader({ alg: alg })
.setIssuedAt(Date.now())
.setIssuedAt(Math.round(Date.now() / 1000))
.setIssuer(this.serverData.url)
.setAudience(clientId)
.setExpirationTime('1h')
Expand Down Expand Up @@ -302,7 +302,7 @@ export class InMemoryCache implements AuthorizationCodeModel {
typ: 'dpop+jwt',
alg: 'ES256',
htm: request.method,
iat: new Date().getTime() - FIVE_MIN
iat: Math.round(Date.now() / 1000) - FIVE_MIN
};

const header = decodeProtectedHeader(dpop);
Expand Down
18 changes: 15 additions & 3 deletions pkg/oauth/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,13 @@ export const createToken = p.new(
//we remove the client and user object from the token
const token: JsonableObject = {
accessToken: res_token.accessToken,
accessTokenExpiresAt: res_token.accessTokenExpiresAt!.toString(),
accessTokenExpiresAt: Math.round(res_token.accessTokenExpiresAt!.getTime()/ 1000),
authorizationCode: res_token['authorizationCode'],
c_nonce: res_token['c_nonce'],
c_nonce_expires_in: res_token['c_nonce_expires_in'],
jkt: res_token['jkt'],
refreshToken: res_token.refreshToken!,
refreshTokenExpiresAt: res_token.refreshTokenExpiresAt!.toString(),
refreshTokenExpiresAt: Math.round(res_token.refreshTokenExpiresAt!.getTime()/ 1000),
scope: res_token.scope!,
};

Expand Down Expand Up @@ -164,8 +164,20 @@ export const createAuthorizationCode = p.new(
if (!cl) {
throw Error('Client is not valid');
}
const res_authCode = await server.authorize(request, response);
const authCode : JsonableObject = {
authorizationCode: res_authCode.authorizationCode,
client: res_authCode.client,
expiresAt: Math.round(res_authCode.expiresAt.getTime()/ 1000),
redirectUri: res_authCode.redirectUri,
user: res_authCode.user
}
if(res_authCode.codeChallenge) authCode['codeChallenge'] = res_authCode.codeChallenge;
if(res_authCode.codeChallengeMethod) authCode['codeChallengeMethod'] = res_authCode.codeChallengeMethod;
if(res_authCode.scope) authCode['scope'] = res_authCode.scope;
if(res_authCode['resource']) authCode['resource'] = res_authCode['resource'];

return ctx.pass(await server.authorize(request, response));
return ctx.pass(authCode);
},
);

Expand Down
2 changes: 1 addition & 1 deletion pkg/oauth/test/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ async function create_dpop_proof() {
crv: 'P-256',
},
})
.setIssuedAt(Date.now())
.setIssuedAt(Math.round(Date.now() / 1000))
.sign(privateKey);
return dpop;
}
Expand Down
Loading

0 comments on commit b6fe8ab

Please sign in to comment.