gristlabs_grist-core/app/server/lib/InstallAdmin.ts
Dmitry S e380fcfa90 (core) Admin Panel and InstallAdmin class to identify installation admins.
Summary:
- Add InstallAdmin class to identify users who can manage Grist installation.

  This is overridable by different Grist flavors (e.g. different in SaaS).
  It generalizes previous logic used to decide who can control Activation
  settings (e.g. enable telemetry).

- Implement a basic Admin Panel at /admin, and move items previously in the
  "Support Grist" page into the "Support Grist" section of the Admin Panel.

- Replace "Support Grist" menu items with "Admin Panel" and show only to admins.

- Add "Support Grist" links to Github sponsorship to user-account menu.

- Add "Support Grist" button to top-bar, which
  - for admins, replaces the previous "Contribute" button and reopens the "Support Grist / opt-in to telemetry" nudge (unchanged)
  - for everyone else, links to Github sponsorship
  - in either case, user can dismiss it.

Test Plan: Shuffled some test cases between Support Grist and the new Admin Panel, and added some new cases.

Reviewers: jarek, paulfitz

Reviewed By: jarek, paulfitz

Differential Revision: https://phab.getgrist.com/D4194
2024-03-25 12:18:38 -04:00

53 lines
2.0 KiB
TypeScript

import {ApiError} from 'app/common/ApiError';
import {appSettings} from 'app/server/lib/AppSettings';
import {getUser, RequestWithLogin} from 'app/server/lib/Authorizer';
import {User} from 'app/gen-server/entity/User';
import express from 'express';
/**
* Class implementing the logic to determine whether a user is authorized to manage the Grist
* installation.
*/
export abstract class InstallAdmin {
// Returns true if user is authorized to manage the Grist installation.
public abstract isAdminUser(user: User): Promise<boolean>;
// Returns true if req is authenticated (contains a user) and the user is authorized to manage
// the Grist installation. This should not fail, only return true or false.
public async isAdminReq(req: express.Request): Promise<boolean> {
const user = (req as RequestWithLogin).user;
return user ? this.isAdminUser(user) : false;
}
// Returns middleware that fails unless the request includes an authenticated user and this user
// is authorized to manage the Grist installation.
public getMiddlewareRequireAdmin(): express.RequestHandler {
return this._requireAdmin.bind(this);
}
private async _requireAdmin(req: express.Request, resp: express.Response, next: express.NextFunction) {
try {
// getUser() will fail with 401 if user is not present.
if (!await this.isAdminUser(getUser(req))) {
throw new ApiError('Access denied', 403);
}
next();
} catch (err) {
next(err);
}
}
}
// Considers the user whose email matches GRIST_DEFAULT_EMAIL env var, if given, to be the
// installation admin. If not given, then there is no admin.
export class SimpleInstallAdmin extends InstallAdmin {
private _installAdminEmail = appSettings.section('access').flag('installAdminEmail').readString({
envVar: 'GRIST_DEFAULT_EMAIL',
});
public override async isAdminUser(user: User): Promise<boolean> {
return this._installAdminEmail ? (user.loginEmail === this._installAdminEmail) : false;
}
}