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

GEWIS / sudosos-backend / 22521478901

28 Feb 2026 01:16PM UTC coverage: 89.184%. First build
22521478901

Pull #761

github

web-flow
Merge a894ad111 into a69b8585a
Pull Request #761: feat: serve TOS from backend

1753 of 2127 branches covered (82.42%)

Branch coverage included in aggregate %.

15 of 46 new or added lines in 4 files covered. (32.61%)

9008 of 9939 relevant lines covered (90.63%)

982.67 hits per line

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

74.29
/src/controller/root-controller.ts
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
 */
20

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

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

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

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

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

79
  /**
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
   */
90
  public async returnAllBanners(req: Request, res: Response): Promise<void> {
91
    this.logger.trace('Get all banners by', req.ip);
3✔
92

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

104
    // handle request
105
    try {
3✔
106
      res.json(await BannerService.getBanners({}, { take, skip }));
3✔
107
    } catch (error) {
108
      this.logger.error('Could not return all banners:', error);
×
109
      res.status(500).json('Internal server error.');
×
110
    }
111
  }
112

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

124
    try {
3✔
125
      const store = ServerSettingsStore.getInstance();
3✔
126
      const maintenanceMode = await store.getSettingFromDatabase('maintenanceMode');
3✔
127
      res.status(200).json({
2✔
128
        maintenanceMode,
129
      } as ServerStatusResponse);
130
    } catch (e) {
131
      res.status(500).json('Internal server error.');
1✔
132
    }
133
  }
134

135
  /**
136
   * GET /terms-of-service/latest
137
   * @summary Get the latest terms of service version
138
   * @operationId getLatestTermsOfService
139
   * @tags terms-of-service - Operations of terms of service controller
140
   * @security JWT
141
   * @return {TermsOfServiceResponse} 200 - The requested terms of service version
142
   * @return {string} 500 - Internal server error
143
   */
144
  public async getLatestTOS(req: Request, res: Response): Promise<void> {
NEW
145
    try {
×
NEW
146
      res.json(await TermsOfServiceService.getLatestTermsOfService());
×
147
    } catch (error) {
NEW
148
      this.logger.error('Could not get latest Terms of Service', error);
×
NEW
149
      res.status(500).json('Internal server error.');
×
150
    }
151
  }
152
}
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