@amplication/plugin-auth-jwt
Advanced tools
Comparing version 1.4.1 to 1.4.2
{ | ||
"name": "@amplication/plugin-auth-jwt", | ||
"version": "1.4.1", | ||
"version": "1.4.2", | ||
"description": "set jwt as provider for Amplication build", | ||
@@ -15,5 +15,6 @@ "main": "dist/index.js", | ||
"devDependencies": { | ||
"@amplication/code-gen-types": "^2.0.4", | ||
"@babel/parser": "^7.18.11", | ||
"@babel/types": "^7.18.10", | ||
"@amplication/code-gen-types": "^2.0.12", | ||
"@amplication/code-gen-utils": "^0.0.6", | ||
"@babel/parser": "^7.23.0", | ||
"@babel/types": "^7.23.0", | ||
"@nestjs/common": "^9.0.9", | ||
@@ -23,21 +24,21 @@ "@nestjs/core": "^9.0.9", | ||
"@nestjs/passport": "^9.0.0", | ||
"@types/lodash": "^4.14.182", | ||
"@types/lodash": "^4.14.199", | ||
"@types/node": "^18.0.0", | ||
"@types/normalize-path": "^3.0.0", | ||
"@typescript-eslint/eslint-plugin": "^5.33.0", | ||
"@typescript-eslint/parser": "^5.33.0", | ||
"@typescript-eslint/eslint-plugin": "^6.7.5", | ||
"@typescript-eslint/parser": "^6.7.5", | ||
"babylon": "^6.18.0", | ||
"copy-webpack-plugin": "^11.0.0", | ||
"eslint": "^8.21.0", | ||
"jest-mock-extended": "^2.0.7", | ||
"eslint": "^8.51.0", | ||
"jest-mock-extended": "^3.0.5", | ||
"lodash": "^4.17.21", | ||
"passport-jwt": "^4.0.1", | ||
"prettier": "^2.8.7", | ||
"rimraf": "^5.0.1", | ||
"ts-loader": "^9.4.2", | ||
"typescript": "^4.9.3", | ||
"webpack": "^5.75.0", | ||
"webpack-cli": "^5.0.1", | ||
"prettier": "^3.0.3", | ||
"recast": "^0.20.5", | ||
"@amplication/code-gen-utils": "^0.0.5", | ||
"babylon": "^6.18.0" | ||
"rimraf": "^5.0.5", | ||
"ts-loader": "^9.5.0", | ||
"typescript": "^5.2.2", | ||
"webpack": "^5.88.2", | ||
"webpack-cli": "^5.1.4" | ||
} | ||
} |
187
src/index.ts
import { | ||
AmplicationPlugin, | ||
CreateAdminUIParams, | ||
CreateEntityServiceBaseParams, | ||
CreateEntityServiceParams, | ||
CreateServerAuthParams, | ||
DsgContext, | ||
EntityField, | ||
Events, | ||
@@ -17,2 +20,17 @@ ModuleMap, | ||
} from "./core"; | ||
import { addIdentifierToConstructorSuperCall, addImports, addInjectableDependency, awaitExpression, getClassDeclarationById, importNames, interpolate, logicalExpression, memberExpression } from "./util/ast"; | ||
import { builders, namedTypes } from "ast-types"; | ||
import { relativeImportPath } from "./util/module"; | ||
import { isPasswordField } from "./util/field"; | ||
const ARGS_ID = builders.identifier("args"); | ||
const PASSWORD_FIELD_ASYNC_METHODS = new Set(["create", "update"]); | ||
const DATA_ID = builders.identifier("data"); | ||
const PASSWORD_SERVICE_ID = builders.identifier("PasswordService"); | ||
const PASSWORD_SERVICE_MEMBER_ID = builders.identifier("passwordService"); | ||
const HASH_MEMBER_EXPRESSION = memberExpression`this.${PASSWORD_SERVICE_MEMBER_ID}.hash`; | ||
const TRANSFORM_STRING_FIELD_UPDATE_INPUT_ID = builders.identifier( | ||
"transformStringFieldUpdateInput" | ||
); | ||
class JwtAuthPlugin implements AmplicationPlugin { | ||
@@ -28,2 +46,8 @@ register(): Events { | ||
}, | ||
CreateEntityService: { | ||
before: this.beforeCreateEntityService, | ||
}, | ||
CreateEntityServiceBase: { | ||
before: this.beforeCreateEntityServiceBase, | ||
}, | ||
}; | ||
@@ -82,4 +106,167 @@ } | ||
} | ||
beforeCreateEntityService( | ||
context: DsgContext, | ||
eventParams: CreateEntityServiceParams | ||
) { | ||
const { template, serviceId, entityName, templateMapping } = eventParams; | ||
const modulePath = `${context.serverDirectories.srcDirectory}/${entityName}/${entityName}.service.ts`; | ||
const passwordFields = JwtAuthPlugin.getPasswordFields( | ||
context, | ||
eventParams.entityName | ||
); | ||
if (!passwordFields?.length) return eventParams; | ||
interpolate(template, templateMapping); | ||
//if there are any password fields, add imports, injection, and pass service to super | ||
if (passwordFields.length) { | ||
const classDeclaration = getClassDeclarationById(template, serviceId); | ||
addInjectableDependency( | ||
classDeclaration, | ||
PASSWORD_SERVICE_MEMBER_ID.name, | ||
PASSWORD_SERVICE_ID, | ||
"protected" | ||
); | ||
addIdentifierToConstructorSuperCall(template, PASSWORD_SERVICE_MEMBER_ID); | ||
for (const member of classDeclaration.body.body) { | ||
if ( | ||
namedTypes.ClassMethod.check(member) && | ||
namedTypes.Identifier.check(member.key) && | ||
PASSWORD_FIELD_ASYNC_METHODS.has(member.key.name) | ||
) { | ||
member.async = true; | ||
} | ||
} | ||
//add the password service | ||
addImports(template, [ | ||
importNames( | ||
[PASSWORD_SERVICE_ID], | ||
relativeImportPath( | ||
modulePath, | ||
`${context.serverDirectories.srcDirectory}/auth/password.service.ts` | ||
) | ||
), | ||
]); | ||
} | ||
return eventParams; | ||
} | ||
beforeCreateEntityServiceBase( | ||
context: DsgContext, | ||
eventParams: CreateEntityServiceBaseParams | ||
) { | ||
const { template, serviceBaseId, entityName, entity, templateMapping } = | ||
eventParams; | ||
const { serverDirectories } = context; | ||
const passwordFields = entity.fields.filter(isPasswordField); | ||
if (!passwordFields?.length) return eventParams; | ||
templateMapping["CREATE_ARGS_MAPPING"] = | ||
JwtAuthPlugin.createMutationDataMapping( | ||
passwordFields.map((field) => { | ||
const fieldId = builders.identifier(field.name); | ||
return builders.objectProperty( | ||
fieldId, | ||
awaitExpression`await ${HASH_MEMBER_EXPRESSION}(${ARGS_ID}.${DATA_ID}.${fieldId})` | ||
); | ||
}) | ||
); | ||
templateMapping["UPDATE_ARGS_MAPPING"] = | ||
JwtAuthPlugin.createMutationDataMapping( | ||
passwordFields.map((field) => { | ||
const fieldId = builders.identifier(field.name); | ||
const valueMemberExpression = memberExpression`${ARGS_ID}.${DATA_ID}.${fieldId}`; | ||
return builders.objectProperty( | ||
fieldId, | ||
logicalExpression`${valueMemberExpression} && await ${TRANSFORM_STRING_FIELD_UPDATE_INPUT_ID}( | ||
${ARGS_ID}.${DATA_ID}.${fieldId}, | ||
(password) => ${HASH_MEMBER_EXPRESSION}(password) | ||
)` | ||
); | ||
}) | ||
); | ||
interpolate(template, eventParams.templateMapping); | ||
const classDeclaration = getClassDeclarationById(template, serviceBaseId); | ||
const moduleBasePath = `${serverDirectories.srcDirectory}/${entityName}/base/${entityName}.service.base.ts`; | ||
addInjectableDependency( | ||
classDeclaration, | ||
PASSWORD_SERVICE_MEMBER_ID.name, | ||
PASSWORD_SERVICE_ID, | ||
"protected" | ||
); | ||
for (const member of classDeclaration.body.body) { | ||
if ( | ||
namedTypes.ClassMethod.check(member) && | ||
namedTypes.Identifier.check(member.key) && | ||
PASSWORD_FIELD_ASYNC_METHODS.has(member.key.name) | ||
) { | ||
member.async = true; | ||
} | ||
} | ||
//add the password service | ||
addImports(template, [ | ||
importNames( | ||
[PASSWORD_SERVICE_ID], | ||
relativeImportPath( | ||
moduleBasePath, | ||
`${context.serverDirectories.srcDirectory}/auth/password.service.ts` | ||
) | ||
), | ||
]); | ||
addImports(template, [ | ||
importNames( | ||
[TRANSFORM_STRING_FIELD_UPDATE_INPUT_ID], | ||
relativeImportPath( | ||
moduleBasePath, | ||
`${serverDirectories.srcDirectory}/prisma.util.ts` | ||
) | ||
), | ||
]); | ||
return eventParams; | ||
} | ||
private static getPasswordFields( | ||
context: DsgContext, | ||
entityName: string | ||
): EntityField[] | undefined { | ||
const entity = context.entities?.find( | ||
(entity) => | ||
entity.name.toLocaleLowerCase() === entityName.toLocaleLowerCase() | ||
); | ||
return entity?.fields.filter(isPasswordField); | ||
} | ||
private static createMutationDataMapping( | ||
mappings: namedTypes.ObjectProperty[] | ||
): namedTypes.Identifier | namedTypes.ObjectExpression { | ||
if (!mappings.length) { | ||
return ARGS_ID; | ||
} | ||
return builders.objectExpression([ | ||
builders.spreadProperty(ARGS_ID), | ||
builders.objectProperty( | ||
DATA_ID, | ||
builders.objectExpression([ | ||
builders.spreadProperty(memberExpression`${ARGS_ID}.${DATA_ID}`), | ||
...mappings, | ||
]) | ||
), | ||
]); | ||
} | ||
} | ||
export default JwtAuthPlugin; |
@@ -10,2 +10,3 @@ const path = require("path"); | ||
entry: "./src/index.ts", | ||
externals: ["@amplication/code-gen-utils", "@amplication/code-gen-types"], | ||
plugins: [ | ||
@@ -12,0 +13,0 @@ new webpack.SourceMapDevToolPlugin({ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
38
39141
3129132
26
1