• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GEWIS / sudosos-backend / 25753937432

12 May 2026 09:17AM UTC coverage: 88.117% (-1.0%) from 89.089%
25753937432

push

github

web-flow
chore(deps): fix missing dependencies for running docs:dev (#911)

3925 of 4574 branches covered (85.81%)

Branch coverage included in aggregate %.

20093 of 22683 relevant lines covered (88.58%)

1125.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.38
/src/controller/root-controller.ts
1
/**
1✔
2
 *  SudoSOS back-end API service.
3
 *  Copyright (C) 2026 Study association GEWIS
4
 *
5
 *  This program is free software: you can redistribute it and/or modify
6
 *  it under the terms of the GNU Affero General Public License as published
7
 *  by the Free Software Foundation, either version 3 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU Affero General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU Affero General Public License
16
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
 *
18
 *  @license
19
 */
1✔
20

21
/**
1✔
22
 * THis is the module page of the root-controller.
23
 *
24
 * @module internal/controllers
25
 */
1✔
26

27
import { Request, Response } from 'express';
28
import log4js, { Logger } from 'log4js';
29
import BaseController, { BaseControllerOptions } from './base-controller';
30
import Policy from './policy';
31
import { parseRequestPagination, toResponse } from '../helpers/pagination';
32
import BannerService from '../service/banner-service';
33
import ServerSettingsStore from '../server-settings/server-settings-store';
34
import { ServerStatusResponse } from './response/server-status-response';
35
import TermsOfServiceService from '../service/terms-of-service-service';
36

37
export default class RootController extends BaseController {
1✔
38
  /**
1✔
39
   * Reference to the logger instance.
40
   */
1✔
41
  private logger: Logger = log4js.getLogger('RootController');
1✔
42

43
  /**
1✔
44
   * Creates a new root controller instance.
45
   * @param options - The options passed to the base controller.
46
   */
1✔
47
  public constructor(options: BaseControllerOptions) {
1✔
48
    super(options);
2✔
49
    this.configureLogger(this.logger);
2✔
50
  }
2✔
51

52
  /**
1✔
53
   * @inheritDoc
54
   */
1✔
55
  public getPolicy(): Policy {
1✔
56
    return {
2✔
57
      '/ping': {
2✔
58
        GET: {
2✔
59
          policy: async () => Promise.resolve(true),
2✔
60
          handler: this.ping.bind(this),
2✔
61
          restrictions: { availableDuringMaintenance: true },
2✔
62
        },
2✔
63
      },
2✔
64
      '/open/banners': {
2✔
65
        GET: {
2✔
66
          policy: async () => true,
2✔
67
          handler: this.returnAllBanners.bind(this),
2✔
68
        },
2✔
69
      },
2✔
70
      '/terms-of-service/latest': {
2✔
71
        GET: {
2✔
72
          policy: async () => Promise.resolve(true),
2✔
73
          handler: this.getLatestTOS.bind(this),
2✔
74
        },
2✔
75
      },
2✔
76
    };
2✔
77
  }
2✔
78

79
  /**
1✔
80
   * GET /open/banners
81
   * @summary Returns all existing banners
82
   * @operationId getAllOpenBanners
83
   * @tags banners - Operations of banner controller
84
   * @param {integer} take.query - How many banners the endpoint should return
85
   * @param {integer} skip.query - How many banners should be skipped (for pagination)
86
   * @return {PaginatedBannerResponse} 200 - All existing banners
87
   * @return {string} 400 - Validation error
88
   * @return {string} 500 - Internal server error
89
   */
1✔
90
  public async returnAllBanners(req: Request, res: Response): Promise<void> {
1✔
91
    this.logger.trace('Get all banners by', req.ip);
3✔
92

93
    let take;
3✔
94
    let skip;
3✔
95
    try {
3✔
96
      const pagination = parseRequestPagination(req);
3✔
97
      take = pagination.take;
3✔
98
      skip = pagination.skip;
3✔
99
    } catch (e) {
3!
100
      res.status(400).send(e.message);
×
101
      return;
×
102
    }
×
103

104
    // handle request
3✔
105
    try {
3✔
106
      const [banners, count] = await BannerService.getBanners({}, { take, skip });
3✔
107
      res.json(toResponse(
3✔
108
        banners.map(BannerService.asBannerResponse),
3✔
109
        count,
3✔
110
        { take, skip },
3✔
111
      ));
112
    } catch (error) {
3!
113
      this.logger.error('Could not return all banners:', error);
×
114
      res.status(500).json('Internal server error.');
×
115
    }
×
116
  }
3✔
117

118
  /**
1✔
119
   * GET /ping
120
   * @summary Get the current status of the backend
121
   * @operationId ping
122
   * @tags root - Operations of the root controller
123
   * @return {ServerStatusResponse} 200 - Success
124
   * @return {string} 500 - Internal server error
125
   */
1✔
126
  public async ping(req: Request, res: Response): Promise<void> {
1✔
127
    this.logger.trace('Ping by', req.ip);
3✔
128

129
    try {
3✔
130
      const store = ServerSettingsStore.getInstance();
3✔
131
      const maintenanceMode = await store.getSettingFromDatabase('maintenanceMode');
3✔
132
      res.status(200).json({
2✔
133
        maintenanceMode,
2✔
134
      } as ServerStatusResponse);
2✔
135
    } catch (e) {
3✔
136
      res.status(500).json('Internal server error.');
1✔
137
    }
1✔
138
  }
3✔
139

140
  /**
1✔
141
   * GET /terms-of-service/latest
142
   * @summary Get the latest terms of service version
143
   * @operationId getLatestTermsOfService
144
   * @tags terms-of-service - Operations of terms of service controller
145
   * @return {TermsOfServiceResponse} 200 - The requested terms of service version
146
   * @return {string} 500 - Internal server error
147
   */
1✔
148
  public async getLatestTOS(req: Request, res: Response): Promise<void> {
1✔
149
    try {
4✔
150
      const tos = await TermsOfServiceService.getLatestTermsOfService();
4✔
151
      res.json(TermsOfServiceService.asTermsOfServiceResponse(tos));
3✔
152
    } catch (error) {
4✔
153
      this.logger.error('Could not get latest Terms of Service', error);
1✔
154
      res.status(500).json('Internal server error.');
1✔
155
    }
1✔
156
  }
4✔
157
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc