* feat(auth): add OAuth2 login with GitHub and Google * chore(translations): add files for Japanese * fix(auth): fix link function for GitHub * feat(oauth): basic oidc implementation * feat(oauth): oauth guard * fix: disable image optimizations for logo to prevent caching issues with custom logos * fix: memory leak while downloading large files * chore(translations): update translations via Crowdin (#278) * New translations en-us.ts (Japanese) * New translations en-us.ts (Japanese) * New translations en-us.ts (Japanese) * release: 0.18.2 * doc(translations): Add Japanese README (#279) * Added Japanese README. * Added JAPANESE README link to README.md. * Updated Japanese README. * Updated Environment Variable Table. * updated zh-cn README. * feat(oauth): unlink account * refactor(oauth): make providers extensible * fix(oauth): fix discoveryUri error when toggle google-enabled * feat(oauth): add microsoft and discord as oauth provider * docs(oauth): update README.md * docs(oauth): update oauth2-guide.md * set password to null for new oauth users * New translations en-us.ts (Japanese) (#281) * chore(translations): add Polish files * fix(oauth): fix random username and password * feat(oauth): add totp * fix(oauth): fix totp throttle * fix(oauth): fix qrcode and remove comment * feat(oauth): add error page * fix(oauth): i18n of error page * feat(auth): add OAuth2 login * fix(auth): fix link function for GitHub * feat(oauth): basic oidc implementation * feat(oauth): oauth guard * feat(oauth): unlink account * refactor(oauth): make providers extensible * fix(oauth): fix discoveryUri error when toggle google-enabled * feat(oauth): add microsoft and discord as oauth provider * docs(oauth): update README.md * docs(oauth): update oauth2-guide.md * set password to null for new oauth users * fix(oauth): fix random username and password * feat(oauth): add totp * fix(oauth): fix totp throttle * fix(oauth): fix qrcode and remove comment * feat(oauth): add error page * fix(oauth): i18n of error page * refactor: return null instead of `false` in `getIdOfCurrentUser` functiom * feat: show original oauth error if available * refactor: run formatter * refactor(oauth): error message i18n * refactor(oauth): make OAuth token available someone may use it (to revoke token or get other info etc.) also improved the i18n message * chore(oauth): remove unused import * chore: add database migration * fix: missing python installation for nanoid --------- Co-authored-by: Elias Schneider <login@eliasschneider.com> Co-authored-by: ふうせん <10260662+fusengum@users.noreply.github.com>
120 lines
3.2 KiB
TypeScript
120 lines
3.2 KiB
TypeScript
import {
|
|
BadRequestException,
|
|
Inject,
|
|
Injectable,
|
|
NotFoundException,
|
|
} from "@nestjs/common";
|
|
import { Config } from "@prisma/client";
|
|
import { PrismaService } from "src/prisma/prisma.service";
|
|
import { EventEmitter } from "events";
|
|
|
|
/**
|
|
* ConfigService extends EventEmitter to allow listening for config updates,
|
|
* now only `update` event will be emitted.
|
|
*/
|
|
@Injectable()
|
|
export class ConfigService extends EventEmitter {
|
|
constructor(
|
|
@Inject("CONFIG_VARIABLES") private configVariables: Config[],
|
|
private prisma: PrismaService,
|
|
) {
|
|
super();
|
|
}
|
|
|
|
get(key: `${string}.${string}`): any {
|
|
const configVariable = this.configVariables.filter(
|
|
(variable) => `${variable.category}.${variable.name}` == key,
|
|
)[0];
|
|
|
|
if (!configVariable) throw new Error(`Config variable ${key} not found`);
|
|
|
|
const value = configVariable.value ?? configVariable.defaultValue;
|
|
|
|
if (configVariable.type == "number") return parseInt(value);
|
|
if (configVariable.type == "boolean") return value == "true";
|
|
if (configVariable.type == "string" || configVariable.type == "text")
|
|
return value;
|
|
}
|
|
|
|
async getByCategory(category: string) {
|
|
const configVariables = await this.prisma.config.findMany({
|
|
orderBy: { order: "asc" },
|
|
where: { category, locked: { equals: false } },
|
|
});
|
|
|
|
return configVariables.map((variable) => {
|
|
return {
|
|
...variable,
|
|
key: `${variable.category}.${variable.name}`,
|
|
value: variable.value ?? variable.defaultValue,
|
|
};
|
|
});
|
|
}
|
|
|
|
async list() {
|
|
const configVariables = await this.prisma.config.findMany({
|
|
where: { secret: { equals: false } },
|
|
});
|
|
|
|
return configVariables.map((variable) => {
|
|
return {
|
|
...variable,
|
|
key: `${variable.category}.${variable.name}`,
|
|
value: variable.value ?? variable.defaultValue,
|
|
};
|
|
});
|
|
}
|
|
|
|
async updateMany(data: { key: string; value: string | number | boolean }[]) {
|
|
const response: Config[] = [];
|
|
|
|
for (const variable of data) {
|
|
response.push(await this.update(variable.key, variable.value));
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
async update(key: string, value: string | number | boolean) {
|
|
const configVariable = await this.prisma.config.findUnique({
|
|
where: {
|
|
name_category: {
|
|
category: key.split(".")[0],
|
|
name: key.split(".")[1],
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!configVariable || configVariable.locked)
|
|
throw new NotFoundException("Config variable not found");
|
|
|
|
if (value === "") {
|
|
value = null;
|
|
} else if (
|
|
typeof value != configVariable.type &&
|
|
typeof value == "string" &&
|
|
configVariable.type != "text"
|
|
) {
|
|
throw new BadRequestException(
|
|
`Config variable must be of type ${configVariable.type}`,
|
|
);
|
|
}
|
|
|
|
const updatedVariable = await this.prisma.config.update({
|
|
where: {
|
|
name_category: {
|
|
category: key.split(".")[0],
|
|
name: key.split(".")[1],
|
|
},
|
|
},
|
|
data: { value: value === null ? null : value.toString() },
|
|
});
|
|
|
|
this.configVariables = await this.prisma.config.findMany();
|
|
|
|
this.emit("update", key, value);
|
|
|
|
return updatedVariable;
|
|
}
|
|
}
|