diff --git a/src/api/public/me/me.controller.spec.ts b/src/api/public/me/me.controller.spec.ts
index 43110f49c..5b8d6f7ff 100644
--- a/src/api/public/me/me.controller.spec.ts
+++ b/src/api/public/me/me.controller.spec.ts
@@ -22,6 +22,7 @@ import { MeController } from './me.controller';
 import { HistoryEntry } from '../../../history/history-entry.entity';
 import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
 import { NoteUserPermission } from '../../../permissions/note-user-permission.entity';
+import { Group } from '../../../groups/group.entity';
 
 describe('Me Controller', () => {
   let controller: MeController;
@@ -53,6 +54,8 @@ describe('Me Controller', () => {
       .useValue({})
       .overrideProvider(getRepositoryToken(NoteUserPermission))
       .useValue({})
+      .overrideProvider(getRepositoryToken(Group))
+      .useValue({})
       .compile();
 
     controller = module.get<MeController>(MeController);
diff --git a/src/api/public/media/media.controller.spec.ts b/src/api/public/media/media.controller.spec.ts
index 7da3ca771..5e99c2b5f 100644
--- a/src/api/public/media/media.controller.spec.ts
+++ b/src/api/public/media/media.controller.spec.ts
@@ -24,6 +24,7 @@ import { User } from '../../../users/user.entity';
 import { MediaController } from './media.controller';
 import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
 import { NoteUserPermission } from '../../../permissions/note-user-permission.entity';
+import { Group } from '../../../groups/group.entity';
 
 describe('Media Controller', () => {
   let controller: MediaController;
@@ -63,6 +64,8 @@ describe('Media Controller', () => {
       .useValue({})
       .overrideProvider(getRepositoryToken(NoteUserPermission))
       .useValue({})
+      .overrideProvider(getRepositoryToken(Group))
+      .useValue({})
       .compile();
 
     controller = module.get<MediaController>(MediaController);
diff --git a/src/api/public/notes/notes.controller.spec.ts b/src/api/public/notes/notes.controller.spec.ts
index 18f28a708..187e5ef1b 100644
--- a/src/api/public/notes/notes.controller.spec.ts
+++ b/src/api/public/notes/notes.controller.spec.ts
@@ -24,6 +24,8 @@ import { HistoryModule } from '../../../history/history.module';
 import { HistoryEntry } from '../../../history/history-entry.entity';
 import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
 import { NoteUserPermission } from '../../../permissions/note-user-permission.entity';
+import { Group } from '../../../groups/group.entity';
+import { GroupsModule } from '../../../groups/groups.module';
 
 describe('Notes Controller', () => {
   let controller: NotesController;
@@ -45,6 +47,7 @@ describe('Notes Controller', () => {
       imports: [
         RevisionsModule,
         UsersModule,
+        GroupsModule,
         LoggerModule,
         PermissionsModule,
         HistoryModule,
@@ -74,6 +77,8 @@ describe('Notes Controller', () => {
       .useValue({})
       .overrideProvider(getRepositoryToken(NoteUserPermission))
       .useValue({})
+      .overrideProvider(getRepositoryToken(Group))
+      .useValue({})
       .compile();
 
     controller = module.get<NotesController>(NotesController);
diff --git a/src/groups/group-info.dto.ts b/src/groups/group-info.dto.ts
new file mode 100644
index 000000000..40ea64cb1
--- /dev/null
+++ b/src/groups/group-info.dto.ts
@@ -0,0 +1,30 @@
+/*
+ * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+import { IsBoolean, IsString } from 'class-validator';
+
+export class GroupInfoDto {
+  /**
+   * Name of the group
+   * @example "superheroes"
+   */
+  @IsString()
+  name: string;
+
+  /**
+   * Display name of this group
+   * @example "Superheroes"
+   */
+  @IsString()
+  displayName: string;
+
+  /**
+   * True if this group must be specially handled
+   * Used for e.g. "everybody", "all logged in users"
+   * @example false
+   */
+  @IsBoolean()
+  special: boolean;
+}
diff --git a/src/groups/group.entity.ts b/src/groups/group.entity.ts
index 0574e243e..f3cdc6ad4 100644
--- a/src/groups/group.entity.ts
+++ b/src/groups/group.entity.ts
@@ -40,4 +40,15 @@ export class Group {
   })
   @JoinTable()
   members: User[];
+
+  // eslint-disable-next-line @typescript-eslint/no-empty-function
+  private constructor() {}
+
+  public static create(name: string, displayName: string): Group {
+    const newGroup = new Group();
+    newGroup.special = false; // this attribute should only be true for the two special groups
+    newGroup.name = name;
+    newGroup.displayName = displayName;
+    return newGroup;
+  }
 }
diff --git a/src/groups/groups.module.ts b/src/groups/groups.module.ts
index 7f3fa62a6..d4d6c2932 100644
--- a/src/groups/groups.module.ts
+++ b/src/groups/groups.module.ts
@@ -7,8 +7,12 @@
 import { Module } from '@nestjs/common';
 import { TypeOrmModule } from '@nestjs/typeorm';
 import { Group } from './group.entity';
+import { GroupsService } from './groups.service';
+import { LoggerModule } from '../logger/logger.module';
 
 @Module({
-  imports: [TypeOrmModule.forFeature([Group])],
+  imports: [TypeOrmModule.forFeature([Group]), LoggerModule],
+  providers: [GroupsService],
+  exports: [GroupsService],
 })
 export class GroupsModule {}
diff --git a/src/groups/groups.service.spec.ts b/src/groups/groups.service.spec.ts
new file mode 100644
index 000000000..827d2d1f0
--- /dev/null
+++ b/src/groups/groups.service.spec.ts
@@ -0,0 +1,75 @@
+/*
+ * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Test, TestingModule } from '@nestjs/testing';
+import { GroupsService } from './groups.service';
+import { getRepositoryToken } from '@nestjs/typeorm';
+import { Repository } from 'typeorm';
+import { Group } from './group.entity';
+import { NotInDBError } from '../errors/errors';
+import { LoggerModule } from '../logger/logger.module';
+
+describe('GroupsService', () => {
+  let service: GroupsService;
+  let groupRepo: Repository<Group>;
+  let group: Group;
+
+  beforeAll(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      providers: [
+        GroupsService,
+        {
+          provide: getRepositoryToken(Group),
+          useClass: Repository,
+        },
+      ],
+      imports: [LoggerModule],
+    }).compile();
+
+    service = module.get<GroupsService>(GroupsService);
+    groupRepo = module.get<Repository<Group>>(getRepositoryToken(Group));
+    group = Group.create('testGroup', 'Superheros') as Group;
+  });
+
+  it('should be defined', () => {
+    expect(service).toBeDefined();
+  });
+
+  describe('getGroupByName', () => {
+    it('works', async () => {
+      jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
+      const foundGroup = await service.getGroupByName(group.name);
+      expect(foundGroup.name).toEqual(group.name);
+      expect(foundGroup.displayName).toEqual(group.displayName);
+      expect(foundGroup.special).toEqual(group.special);
+    });
+    it('fails with non-existing group', async () => {
+      jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(undefined);
+      try {
+        await service.getGroupByName('i_dont_exist');
+      } catch (e) {
+        expect(e).toBeInstanceOf(NotInDBError);
+      }
+    });
+  });
+
+  describe('toGroupDto', () => {
+    it('works', () => {
+      const groupDto = service.toGroupDto(group);
+      expect(groupDto.displayName).toEqual(group.displayName);
+      expect(groupDto.name).toEqual(group.name);
+      expect(groupDto.special).toBeFalsy();
+    });
+    it('fails with null parameter', () => {
+      const groupDto = service.toGroupDto(null);
+      expect(groupDto).toBeNull();
+    });
+    it('fails with undefined parameter', () => {
+      const groupDto = service.toGroupDto(undefined);
+      expect(groupDto).toBeNull();
+    });
+  });
+});
diff --git a/src/groups/groups.service.ts b/src/groups/groups.service.ts
new file mode 100644
index 000000000..042ef0996
--- /dev/null
+++ b/src/groups/groups.service.ts
@@ -0,0 +1,57 @@
+/*
+ * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { ConsoleLoggerService } from '../logger/console-logger.service';
+import { InjectRepository } from '@nestjs/typeorm';
+import { Repository } from 'typeorm';
+import { Group } from './group.entity';
+import { NotInDBError } from '../errors/errors';
+import { GroupInfoDto } from './group-info.dto';
+
+@Injectable()
+export class GroupsService {
+  constructor(
+    private readonly logger: ConsoleLoggerService,
+    @InjectRepository(Group) private groupRepository: Repository<Group>,
+  ) {
+    this.logger.setContext(GroupsService.name);
+  }
+
+  /**
+   * @async
+   * Get a group by their name.
+   * @param {string} name - the groups name
+   * @return {Group} the group
+   * @throws {NotInDBError} there is no group with this name
+   */
+  async getGroupByName(name: string): Promise<Group> {
+    const group = await this.groupRepository.findOne({
+      where: { name: name },
+    });
+    if (group === undefined) {
+      throw new NotInDBError(`Group with name '${name}' not found`);
+    }
+    return group;
+  }
+
+  /**
+   * Build GroupInfoDto from a group.
+   * @param {Group} group - the group to use
+   * @return {GroupInfoDto} the built GroupInfoDto
+   */
+  toGroupDto(group: Group | null | undefined): GroupInfoDto | null {
+    if (!group) {
+      this.logger.warn(`Recieved ${group} argument!`, 'toGroupDto');
+      return null;
+    }
+    return {
+      name: group.name,
+      displayName: group.displayName,
+      special: group.special,
+    };
+  }
+}
diff --git a/src/history/history.service.spec.ts b/src/history/history.service.spec.ts
index caa177c36..af4613dc1 100644
--- a/src/history/history.service.spec.ts
+++ b/src/history/history.service.spec.ts
@@ -23,6 +23,7 @@ import { Repository } from 'typeorm';
 import { NotInDBError } from '../errors/errors';
 import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
 import { NoteUserPermission } from '../permissions/note-user-permission.entity';
+import { Group } from '../groups/group.entity';
 
 describe('HistoryService', () => {
   let service: HistoryService;
@@ -60,6 +61,8 @@ describe('HistoryService', () => {
       .useValue({})
       .overrideProvider(getRepositoryToken(NoteUserPermission))
       .useValue({})
+      .overrideProvider(getRepositoryToken(Group))
+      .useValue({})
       .compile();
 
     service = module.get<HistoryService>(HistoryService);
diff --git a/src/media/media.service.spec.ts b/src/media/media.service.spec.ts
index 9c2c0535e..8773be3da 100644
--- a/src/media/media.service.spec.ts
+++ b/src/media/media.service.spec.ts
@@ -27,6 +27,7 @@ import { promises as fs } from 'fs';
 import { ClientError, NotInDBError, PermissionError } from '../errors/errors';
 import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
 import { NoteUserPermission } from '../permissions/note-user-permission.entity';
+import { Group } from '../groups/group.entity';
 
 describe('MediaService', () => {
   let service: MediaService;
@@ -78,6 +79,8 @@ describe('MediaService', () => {
       .useValue({})
       .overrideProvider(getRepositoryToken(MediaUpload))
       .useClass(Repository)
+      .overrideProvider(getRepositoryToken(Group))
+      .useValue({})
       .compile();
 
     service = module.get<MediaService>(MediaService);
diff --git a/src/notes/note-permissions.dto.ts b/src/notes/note-permissions.dto.ts
index 55bb1c7b9..42da78129 100644
--- a/src/notes/note-permissions.dto.ts
+++ b/src/notes/note-permissions.dto.ts
@@ -6,6 +6,7 @@
 
 import { IsArray, IsBoolean, IsString, ValidateNested } from 'class-validator';
 import { UserInfoDto } from '../users/user-info.dto';
+import { GroupInfoDto } from '../groups/group-info.dto';
 
 export class NoteUserPermissionEntryDto {
   /**
@@ -38,30 +39,6 @@ export class NoteUserPermissionUpdateDto {
   canEdit: boolean;
 }
 
-export class GroupInfoDto {
-  /**
-   * Name of the group
-   * @example "superheroes"
-   */
-  @IsString()
-  name: string;
-
-  /**
-   * Display name of this group
-   * @example "Superheroes"
-   */
-  @IsString()
-  displayName: string;
-
-  /**
-   * True if this group must be specially handled
-   * Used for e.g. "everybody", "all logged in users"
-   * @example false
-   */
-  @IsBoolean()
-  special: boolean;
-}
-
 export class NoteGroupPermissionEntryDto {
   /**
    * Group this permission applies to
diff --git a/src/notes/notes.module.ts b/src/notes/notes.module.ts
index cba204cf6..609489ac3 100644
--- a/src/notes/notes.module.ts
+++ b/src/notes/notes.module.ts
@@ -15,6 +15,7 @@ import { NotesService } from './notes.service';
 import { Tag } from './tag.entity';
 import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
 import { NoteUserPermission } from '../permissions/note-user-permission.entity';
+import { GroupsModule } from '../groups/groups.module';
 
 @Module({
   imports: [
@@ -27,6 +28,7 @@ import { NoteUserPermission } from '../permissions/note-user-permission.entity';
     ]),
     forwardRef(() => RevisionsModule),
     UsersModule,
+    GroupsModule,
     LoggerModule,
   ],
   controllers: [],
diff --git a/src/notes/notes.service.spec.ts b/src/notes/notes.service.spec.ts
index d08cc8f03..12a596ef7 100644
--- a/src/notes/notes.service.spec.ts
+++ b/src/notes/notes.service.spec.ts
@@ -17,9 +17,12 @@ import { UsersModule } from '../users/users.module';
 import { AuthorColor } from './author-color.entity';
 import { Note } from './note.entity';
 import { NotesService } from './notes.service';
+import { Repository } from 'typeorm';
 import { Tag } from './tag.entity';
 import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
 import { NoteUserPermission } from '../permissions/note-user-permission.entity';
+import { GroupsModule } from '../groups/groups.module';
+import { Group } from '../groups/group.entity';
 
 describe('NotesService', () => {
   let service: NotesService;
@@ -37,7 +40,7 @@ describe('NotesService', () => {
           useValue: {},
         },
       ],
-      imports: [UsersModule, RevisionsModule, LoggerModule],
+      imports: [LoggerModule, UsersModule, GroupsModule, RevisionsModule],
     })
       .overrideProvider(getRepositoryToken(User))
       .useValue({})
@@ -59,7 +62,10 @@ describe('NotesService', () => {
       .useValue({})
       .overrideProvider(getRepositoryToken(NoteUserPermission))
       .useValue({})
+      .overrideProvider(getRepositoryToken(Group))
+      .useClass(Repository)
       .compile();
+
     service = module.get<NotesService>(NotesService);
   });
 
diff --git a/src/notes/notes.service.ts b/src/notes/notes.service.ts
index 6bc0fca7d..d05a2159b 100644
--- a/src/notes/notes.service.ts
+++ b/src/notes/notes.service.ts
@@ -22,6 +22,9 @@ import { NoteDto } from './note.dto';
 import { Note } from './note.entity';
 import { Tag } from './tag.entity';
 import { HistoryEntry } from '../history/history-entry.entity';
+import { NoteUserPermission } from '../permissions/note-user-permission.entity';
+import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
+import { GroupsService } from '../groups/groups.service';
 
 @Injectable()
 export class NotesService {
@@ -30,6 +33,7 @@ export class NotesService {
     @InjectRepository(Note) private noteRepository: Repository<Note>,
     @InjectRepository(Tag) private tagRepository: Repository<Tag>,
     @Inject(UsersService) private usersService: UsersService,
+    @Inject(GroupsService) private groupsService: GroupsService,
     @Inject(forwardRef(() => RevisionsService))
     private revisionsService: RevisionsService,
   ) {
diff --git a/src/permissions/permissions.service.spec.ts b/src/permissions/permissions.service.spec.ts
index da27e14a4..6396eb09c 100644
--- a/src/permissions/permissions.service.spec.ts
+++ b/src/permissions/permissions.service.spec.ts
@@ -51,6 +51,8 @@ describe('PermissionsService', () => {
       .useValue({})
       .overrideProvider(getRepositoryToken(NoteUserPermission))
       .useValue({})
+      .overrideProvider(getRepositoryToken(Group))
+      .useValue({})
       .compile();
     permissionsService = module.get<PermissionsService>(PermissionsService);
   });
@@ -241,33 +243,27 @@ describe('PermissionsService', () => {
   function createGroups(): { [id: string]: Group } {
     const result: { [id: string]: Group } = {};
 
-    const everybody: Group = new Group();
+    const everybody: Group = Group.create('everybody', 'Everybody');
     everybody.special = true;
-    everybody.name = 'everybody';
     result['everybody'] = everybody;
 
-    const loggedIn = new Group();
+    const loggedIn = Group.create('loggedIn', 'loggedIn');
     loggedIn.special = true;
-    loggedIn.name = 'loggedIn';
     result['loggedIn'] = loggedIn;
 
-    const user1group = new Group();
-    user1group.name = 'user1group';
+    const user1group = Group.create('user1group', 'user1group');
     user1group.members = [user1];
     result['user1group'] = user1group;
 
-    const user2group = new Group();
-    user2group.name = 'user2group';
+    const user2group = Group.create('user2group', 'user2group');
     user2group.members = [user2];
     result['user2group'] = user2group;
 
-    const user1and2group = new Group();
-    user1and2group.name = 'user1and2group';
+    const user1and2group = Group.create('user1and2group', 'user1and2group');
     user1and2group.members = [user1, user2];
     result['user1and2group'] = user1and2group;
 
-    const user2and1group = new Group();
-    user2and1group.name = 'user2and1group';
+    const user2and1group = Group.create('user2and1group', 'user2and1group');
     user2and1group.members = [user2, user1];
     result['user2and1group'] = user2and1group;
 
diff --git a/src/revisions/revisions.service.spec.ts b/src/revisions/revisions.service.spec.ts
index 43799ae0d..fe82a346f 100644
--- a/src/revisions/revisions.service.spec.ts
+++ b/src/revisions/revisions.service.spec.ts
@@ -19,6 +19,7 @@ import { RevisionsService } from './revisions.service';
 import { Tag } from '../notes/tag.entity';
 import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
 import { NoteUserPermission } from '../permissions/note-user-permission.entity';
+import { Group } from '../groups/group.entity';
 
 describe('RevisionsService', () => {
   let service: RevisionsService;
@@ -54,6 +55,8 @@ describe('RevisionsService', () => {
       .useValue({})
       .overrideProvider(getRepositoryToken(NoteUserPermission))
       .useValue({})
+      .overrideProvider(getRepositoryToken(Group))
+      .useValue({})
       .compile();
 
     service = module.get<RevisionsService>(RevisionsService);