Skip to content

Commit

Permalink
Added generic auth loading for graphql guards (#4872)
Browse files Browse the repository at this point in the history
* Added generic auth loading for graphql guards

* fix ci

* refactor

* better logging and structure

* fixed space not loaded correctly for calendar events

* removed redundant comments

---------

Co-authored-by: Svetoslav <[email protected]>
  • Loading branch information
valentinyanakiev and hero101 authored Jan 27, 2025
1 parent fe6dcb3 commit 0408f99
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 14 deletions.
3 changes: 3 additions & 0 deletions src/common/enums/logging.context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,7 @@ export enum LogContext {
KRATOS = 'kratos',
WINGBACK = 'wingback',
WINGBACK_HOOKS = 'wingback-hooks',
//
AUTH_GUARD = 'auth-guard',
CODE_ERRORS = 'code-errors', // This is a special context for logging code errors with potential high impact
}
68 changes: 61 additions & 7 deletions src/core/authorization/graphql.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import { AuthorizationService } from '@core/authorization/authorization.service'
import { AuthorizationRuleAgentPrivilege } from './authorization.rule.agent.privilege';
import { AgentInfo } from '@core/authentication.agent.info/agent.info';
import { ICredentialDefinition } from '@domain/agent/credential/credential.definition.interface';
import { AuthorizationPolicy } from '@domain/common/authorization-policy';
import { InjectEntityManager } from '@nestjs/typeorm';
import { EntityManager } from 'typeorm';

@Injectable()
export class GraphqlGuard extends AuthGuard([
Expand All @@ -30,6 +33,8 @@ export class GraphqlGuard extends AuthGuard([
constructor(
private reflector: Reflector,
private authorizationService: AuthorizationService,
@InjectEntityManager('default')
private entityManager: EntityManager,
@Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService
) {
super();
Expand Down Expand Up @@ -98,18 +103,67 @@ export class GraphqlGuard extends AuthGuard([
);
if (privilege) {
const fieldParent = gqlContext.getRoot();
const rule = new AuthorizationRuleAgentPrivilege(
this.authorizationService,
privilege,
fieldParent,
fieldName
);
rule.execute(resultAgentInfo);
if (fieldParent.authorizationId && !fieldParent.authorization) {
this.logger.error(
{
message: 'No authorization policy present in Guard',
fieldName,
fieldParent,
authorizationId: fieldParent.authorizationId,
},
undefined,
LogContext.CODE_ERRORS
);
this.entityManager
.findOne(AuthorizationPolicy, {
where: { id: fieldParent.authorizationId },
})
.then((authorization: any) => {
fieldParent.authorization = authorization;
})
.catch((error: any) => {
this.logger.error(
`Error loading authorization with id ${fieldParent.authorizationId}: ${error}`,
undefined,
LogContext.AUTH_GUARD
);
})
.finally(() => {
this.executeAuthorizationRule(
privilege,
fieldParent,
fieldName,
resultAgentInfo
);
});
} else {
this.executeAuthorizationRule(
privilege,
fieldParent,
fieldName,
resultAgentInfo
);
}
}

return resultAgentInfo;
}

private executeAuthorizationRule(
privilege: AuthorizationPrivilege,
fieldParent: any,
fieldName: any,
resultAgentInfo: any
) {
const rule = new AuthorizationRuleAgentPrivilege(
this.authorizationService,
privilege,
fieldParent,
fieldName
);
rule.execute(resultAgentInfo);
}

public createAnonymousAgentInfo(): AgentInfo {
const emptyAgentInfo = new AgentInfo();
const anonymousCredential: ICredentialDefinition = {
Expand Down
2 changes: 2 additions & 0 deletions src/domain/community/user/user.resolver.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { MockPreferenceSetService } from '@test/mocks/preference.set.service.moc
import { MockNotificationsService } from '@test/mocks/notifications.service.mock';
import { MockNotificationAdapter } from '@test/mocks/notification.adapter.service.mock';
import { MockPlatformAuthorizationService } from '@test/mocks/platform.authorization.service.mock';
import { MockEntityManagerProvider } from '@test/mocks';

describe('UserResolver', () => {
let resolver: UserResolverQueries;
Expand All @@ -35,6 +36,7 @@ describe('UserResolver', () => {
MockPreferenceSetService,
MockNotificationAdapter,
MockNotificationsService,
MockEntityManagerProvider,
UserResolverMutations,
UserResolverQueries,
],
Expand Down
1 change: 1 addition & 0 deletions src/domain/timeline/event/event.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { NameableEntity } from '@domain/common/entity/nameable-entity/nameable.e
import { Room } from '@domain/communication/room/room.entity';
import { ENUM_LENGTH, UUID_LENGTH } from '@common/constants';
import { CalendarEventType } from '@common/enums/calendar.event.type';
import { Space } from '@domain/space/space/space.entity';

@Entity()
export class CalendarEvent extends NameableEntity implements ICalendarEvent {
Expand Down
3 changes: 2 additions & 1 deletion src/domain/timeline/event/event.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { CalendarEventAuthorizationService } from './event.service.authorization
import { ProfileModule } from '@domain/common/profile/profile.module';
import { RoomModule } from '@domain/communication/room/room.module';
import { UserLookupModule } from '@domain/community/user-lookup/user.lookup.module';
import { Space } from '@domain/space/space/space.entity';

@Module({
imports: [
Expand All @@ -20,7 +21,7 @@ import { UserLookupModule } from '@domain/community/user-lookup/user.lookup.modu
VisualModule,
UserLookupModule,
ProfileModule,
TypeOrmModule.forFeature([CalendarEvent]),
TypeOrmModule.forFeature([CalendarEvent, Space]),
],
providers: [
CalendarEventResolverMutations,
Expand Down
23 changes: 17 additions & 6 deletions src/domain/timeline/event/event.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Inject, Injectable, LoggerService } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm';
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';
import { FindOneOptions, In, Repository } from 'typeorm';
import { EntityManager, FindOneOptions, In, Repository } from 'typeorm';
import { EntityNotFoundException } from '@common/exceptions';
import { LogContext, ProfileType } from '@common/enums';
import { AuthorizationPolicy } from '@domain/common/authorization-policy';
Expand Down Expand Up @@ -31,6 +31,7 @@ export class CalendarEventService {
private authorizationPolicyService: AuthorizationPolicyService,
private roomService: RoomService,
private profileService: ProfileService,
@InjectRepository(Space) private spaceRepository: Repository<Space>,
@InjectRepository(CalendarEvent)
private calendarEventRepository: Repository<CalendarEvent>,
@Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService
Expand Down Expand Up @@ -205,10 +206,10 @@ export class CalendarEventService {
return calendarEventLoaded.profile;
}

public getSubspace(
public async getSubspace(
calendarEvent: ICalendarEvent
): Promise<ISpace | undefined> {
return this.calendarEventRepository
const spaceParentOfTheEvent = await this.calendarEventRepository
.createQueryBuilder('calendarEvent')
.leftJoin(Calendar, 'calendar', 'calendar.id = calendarEvent.calendarId')
.leftJoin(Timeline, 'timeline', 'timeline.calendarId = calendar.id')
Expand All @@ -224,8 +225,18 @@ export class CalendarEventService {
)
.where('calendarEvent.id = :id', { id: calendarEvent.id })
.andWhere('subspace.level != :level', { level: SpaceLevel.SPACE })
.select('subspace.*')
.getRawOne<ISpace>();
.select('subspace.id as spaceId')
.getRawOne<{ spaceId: string }>();

if (!spaceParentOfTheEvent) {
return undefined;
}

const space = await this.spaceRepository.findOne({
where: { id: spaceParentOfTheEvent.spaceId },
});

return space ?? undefined;
}

public async getComments(calendarEventID: string) {
Expand Down

0 comments on commit 0408f99

Please sign in to comment.