1895 extensibility v1 application tokens 3 (#16504)

- moves applicationRoleId to application entity
- add new `APPLICATION` FieldActorSource and `APPLICATION`
JwtTokenTypeEnum value
- create a new token with applicationId when executing a function
- when applicationId is in token, check for application.defaultRole
permissions
-use twenty-shared types in `twenty-sdk/application`
- create a new import from generate called "Twenty" that you can use
directly without having to set TWENTY_API_KEY AND TWENTY_API_URL (keep
metadata or core parameter only)
- provide to serverless unique one time BEARER TOKEN to run it

Result
<img width="977" height="566" alt="image"
src="https://github.com/user-attachments/assets/e78428a0-5b13-4975-aa13-58ee3b32450c"
/>

<img width="910" height="596" alt="image"
src="https://github.com/user-attachments/assets/6ec72bf5-7655-4093-a45e-ad269595a324"
/>

<img width="741" height="568" alt="image"
src="https://github.com/user-attachments/assets/7683944c-fd79-4417-8fb2-8e4815cc112f"
/>
This commit is contained in:
martmull
2025-12-15 17:44:23 +01:00
committed by GitHub
parent e33f18bfa8
commit e289f3056e
103 changed files with 1427 additions and 512 deletions
@@ -49,6 +49,7 @@ import { PermissionsService } from 'src/engine/metadata-modules/permissions/perm
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import type { RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
@Injectable()
export abstract class CommonBaseQueryRunnerService<
@@ -304,6 +305,10 @@ export abstract class CommonBaseQueryRunnerService<
);
}
if (isDefined(authContext.application?.defaultServerlessFunctionRoleId)) {
return authContext.application?.defaultServerlessFunctionRoleId;
}
if (!isDefined(authContext.userWorkspaceId)) {
throw new CommonQueryRunnerException(
'Invalid auth context',
@@ -325,7 +330,9 @@ export abstract class CommonBaseQueryRunnerService<
const roleId = await this.getRoleIdOrThrow(authContext, workspaceId);
const rolePermissionConfig = { unionOf: [roleId] };
const rolePermissionConfig: RolePermissionConfig = {
intersectionOf: [roleId],
};
const repository = await this.globalWorkspaceOrmManager.getRepository(
workspaceId,
@@ -2,6 +2,7 @@ import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-contex
interface AuthContextWithDefinedWorkspaceProperties {
user: AuthContext['user'];
application: AuthContext['application'];
workspace: NonNullable<AuthContext['workspace']>;
workspaceMetadataVersion?: string;
workspaceMemberId: AuthContext['workspaceMemberId'];
@@ -17,5 +18,9 @@ interface UserWorkspaceAuthContext extends Request {
userWorkspaceId: NonNullable<AuthContext['userWorkspaceId']>;
}
interface ApplicationAuthContext extends Request {
application: NonNullable<AuthContext['application']>;
}
export type WorkspaceAuthContext = AuthContextWithDefinedWorkspaceProperties &
(ApiKeyAuthContext | UserWorkspaceAuthContext);
(ApiKeyAuthContext | UserWorkspaceAuthContext | ApplicationAuthContext);
@@ -9,6 +9,8 @@ export const isWorkspaceAuthContext = (
): context is WorkspaceAuthContext => {
return (
isDefined(context.workspace) &&
(isDefined(context.userWorkspaceId) || isDefined(context.apiKey))
(isDefined(context.userWorkspaceId) ||
isDefined(context.apiKey) ||
isDefined(context.application))
);
};