-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into BC-5971-copying-internal-links
- Loading branch information
Showing
119 changed files
with
3,248 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
ansible/roles/schulcloud-server-core/templates/admin-api-server-configmap.yml.j2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: admin-api-server-configmap | ||
namespace: {{ NAMESPACE }} | ||
labels: | ||
app: api-admin | ||
data: | ||
NODE_OPTIONS: "--max-old-space-size=3072" | ||
NEST_LOG_LEVEL: "info" | ||
ADMIN_API__PORT: "4030" | ||
SC_DOMAIN: "{{ DOMAIN }}" | ||
FEATURE_PROMETHEUS_METRICS_ENABLED: "true" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
ansible/roles/schulcloud-server-core/templates/admin-api-server-onepassword.yml.j2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
apiVersion: onepassword.com/v1 | ||
kind: OnePasswordItem | ||
metadata: | ||
name: admin-api-server-secret | ||
namespace: {{ NAMESPACE }} | ||
labels: | ||
app: api-admin | ||
spec: | ||
itemPath: "vaults/{{ ONEPASSWORD_OPERATOR_VAULT }}/items/admin-api-server" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
export interface MailConfig { | ||
ADDITIONAL_BLACKLISTED_EMAIL_DOMAINS: string[]; | ||
BLOCKLIST_OF_EMAIL_DOMAINS: string[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
export * from './account.module'; | ||
export * from './account-config'; | ||
export { AccountService, AccountDto } from './services'; | ||
export { AccountService, AccountDto, AccountSaveDto } from './services'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
export * from './account.service'; | ||
export { AccountDto } from './dto'; | ||
export { AccountDto, AccountSaveDto } from './dto'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
222 changes: 222 additions & 0 deletions
222
apps/server/src/modules/authorization/domain/rules/school-system-options.rule.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
import { createMock, DeepMocked } from '@golevelup/ts-jest'; | ||
import { ObjectId } from '@mikro-orm/mongodb'; | ||
import { SchoolSystemOptions } from '@modules/legacy-school'; | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { SchoolEntity, SystemEntity, User } from '@shared/domain/entity'; | ||
import { Permission } from '@shared/domain/interface'; | ||
import { | ||
schoolFactory, | ||
schoolSystemOptionsFactory, | ||
setupEntities, | ||
systemEntityFactory, | ||
userFactory, | ||
} from '@shared/testing'; | ||
import { AuthorizationContextBuilder } from '../mapper'; | ||
import { AuthorizationHelper } from '../service/authorization.helper'; | ||
import { SchoolSystemOptionsRule } from './school-system-options.rule'; | ||
|
||
describe(SchoolSystemOptionsRule.name, () => { | ||
let module: TestingModule; | ||
let rule: SchoolSystemOptionsRule; | ||
|
||
let authorizationHelper: DeepMocked<AuthorizationHelper>; | ||
|
||
beforeAll(async () => { | ||
await setupEntities(); | ||
|
||
module = await Test.createTestingModule({ | ||
providers: [ | ||
SchoolSystemOptionsRule, | ||
{ | ||
provide: AuthorizationHelper, | ||
useValue: createMock<AuthorizationHelper>(), | ||
}, | ||
], | ||
}).compile(); | ||
|
||
rule = module.get(SchoolSystemOptionsRule); | ||
authorizationHelper = module.get(AuthorizationHelper); | ||
}); | ||
|
||
afterAll(async () => { | ||
await module.close(); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
describe('isApplicable', () => { | ||
describe('when the entity is applicable', () => { | ||
const setup = () => { | ||
const user: User = userFactory.buildWithId(); | ||
const schoolSystemOptions: SchoolSystemOptions = schoolSystemOptionsFactory.build(); | ||
|
||
return { | ||
user, | ||
schoolSystemOptions, | ||
}; | ||
}; | ||
|
||
it('should return true', () => { | ||
const { user, schoolSystemOptions } = setup(); | ||
|
||
const result = rule.isApplicable(user, schoolSystemOptions); | ||
|
||
expect(result).toEqual(true); | ||
}); | ||
}); | ||
|
||
describe('when the entity is not applicable', () => { | ||
const setup = () => { | ||
const user: User = userFactory.buildWithId(); | ||
|
||
return { | ||
user, | ||
}; | ||
}; | ||
|
||
it('should return false', () => { | ||
const { user } = setup(); | ||
|
||
const result = rule.isApplicable(user, {} as unknown as SchoolSystemOptions); | ||
|
||
expect(result).toEqual(false); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('hasPermission', () => { | ||
describe('when the user accesses a system at his school with the required permissions', () => { | ||
const setup = () => { | ||
const systemEntity: SystemEntity = systemEntityFactory.buildWithId(); | ||
const school: SchoolEntity = schoolFactory.buildWithId({ | ||
systems: [systemEntity], | ||
}); | ||
const schoolSystemOptions: SchoolSystemOptions = schoolSystemOptionsFactory.build({ | ||
systemId: systemEntity.id, | ||
schoolId: school.id, | ||
}); | ||
const user: User = userFactory.buildWithId({ school }); | ||
const authorizationContext = AuthorizationContextBuilder.read([Permission.SCHOOL_SYSTEM_VIEW]); | ||
|
||
authorizationHelper.hasAllPermissions.mockReturnValueOnce(true); | ||
|
||
return { | ||
user, | ||
schoolSystemOptions, | ||
authorizationContext, | ||
}; | ||
}; | ||
|
||
it('should check the permission', () => { | ||
const { user, schoolSystemOptions, authorizationContext } = setup(); | ||
|
||
rule.hasPermission(user, schoolSystemOptions, authorizationContext); | ||
|
||
expect(authorizationHelper.hasAllPermissions).toHaveBeenCalledWith( | ||
user, | ||
authorizationContext.requiredPermissions | ||
); | ||
}); | ||
|
||
it('should return true', () => { | ||
const { user, schoolSystemOptions, authorizationContext } = setup(); | ||
|
||
const result = rule.hasPermission(user, schoolSystemOptions, authorizationContext); | ||
|
||
expect(result).toEqual(true); | ||
}); | ||
}); | ||
|
||
describe('when the user accesses a system at his school, but does not have the required permissions', () => { | ||
const setup = () => { | ||
const systemEntity: SystemEntity = systemEntityFactory.buildWithId(); | ||
const school: SchoolEntity = schoolFactory.buildWithId({ | ||
systems: [systemEntity], | ||
}); | ||
const schoolSystemOptions: SchoolSystemOptions = schoolSystemOptionsFactory.build({ | ||
systemId: systemEntity.id, | ||
schoolId: school.id, | ||
}); | ||
const user: User = userFactory.buildWithId({ school }); | ||
const authorizationContext = AuthorizationContextBuilder.read([Permission.SCHOOL_SYSTEM_VIEW]); | ||
|
||
authorizationHelper.hasAllPermissions.mockReturnValueOnce(false); | ||
|
||
return { | ||
user, | ||
schoolSystemOptions, | ||
authorizationContext, | ||
}; | ||
}; | ||
|
||
it('should return false', () => { | ||
const { user, schoolSystemOptions, authorizationContext } = setup(); | ||
|
||
const result = rule.hasPermission(user, schoolSystemOptions, authorizationContext); | ||
|
||
expect(result).toEqual(false); | ||
}); | ||
}); | ||
|
||
describe('when the system is not part of the users school', () => { | ||
const setup = () => { | ||
const systemEntity: SystemEntity = systemEntityFactory.buildWithId(); | ||
const school: SchoolEntity = schoolFactory.buildWithId({ | ||
systems: [systemEntity], | ||
}); | ||
const schoolSystemOptions: SchoolSystemOptions = schoolSystemOptionsFactory.build({ | ||
systemId: new ObjectId().toHexString(), | ||
schoolId: school.id, | ||
}); | ||
const user: User = userFactory.buildWithId({ school }); | ||
const authorizationContext = AuthorizationContextBuilder.read([Permission.SCHOOL_SYSTEM_VIEW]); | ||
|
||
authorizationHelper.hasAllPermissions.mockReturnValueOnce(true); | ||
|
||
return { | ||
user, | ||
schoolSystemOptions, | ||
authorizationContext, | ||
}; | ||
}; | ||
|
||
it('should return false', () => { | ||
const { user, schoolSystemOptions, authorizationContext } = setup(); | ||
|
||
const result = rule.hasPermission(user, schoolSystemOptions, authorizationContext); | ||
|
||
expect(result).toEqual(false); | ||
}); | ||
}); | ||
|
||
describe('when the user is not at the school', () => { | ||
const setup = () => { | ||
const schoolSystemOptions: SchoolSystemOptions = schoolSystemOptionsFactory.build(); | ||
const systemEntity: SystemEntity = systemEntityFactory.buildWithId(); | ||
const school: SchoolEntity = schoolFactory.buildWithId({ | ||
systems: [systemEntity], | ||
}); | ||
const user: User = userFactory.buildWithId({ school }); | ||
const authorizationContext = AuthorizationContextBuilder.read([Permission.SCHOOL_SYSTEM_VIEW]); | ||
|
||
authorizationHelper.hasAllPermissions.mockReturnValueOnce(true); | ||
|
||
return { | ||
user, | ||
schoolSystemOptions, | ||
authorizationContext, | ||
}; | ||
}; | ||
|
||
it('should return false', () => { | ||
const { user, schoolSystemOptions, authorizationContext } = setup(); | ||
|
||
const result = rule.hasPermission(user, schoolSystemOptions, authorizationContext); | ||
|
||
expect(result).toEqual(false); | ||
}); | ||
}); | ||
}); | ||
}); |
28 changes: 28 additions & 0 deletions
28
apps/server/src/modules/authorization/domain/rules/school-system-options.rule.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { AnyProvisioningOptions, SchoolSystemOptions } from '@modules/legacy-school'; | ||
import { Injectable } from '@nestjs/common'; | ||
import { User } from '@shared/domain/entity'; | ||
import { AuthorizationHelper } from '../service/authorization.helper'; | ||
import { AuthorizationContext, Rule } from '../type'; | ||
|
||
@Injectable() | ||
export class SchoolSystemOptionsRule implements Rule<SchoolSystemOptions> { | ||
constructor(private readonly authorizationHelper: AuthorizationHelper) {} | ||
|
||
public isApplicable(user: User, domainObject: SchoolSystemOptions): boolean { | ||
const isMatched: boolean = domainObject instanceof SchoolSystemOptions<AnyProvisioningOptions>; | ||
|
||
return isMatched; | ||
} | ||
|
||
public hasPermission(user: User, domainObject: SchoolSystemOptions, context: AuthorizationContext): boolean { | ||
const hasPermissions: boolean = this.authorizationHelper.hasAllPermissions(user, context.requiredPermissions); | ||
|
||
const isAtSchool: boolean = user.school.id === domainObject.schoolId; | ||
|
||
const hasSystem: boolean = user.school.systems.getIdentifiers().includes(domainObject.systemId); | ||
|
||
const isAuthorized: boolean = hasPermissions && isAtSchool && hasSystem; | ||
|
||
return isAuthorized; | ||
} | ||
} |
Oops, something went wrong.