Skip to content
Merged

Stage #9305

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@

Contact: <mailto:[email protected]>

Ever Gauzy™ follows good security practices, but 100% security cannot be guaranteed in any software!
Ever Gauzy™ is provided AS IS without any warranty. Use at your own risk!
Ever Gauzy™ follows good security practices, but 100% security cannot be guaranteed in any software!
Ever Gauzy™ is provided AS IS without any warranty. Use at your own risk!
See more details in the [LICENSE](LICENSE.md).

In a production setup, all client-side to server-side (backend, APIs) communications should be encrypted using HTTPS/WSS/SSL (REST APIs, GraphQL endpoint, Socket.io WebSockets, etc.).

If you discover any issue regarding security, please disclose the information responsibly by sending an email to <mailto:[email protected]> or on [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev) and not by creating a GitHub issue.
If you discover any issue regarding security, please disclose the information responsibly by sending an email to <mailto:[email protected]> and not by creating a GitHub issue.

## CVE Clarifications

### CVE-2023-53951 (JWT Weak HMAC Secret)

⚠️ **CVE-2023-53951** refers to our **PUBLIC DEMO environment** (`demo.gauzy.co` / `apidemo.gauzy.co`), which intentionally uses default credentials and secrets for testing purposes. This is expected behavior for a demo environment meant to allow public access and evaluation of the software.

**Production deployments should always use strong, unique secrets configured via environment variables** (e.g., `JWT_SECRET`, `JWT_REFRESH_SECRET`). See our [environment configuration documentation](.env.sample) for all required security-related environment variables.
4 changes: 2 additions & 2 deletions apps/agent/src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@
"publish": [
{
"provider": "github",
"repo": "ever-agent",
"repo": "ever-gauzy-agent",
"releaseType": "release"
},
{
"provider": "spaces",
"name": "ever",
"region": "sfo3",
"path": "/ever-agent",
"path": "/ever-gauzy-agent",
"acl": "public-read"
}
],
Expand Down
1 change: 1 addition & 0 deletions packages/contracts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export * from './lib/role.model';
export * from './lib/screening-task.model';
export * from './lib/screenshot.model';
export * from './lib/seed.model';
export * from './lib/shared-entity.model';
export * from './lib/shared-types';
export * from './lib/skill-entity.model';
export * from './lib/sms.model';
Expand Down
18 changes: 18 additions & 0 deletions packages/contracts/src/lib/shared-entity.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { IBasePerEntityType, JsonData, OmitFields } from "./base-entity.model";

export interface ISharedEntity extends IBasePerEntityType {
readonly token: string;
shareRules: IShareRule | string; // Essentially stores entity fields and relations that are shared
sharedOptions?: JsonData; // Stores additional options for the shared entity
}

export interface IShareRule {
fields: string[];
relations?: Record<string, IShareRule> | string;
}

export interface ISharedEntityCreateInput extends OmitFields<ISharedEntity, 'token'> {}

export interface ISharedEntityFindInput extends Partial<ISharedEntity> {}

export interface ISharedEntityUpdateInput extends Partial<OmitFields<ISharedEntity, 'token' | 'entity' | 'entityId'>> {}
4 changes: 3 additions & 1 deletion packages/core/src/lib/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ import { TagTypeModule } from '../tag-type/tag-type.module';
import { EmployeeNotificationModule } from '../employee-notification/employee-notification.module';
import { EmployeeNotificationSettingModule } from '../employee-notification-setting/employee-notification-setting.module';
import { EmployeeRecentVisitModule } from '../employee-recent-visit/employee-recent-visit.module';
import { SharedEntityModule } from '../shared-entity/shared-entity.module';

const { unleashConfig } = environment;

Expand Down Expand Up @@ -508,7 +509,8 @@ if (environment.THROTTLE_ENABLED) {
EmployeeNotificationModule,
EmployeeNotificationSettingModule,
TenantApiKeyModule,
EmployeeRecentVisitModule
EmployeeRecentVisitModule,
SharedEntityModule
],
controllers: [AppController],
providers: [
Expand Down
32 changes: 30 additions & 2 deletions packages/core/src/lib/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
ISocialAccount,
ISocialAccountExistUser,
IUserSigninWorkspaceResponse,
LanguagesEnum
LanguagesEnum,
PermissionsEnum
} from '@gauzy/contracts';
import { Public } from '@gauzy/common';
import { parseToBoolean } from '@gauzy/utils';
Expand All @@ -31,7 +32,8 @@ import {
WorkspaceSigninVerifyTokenCommand
} from './commands';
import { RequestContext } from '../core/context';
import { AuthRefreshGuard, TenantPermissionGuard } from './../shared/guards';
import { AuthRefreshGuard, PermissionGuard, TenantPermissionGuard } from './../shared/guards';
import { Permissions } from './../shared/decorators';
import { UseValidationPipe } from '../shared/pipes';
import { ChangePasswordRequestDTO, ResetPasswordRequestDTO } from './../password-reset/dto';
import { RegisterUserDTO, UserEmailDTO, UserLoginDTO, UserSigninWorkspaceDTO } from './../user/dto';
Expand All @@ -42,6 +44,7 @@ import {
RefreshTokenDto,
WorkspaceSigninEmailVerifyDTO,
WorkspaceSigninDTO,
SwitchOrganizationDTO,
SwitchWorkspaceDTO
} from './dto';
import { FindUserBySocialLoginDTO, SocialLoginBodyRequestDTO } from './social-account/dto';
Expand Down Expand Up @@ -361,4 +364,29 @@ export class AuthController {
async switchWorkspace(@Body() input: SwitchWorkspaceDTO): Promise<IAuthResponse | null> {
return await this.authService.switchWorkspace(input.tenantId);
}

/**
* Switch to a different organization within the current workspace
*/
@ApiOperation({ summary: 'Switch to a different organization within the current workspace' })
@ApiResponse({
status: HttpStatus.OK,
description: 'Successfully switched organization. Returns new authentication tokens.'
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: 'User not authenticated or does not have access to the organization.'
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'Invalid organization switch request. Check that organizationId is a valid UUID.'
})
@HttpCode(HttpStatus.OK)
@Post('/switch-organization')
@UseGuards(TenantPermissionGuard, PermissionGuard)
@Permissions(PermissionsEnum.CHANGE_SELECTED_ORGANIZATION)
@UseValidationPipe({ whitelist: true })
async switchOrganization(@Body() input: SwitchOrganizationDTO): Promise<IAuthResponse | null> {
return await this.authService.switchOrganization(input.organizationId);
}
}
Loading
Loading