Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
511ae933fa | ||
|
|
df2521b192 | ||
|
|
8f16d6b53e | ||
|
|
3310fe53b3 | ||
|
|
adc4af996d | ||
|
|
61edc4f4f6 | ||
|
|
eba7984a0f | ||
|
|
69752b8b41 | ||
|
|
ee73293c0f | ||
|
|
5553607ffe | ||
|
|
2ca6e6ee5f | ||
|
|
18135b0ec0 | ||
|
|
f8bfb8ec3c | ||
|
|
187911e334 | ||
|
|
64acae11a2 | ||
|
|
6b39adfd03 | ||
|
|
d9cfe697d6 | ||
|
|
67a0fc6ea5 | ||
|
|
b13a81a88c | ||
|
|
97dc3ecfdd | ||
|
|
d00d52baa9 |
32
CHANGELOG.md
32
CHANGELOG.md
@@ -1,3 +1,35 @@
|
|||||||
|
## [1.1.3](https://github.com/stonith404/pingvin-share/compare/v1.1.2...v1.1.3) (2024-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* improve the LDAP implementation ([#615](https://github.com/stonith404/pingvin-share/issues/615)) ([3310fe5](https://github.com/stonith404/pingvin-share/commit/3310fe53b3e4c89db78d57ede6c8d57d8137ecc1)), closes [#601](https://github.com/stonith404/pingvin-share/issues/601)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* omit invalid username characters in oidc registration ([adc4af9](https://github.com/stonith404/pingvin-share/commit/adc4af996d30b295b06e4ee517aa53be62c0f6c1))
|
||||||
|
|
||||||
|
## [1.1.2](https://github.com/stonith404/pingvin-share/compare/v1.1.1...v1.1.2) (2024-09-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* disable auto complete for email recipients and share password ([ee73293](https://github.com/stonith404/pingvin-share/commit/ee73293c0f822d3e79cfefd096c656d4c36a12d1))
|
||||||
|
* enable secure cookies if app url starts with https ([69752b8](https://github.com/stonith404/pingvin-share/commit/69752b8b417edda1ab4a4acedbdda09d545d6df8))
|
||||||
|
|
||||||
|
## [1.1.1](https://github.com/stonith404/pingvin-share/compare/v1.1.0...v1.1.1) (2024-09-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add environment variable to trust the reverse proxy ([b13a81a](https://github.com/stonith404/pingvin-share/commit/b13a81a88ca871c5714b2ed52d0e12fb7ceca176))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* disable email login if ldap is enabled ([d9cfe69](https://github.com/stonith404/pingvin-share/commit/d9cfe697d66e9db7bfbc2252b3700580793ce9bb))
|
||||||
|
|
||||||
## [1.1.0](https://github.com/stonith404/pingvin-share/compare/v1.0.4...v1.1.0) (2024-09-14)
|
## [1.1.0](https://github.com/stonith404/pingvin-share/compare/v1.0.4...v1.1.0) (2024-09-14)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
15
Caddyfile
15
Caddyfile
@@ -1,15 +0,0 @@
|
|||||||
:3000 {
|
|
||||||
# Reverse proxy for /api
|
|
||||||
reverse_proxy /api/* http://localhost:8080 {
|
|
||||||
header_up X-Forwarded-Host {host}:{server_port}
|
|
||||||
header_up X-Forwarded-For {remote_host}
|
|
||||||
header_up X-Forwarded-Proto {scheme}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Reverse proxy for all other requests
|
|
||||||
reverse_proxy http://localhost:3333 {
|
|
||||||
header_up X-Forwarded-Host {host}:{server_port}
|
|
||||||
header_up X-Forwarded-For {remote_host}
|
|
||||||
header_up X-Forwarded-Proto {scheme}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -46,7 +46,7 @@ COPY --from=backend-builder /opt/app/dist ./dist
|
|||||||
COPY --from=backend-builder /opt/app/prisma ./prisma
|
COPY --from=backend-builder /opt/app/prisma ./prisma
|
||||||
COPY --from=backend-builder /opt/app/package.json ./
|
COPY --from=backend-builder /opt/app/package.json ./
|
||||||
|
|
||||||
COPY ./Caddyfile /etc/caddy/Caddyfile
|
COPY ./reverse-proxy /etc/caddy
|
||||||
COPY ./scripts/docker-entrypoint.sh /opt/app/docker-entrypoint.sh
|
COPY ./scripts/docker-entrypoint.sh /opt/app/docker-entrypoint.sh
|
||||||
|
|
||||||
WORKDIR /opt/app
|
WORKDIR /opt/app
|
||||||
|
|||||||
2132
backend/package-lock.json
generated
2132
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pingvin-share-backend",
|
"name": "pingvin-share-backend",
|
||||||
"version": "1.1.0",
|
"version": "1.1.3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nest build",
|
"build": "nest build",
|
||||||
"dev": "cross-env NODE_ENV=development nest start --watch",
|
"dev": "cross-env NODE_ENV=development nest start --watch",
|
||||||
@@ -14,74 +14,73 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nestjs/cache-manager": "^2.2.2",
|
"@nestjs/cache-manager": "^2.2.2",
|
||||||
"@nestjs/common": "^10.3.9",
|
"@nestjs/common": "^10.4.3",
|
||||||
"@nestjs/config": "^3.2.2",
|
"@nestjs/config": "^3.2.3",
|
||||||
"@nestjs/core": "^10.3.9",
|
"@nestjs/core": "^10.4.3",
|
||||||
"@nestjs/jwt": "^10.2.0",
|
"@nestjs/jwt": "^10.2.0",
|
||||||
"@nestjs/passport": "^10.0.3",
|
"@nestjs/passport": "^10.0.3",
|
||||||
"@nestjs/platform-express": "^10.3.9",
|
"@nestjs/platform-express": "^10.4.3",
|
||||||
"@nestjs/schedule": "^4.0.2",
|
"@nestjs/schedule": "^4.1.1",
|
||||||
"@nestjs/swagger": "^7.3.1",
|
"@nestjs/swagger": "^7.4.2",
|
||||||
"@nestjs/throttler": "^5.2.0",
|
"@nestjs/throttler": "^6.2.1",
|
||||||
"@prisma/client": "^5.16.1",
|
"@prisma/client": "^5.19.1",
|
||||||
"@types/jmespath": "^0.15.2",
|
"@types/jmespath": "^0.15.2",
|
||||||
"@types/ldapjs": "^3.0.6",
|
|
||||||
"archiver": "^7.0.1",
|
"archiver": "^7.0.1",
|
||||||
"argon2": "^0.40.3",
|
"argon2": "^0.41.1",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.3",
|
||||||
"cache-manager": "^5.6.1",
|
"cache-manager": "^5.7.6",
|
||||||
"clamscan": "^2.2.1",
|
"clamscan": "^2.3.1",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.1",
|
"class-validator": "^0.14.1",
|
||||||
"content-disposition": "^0.5.4",
|
"content-disposition": "^0.5.4",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"jmespath": "^0.16.0",
|
"jmespath": "^0.16.0",
|
||||||
"ldapjs": "^3.0.7",
|
"ldapts": "^7.2.0",
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"nanoid": "^3.3.7",
|
"nanoid": "^3.3.7",
|
||||||
"nodemailer": "^6.9.14",
|
"nodemailer": "^6.9.15",
|
||||||
"otplib": "^12.0.1",
|
"otplib": "^12.0.1",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"qrcode-svg": "^1.1.0",
|
"qrcode-svg": "^1.1.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rimraf": "^5.0.7",
|
"rimraf": "^6.0.1",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"sharp": "^0.33.4",
|
"sharp": "^0.33.5",
|
||||||
"ts-node": "^10.9.2"
|
"ts-node": "^10.9.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nestjs/cli": "^10.3.2",
|
"@nestjs/cli": "^10.4.5",
|
||||||
"@nestjs/schematics": "^10.1.1",
|
"@nestjs/schematics": "^10.1.4",
|
||||||
"@nestjs/testing": "^10.3.9",
|
"@nestjs/testing": "^10.4.3",
|
||||||
"@types/archiver": "^6.0.2",
|
"@types/archiver": "^6.0.2",
|
||||||
"@types/clamscan": "^2.0.8",
|
"@types/clamscan": "^2.0.8",
|
||||||
"@types/cookie-parser": "^1.4.7",
|
"@types/cookie-parser": "^1.4.7",
|
||||||
"@types/cron": "^2.0.1",
|
"@types/cron": "^2.4.0",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/mime-types": "^2.1.4",
|
"@types/mime-types": "^2.1.4",
|
||||||
"@types/multer": "^1.4.11",
|
"@types/multer": "^1.4.12",
|
||||||
"@types/node": "^20.14.9",
|
"@types/node": "^22.5.5",
|
||||||
"@types/nodemailer": "^6.4.15",
|
"@types/nodemailer": "^6.4.16",
|
||||||
"@types/passport-jwt": "^4.0.1",
|
"@types/passport-jwt": "^4.0.1",
|
||||||
"@types/qrcode-svg": "^1.1.4",
|
"@types/qrcode-svg": "^1.1.5",
|
||||||
"@types/sharp": "^0.31.1",
|
"@types/sharp": "^0.32.0",
|
||||||
"@types/supertest": "^6.0.2",
|
"@types/supertest": "^6.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
"@typescript-eslint/eslint-plugin": "^8.6.0",
|
||||||
"@typescript-eslint/parser": "^7.14.1",
|
"@typescript-eslint/parser": "^8.6.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^9.10.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"newman": "^6.1.3",
|
"newman": "^6.2.1",
|
||||||
"prettier": "^3.3.2",
|
"prettier": "^3.3.3",
|
||||||
"prisma": "^5.16.1",
|
"prisma": "^5.19.1",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"ts-loader": "^9.5.1",
|
"ts-loader": "^9.5.1",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"typescript": "^5.5.2",
|
"typescript": "^5.6.2",
|
||||||
"wait-on": "^7.2.0"
|
"wait-on": "^8.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,6 +178,15 @@ const configVariables: ConfigVariables = {
|
|||||||
adminGroups: {
|
adminGroups: {
|
||||||
type: "string",
|
type: "string",
|
||||||
defaultValue: ""
|
defaultValue: ""
|
||||||
|
},
|
||||||
|
|
||||||
|
fieldNameMemberOf: {
|
||||||
|
type: "string",
|
||||||
|
defaultValue: "memberOf",
|
||||||
|
},
|
||||||
|
fieldNameEmail: {
|
||||||
|
type: "string",
|
||||||
|
defaultValue: "userPrincipalName",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
oauth: {
|
oauth: {
|
||||||
|
|||||||
@@ -173,11 +173,17 @@ export class AuthController {
|
|||||||
@Res({ passthrough: true }) response: Response,
|
@Res({ passthrough: true }) response: Response,
|
||||||
) {
|
) {
|
||||||
await this.authService.signOut(request.cookies.access_token);
|
await this.authService.signOut(request.cookies.access_token);
|
||||||
response.cookie("access_token", "accessToken", { maxAge: -1 });
|
|
||||||
|
const isSecure = this.config.get("general.appUrl").startsWith("https");
|
||||||
|
response.cookie("access_token", "accessToken", {
|
||||||
|
maxAge: -1,
|
||||||
|
secure: isSecure,
|
||||||
|
});
|
||||||
response.cookie("refresh_token", "", {
|
response.cookie("refresh_token", "", {
|
||||||
path: "/api/auth/token",
|
path: "/api/auth/token",
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
maxAge: -1,
|
maxAge: -1,
|
||||||
|
secure: isSecure,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,8 +66,9 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async signIn(dto: AuthSignInDTO, ip: string) {
|
async signIn(dto: AuthSignInDTO, ip: string) {
|
||||||
if (!dto.email && !dto.username)
|
if (!dto.email && !dto.username) {
|
||||||
throw new BadRequestException("Email or username is required");
|
throw new BadRequestException("Email or username is required");
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.config.get("oauth.disablePassword")) {
|
if (!this.config.get("oauth.disablePassword")) {
|
||||||
const user = await this.prisma.user.findFirst({
|
const user = await this.prisma.user.findFirst({
|
||||||
@@ -85,18 +86,22 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.config.get("ldap.enabled")) {
|
if (this.config.get("ldap.enabled")) {
|
||||||
this.logger.debug(`Trying LDAP login for user ${dto.username}`);
|
/*
|
||||||
|
* E-mail-like user credentials are passed as the email property
|
||||||
|
* instead of the username. Since the username format does not matter
|
||||||
|
* when searching for users in LDAP, we simply use the username
|
||||||
|
* in whatever format it is provided.
|
||||||
|
*/
|
||||||
|
const ldapUsername = dto.username || dto.email;
|
||||||
|
this.logger.debug(`Trying LDAP login for user ${ldapUsername}`);
|
||||||
const ldapUser = await this.ldapService.authenticateUser(
|
const ldapUser = await this.ldapService.authenticateUser(
|
||||||
dto.username,
|
ldapUsername,
|
||||||
dto.password,
|
dto.password,
|
||||||
);
|
);
|
||||||
if (ldapUser) {
|
if (ldapUser) {
|
||||||
const user = await this.userService.findOrCreateFromLDAP(
|
const user = await this.userService.findOrCreateFromLDAP(dto, ldapUser);
|
||||||
dto.username,
|
|
||||||
ldapUser,
|
|
||||||
);
|
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`Successful LDAP login for user ${user.email} from IP ${ip}`,
|
`Successful LDAP login for user ${ldapUsername} (${user.id}) from IP ${ip}`,
|
||||||
);
|
);
|
||||||
return this.generateToken(user);
|
return this.generateToken(user);
|
||||||
}
|
}
|
||||||
@@ -272,9 +277,11 @@ export class AuthService {
|
|||||||
refreshToken?: string,
|
refreshToken?: string,
|
||||||
accessToken?: string,
|
accessToken?: string,
|
||||||
) {
|
) {
|
||||||
|
const isSecure = this.config.get("general.appUrl").startsWith("https");
|
||||||
if (accessToken)
|
if (accessToken)
|
||||||
response.cookie("access_token", accessToken, {
|
response.cookie("access_token", accessToken, {
|
||||||
sameSite: "lax",
|
sameSite: "lax",
|
||||||
|
secure: isSecure,
|
||||||
maxAge: 1000 * 60 * 60 * 24 * 30 * 3, // 3 months
|
maxAge: 1000 * 60 * 60 * 24 * 30 * 3, // 3 months
|
||||||
});
|
});
|
||||||
if (refreshToken)
|
if (refreshToken)
|
||||||
@@ -282,6 +289,7 @@ export class AuthService {
|
|||||||
path: "/api/auth/token",
|
path: "/api/auth/token",
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
sameSite: "strict",
|
sameSite: "strict",
|
||||||
|
secure: isSecure,
|
||||||
maxAge: 1000 * 60 * 60 * this.config.get("general.sessionDuration"),
|
maxAge: 1000 * 60 * 60 * this.config.get("general.sessionDuration"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,101 +1,7 @@
|
|||||||
import { Inject, Injectable, Logger } from "@nestjs/common";
|
import { Inject, Injectable, Logger } from "@nestjs/common";
|
||||||
import * as ldap from "ldapjs";
|
|
||||||
import {
|
|
||||||
AttributeJson,
|
|
||||||
InvalidCredentialsError,
|
|
||||||
SearchCallbackResponse,
|
|
||||||
SearchOptions,
|
|
||||||
} from "ldapjs";
|
|
||||||
import { inspect } from "node:util";
|
import { inspect } from "node:util";
|
||||||
import { ConfigService } from "../config/config.service";
|
import { ConfigService } from "../config/config.service";
|
||||||
|
import { Client, Entry, InvalidCredentialsError } from "ldapts";
|
||||||
type LdapSearchEntry = {
|
|
||||||
objectName: string;
|
|
||||||
attributes: AttributeJson[];
|
|
||||||
};
|
|
||||||
|
|
||||||
async function ldapExecuteSearch(
|
|
||||||
client: ldap.Client,
|
|
||||||
base: string,
|
|
||||||
options: SearchOptions,
|
|
||||||
): Promise<LdapSearchEntry[]> {
|
|
||||||
const searchResponse = await new Promise<SearchCallbackResponse>(
|
|
||||||
(resolve, reject) => {
|
|
||||||
client.search(base, options, (err, res) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve(res);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return await new Promise<any[]>((resolve, reject) => {
|
|
||||||
const entries: LdapSearchEntry[] = [];
|
|
||||||
searchResponse.on("searchEntry", (entry) =>
|
|
||||||
entries.push({
|
|
||||||
attributes: entry.pojo.attributes,
|
|
||||||
objectName: entry.pojo.objectName,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
searchResponse.once("error", reject);
|
|
||||||
searchResponse.once("end", () => resolve(entries));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ldapBindUser(
|
|
||||||
client: ldap.Client,
|
|
||||||
dn: string,
|
|
||||||
password: string,
|
|
||||||
): Promise<void> {
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
|
||||||
client.bind(dn, password, (error) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ldapCreateConnection(
|
|
||||||
logger: Logger,
|
|
||||||
url: string,
|
|
||||||
): Promise<ldap.Client> {
|
|
||||||
const ldapClient = ldap.createClient({
|
|
||||||
url: url.split(","),
|
|
||||||
connectTimeout: 10_000,
|
|
||||||
timeout: 10_000,
|
|
||||||
});
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
ldapClient.once("error", reject);
|
|
||||||
ldapClient.on("setupError", reject);
|
|
||||||
ldapClient.on("socketTimeout", reject);
|
|
||||||
ldapClient.on("connectRefused", () =>
|
|
||||||
reject(new Error("connection has been refused")),
|
|
||||||
);
|
|
||||||
ldapClient.on("connectTimeout", () =>
|
|
||||||
reject(new Error("connect timed out")),
|
|
||||||
);
|
|
||||||
ldapClient.on("connectError", reject);
|
|
||||||
|
|
||||||
ldapClient.on("connect", resolve);
|
|
||||||
}).catch((error) => {
|
|
||||||
logger.error(`Connect error: ${inspect(error)}`);
|
|
||||||
ldapClient.destroy();
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
|
|
||||||
return ldapClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type LdapAuthenticateResult = {
|
|
||||||
userDn: string;
|
|
||||||
attributes: Record<string, string[]>;
|
|
||||||
};
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LdapService {
|
export class LdapService {
|
||||||
@@ -105,40 +11,42 @@ export class LdapService {
|
|||||||
private readonly serviceConfig: ConfigService,
|
private readonly serviceConfig: ConfigService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
private async createLdapConnection(): Promise<ldap.Client> {
|
private async createLdapConnection(): Promise<Client> {
|
||||||
const ldapUrl = this.serviceConfig.get("ldap.url");
|
const ldapUrl = this.serviceConfig.get("ldap.url");
|
||||||
if (!ldapUrl) {
|
if (!ldapUrl) {
|
||||||
throw new Error("LDAP server URL is not defined");
|
throw new Error("LDAP server URL is not defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
const ldapClient = await ldapCreateConnection(this.logger, ldapUrl);
|
const ldapClient = new Client({
|
||||||
try {
|
url: ldapUrl,
|
||||||
const bindDn = this.serviceConfig.get("ldap.bindDn") || null;
|
timeout: 15_000,
|
||||||
if (bindDn) {
|
connectTimeout: 15_000,
|
||||||
try {
|
});
|
||||||
await ldapBindUser(
|
|
||||||
ldapClient,
|
|
||||||
bindDn,
|
|
||||||
this.serviceConfig.get("ldap.bindPassword"),
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.warn(`Failed to bind to default user: ${error}`);
|
|
||||||
throw new Error("failed to bind to default user");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ldapClient;
|
const bindDn = this.serviceConfig.get("ldap.bindDn") || null;
|
||||||
} catch (error) {
|
if (bindDn) {
|
||||||
ldapClient.destroy();
|
try {
|
||||||
throw error;
|
await ldapClient.bind(
|
||||||
|
bindDn,
|
||||||
|
this.serviceConfig.get("ldap.bindPassword"),
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.warn(`Failed to bind to default user: ${error}`);
|
||||||
|
throw new Error("failed to bind to default user");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ldapClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async authenticateUser(
|
public async authenticateUser(
|
||||||
username: string,
|
username: string,
|
||||||
password: string,
|
password: string,
|
||||||
): Promise<LdapAuthenticateResult | null> {
|
): Promise<Entry | null> {
|
||||||
if (!username.match(/^[a-zA-Z0-0]+$/)) {
|
if (!username.match(/^[a-zA-Z0-9-_.@]+$/)) {
|
||||||
|
this.logger.verbose(
|
||||||
|
`Username ${username} does not match username pattern. Authentication failed.`,
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,45 +57,48 @@ export class LdapService {
|
|||||||
|
|
||||||
const ldapClient = await this.createLdapConnection();
|
const ldapClient = await this.createLdapConnection();
|
||||||
try {
|
try {
|
||||||
const [result] = await ldapExecuteSearch(ldapClient, searchBase, {
|
const { searchEntries } = await ldapClient.search(searchBase, {
|
||||||
filter: searchQuery,
|
filter: searchQuery,
|
||||||
scope: "sub",
|
scope: "sub",
|
||||||
|
|
||||||
|
attributes: ["*"],
|
||||||
|
returnAttributeValues: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!result) {
|
if (searchEntries.length > 1) {
|
||||||
|
/* too many users found */
|
||||||
|
this.logger.verbose(
|
||||||
|
`Authentication for username ${username} failed. Too many users found with query ${searchQuery}`,
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
} else if (searchEntries.length == 0) {
|
||||||
/* user not found */
|
/* user not found */
|
||||||
|
this.logger.verbose(
|
||||||
|
`Authentication for username ${username} failed. No user found with query ${searchQuery}`,
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const targetEntity = searchEntries[0];
|
||||||
|
this.logger.verbose(
|
||||||
|
`Trying to authenticate ${username} against LDAP user ${targetEntity.dn}`,
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
await ldapBindUser(ldapClient, result.objectName, password);
|
await ldapClient.bind(targetEntity.dn, password);
|
||||||
|
return targetEntity;
|
||||||
/*
|
|
||||||
* In theory we could query the user attributes now,
|
|
||||||
* but as we must query the user attributes for validation anyways
|
|
||||||
* we'll create a second ldap server connection.
|
|
||||||
*/
|
|
||||||
return {
|
|
||||||
userDn: result.objectName,
|
|
||||||
attributes: Object.fromEntries(
|
|
||||||
result.attributes.map((attribute) => [
|
|
||||||
attribute.type,
|
|
||||||
attribute.values,
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof InvalidCredentialsError) {
|
if (error instanceof InvalidCredentialsError) {
|
||||||
|
this.logger.verbose(
|
||||||
|
`Failed to authenticate ${username} against ${targetEntity.dn}. Invalid credentials.`,
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.warn(`LDAP user bind failure: ${inspect(error)}`);
|
this.logger.warn(`User bind failure: ${inspect(error)}`);
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
|
||||||
ldapClient.destroy();
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.warn(`LDAP connect error: ${inspect(error)}`);
|
this.logger.warn(`Connect error: ${inspect(error)}`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { LogLevel } from "@nestjs/common";
|
||||||
|
|
||||||
export const DATA_DIRECTORY = process.env.DATA_DIRECTORY || "./data";
|
export const DATA_DIRECTORY = process.env.DATA_DIRECTORY || "./data";
|
||||||
export const SHARE_DIRECTORY = `${DATA_DIRECTORY}/uploads/shares`;
|
export const SHARE_DIRECTORY = `${DATA_DIRECTORY}/uploads/shares`;
|
||||||
export const DATABASE_URL =
|
export const DATABASE_URL =
|
||||||
@@ -7,3 +9,7 @@ export const CLAMAV_HOST =
|
|||||||
process.env.CLAMAV_HOST ||
|
process.env.CLAMAV_HOST ||
|
||||||
(process.env.NODE_ENV == "docker" ? "clamav" : "127.0.0.1");
|
(process.env.NODE_ENV == "docker" ? "clamav" : "127.0.0.1");
|
||||||
export const CLAMAV_PORT = parseInt(process.env.CLAMAV_PORT) || 3310;
|
export const CLAMAV_PORT = parseInt(process.env.CLAMAV_PORT) || 3310;
|
||||||
|
|
||||||
|
export const LOG_LEVEL_AVAILABLE: LogLevel[] = ['verbose', 'debug', 'log', 'warn', 'error', 'fatal'];
|
||||||
|
export const LOG_LEVEL_DEFAULT: LogLevel = process.env.NODE_ENV === 'development' ? "verbose" : "log";
|
||||||
|
export const LOG_LEVEL_ENV = `${process.env.PV_LOG_LEVEL || ""}`;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ClassSerializerInterceptor,
|
ClassSerializerInterceptor,
|
||||||
Logger,
|
Logger,
|
||||||
|
LogLevel,
|
||||||
ValidationPipe,
|
ValidationPipe,
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
import { NestFactory, Reflector } from "@nestjs/core";
|
import { NestFactory, Reflector } from "@nestjs/core";
|
||||||
@@ -12,10 +13,35 @@ import { NextFunction, Request, Response } from "express";
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { AppModule } from "./app.module";
|
import { AppModule } from "./app.module";
|
||||||
import { ConfigService } from "./config/config.service";
|
import { ConfigService } from "./config/config.service";
|
||||||
import { DATA_DIRECTORY } from "./constants";
|
import {
|
||||||
|
DATA_DIRECTORY,
|
||||||
|
LOG_LEVEL_AVAILABLE,
|
||||||
|
LOG_LEVEL_DEFAULT,
|
||||||
|
LOG_LEVEL_ENV,
|
||||||
|
} from "./constants";
|
||||||
|
|
||||||
|
function generateNestJsLogLevels(): LogLevel[] {
|
||||||
|
if (LOG_LEVEL_ENV) {
|
||||||
|
const levelIndex = LOG_LEVEL_AVAILABLE.indexOf(LOG_LEVEL_ENV as any);
|
||||||
|
if (levelIndex === -1) {
|
||||||
|
throw new Error(`log level ${LOG_LEVEL_ENV} unknown`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LOG_LEVEL_AVAILABLE.slice(levelIndex, LOG_LEVEL_AVAILABLE.length);
|
||||||
|
} else {
|
||||||
|
const levelIndex = LOG_LEVEL_AVAILABLE.indexOf(LOG_LEVEL_DEFAULT);
|
||||||
|
return LOG_LEVEL_AVAILABLE.slice(levelIndex, LOG_LEVEL_AVAILABLE.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
const logLevels = generateNestJsLogLevels();
|
||||||
|
Logger.log(`Showing ${logLevels.join(", ")} messages`);
|
||||||
|
|
||||||
|
const app = await NestFactory.create<NestExpressApplication>(AppModule, {
|
||||||
|
logger: logLevels,
|
||||||
|
});
|
||||||
|
|
||||||
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
|
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
|
||||||
app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
|
app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
|
||||||
|
|
||||||
|
|||||||
@@ -108,8 +108,10 @@ export class OAuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getAvailableUsername(preferredUsername: string) {
|
private async getAvailableUsername(preferredUsername: string) {
|
||||||
// only remove + and - from preferred username for now (maybe not enough)
|
// Only keep letters, numbers, dots, and underscores. Truncate to 20 characters.
|
||||||
let username = preferredUsername.replace(/[+-]/g, "").substring(0, 20);
|
let username = preferredUsername
|
||||||
|
.replace(/[^a-zA-Z0-9._]/g, "")
|
||||||
|
.substring(0, 20);
|
||||||
while (true) {
|
while (true) {
|
||||||
const user = await this.prisma.user.findFirst({
|
const user = await this.prisma.user.findFirst({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Injectable } from "@nestjs/common";
|
import { Injectable, Logger } from "@nestjs/common";
|
||||||
import { PrismaClient } from "@prisma/client";
|
import { PrismaClient } from "@prisma/client";
|
||||||
import { DATABASE_URL } from "../constants";
|
import { DATABASE_URL } from "../constants";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PrismaService extends PrismaClient {
|
export class PrismaService extends PrismaClient {
|
||||||
|
private readonly logger = new Logger(PrismaService.name);
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
datasources: {
|
datasources: {
|
||||||
@@ -12,6 +14,6 @@ export class PrismaService extends PrismaClient {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
super.$connect().then(() => console.info("Connected to the database"));
|
super.$connect().then(() => this.logger.log("Connected to the database"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,14 @@ import { UpdateOwnUserDTO } from "./dto/updateOwnUser.dto";
|
|||||||
import { UpdateUserDto } from "./dto/updateUser.dto";
|
import { UpdateUserDto } from "./dto/updateUser.dto";
|
||||||
import { UserDTO } from "./dto/user.dto";
|
import { UserDTO } from "./dto/user.dto";
|
||||||
import { UserSevice } from "./user.service";
|
import { UserSevice } from "./user.service";
|
||||||
|
import { ConfigService } from "../config/config.service";
|
||||||
|
|
||||||
@Controller("users")
|
@Controller("users")
|
||||||
export class UserController {
|
export class UserController {
|
||||||
constructor(private userService: UserSevice) {}
|
constructor(
|
||||||
|
private userService: UserSevice,
|
||||||
|
private config: ConfigService,
|
||||||
|
) {}
|
||||||
|
|
||||||
// Own user operations
|
// Own user operations
|
||||||
@Get("me")
|
@Get("me")
|
||||||
@@ -49,11 +53,17 @@ export class UserController {
|
|||||||
@GetUser() user: User,
|
@GetUser() user: User,
|
||||||
@Res({ passthrough: true }) response: Response,
|
@Res({ passthrough: true }) response: Response,
|
||||||
) {
|
) {
|
||||||
response.cookie("access_token", "accessToken", { maxAge: -1 });
|
const isSecure = this.config.get("general.appUrl").startsWith("https");
|
||||||
|
|
||||||
|
response.cookie("access_token", "accessToken", {
|
||||||
|
maxAge: -1,
|
||||||
|
secure: isSecure,
|
||||||
|
});
|
||||||
response.cookie("refresh_token", "", {
|
response.cookie("refresh_token", "", {
|
||||||
path: "/api/auth/token",
|
path: "/api/auth/token",
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
maxAge: -1,
|
maxAge: -1,
|
||||||
|
secure: isSecure,
|
||||||
});
|
});
|
||||||
return new UserDTO().from(await this.userService.delete(user.id));
|
return new UserDTO().from(await this.userService.delete(user.id));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BadRequestException, Injectable } from "@nestjs/common";
|
import { BadRequestException, Injectable, Logger } from "@nestjs/common";
|
||||||
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
|
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
|
||||||
import * as argon from "argon2";
|
import * as argon from "argon2";
|
||||||
import * as crypto from "crypto";
|
import * as crypto from "crypto";
|
||||||
@@ -8,10 +8,14 @@ import { FileService } from "../file/file.service";
|
|||||||
import { CreateUserDTO } from "./dto/createUser.dto";
|
import { CreateUserDTO } from "./dto/createUser.dto";
|
||||||
import { UpdateUserDto } from "./dto/updateUser.dto";
|
import { UpdateUserDto } from "./dto/updateUser.dto";
|
||||||
import { ConfigService } from "../config/config.service";
|
import { ConfigService } from "../config/config.service";
|
||||||
import { LdapAuthenticateResult } from "../auth/ldap.service";
|
import { Entry } from "ldapts";
|
||||||
|
import { AuthSignInDTO } from "src/auth/dto/authSignIn.dto";
|
||||||
|
import { inspect } from "util";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserSevice {
|
export class UserSevice {
|
||||||
|
private readonly logger = new Logger(UserSevice.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private prisma: PrismaService,
|
private prisma: PrismaService,
|
||||||
private emailService: EmailService,
|
private emailService: EmailService,
|
||||||
@@ -92,33 +96,114 @@ export class UserSevice {
|
|||||||
return await this.prisma.user.delete({ where: { id } });
|
return await this.prisma.user.delete({ where: { id } });
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOrCreateFromLDAP(username: string, ldap: LdapAuthenticateResult) {
|
async findOrCreateFromLDAP(
|
||||||
const passwordHash = await argon.hash(crypto.randomUUID());
|
providedCredentials: AuthSignInDTO,
|
||||||
const userEmail =
|
ldapEntry: Entry,
|
||||||
ldap.attributes["userPrincipalName"]?.at(0) ??
|
) {
|
||||||
`${crypto.randomUUID()}@ldap.local`;
|
const fieldNameMemberOf = this.configService.get("ldap.fieldNameMemberOf");
|
||||||
const adminGroup = this.configService.get("ldap.adminGroups");
|
const fieldNameEmail = this.configService.get("ldap.fieldNameEmail");
|
||||||
const isAdmin = ldap.attributes["memberOf"]?.includes(adminGroup) ?? false;
|
|
||||||
|
let isAdmin = false;
|
||||||
|
if (fieldNameMemberOf in ldapEntry) {
|
||||||
|
const adminGroup = this.configService.get("ldap.adminGroups");
|
||||||
|
const entryGroups = Array.isArray(ldapEntry[fieldNameMemberOf])
|
||||||
|
? ldapEntry[fieldNameMemberOf]
|
||||||
|
: [ldapEntry[fieldNameMemberOf]];
|
||||||
|
isAdmin = entryGroups.includes(adminGroup) ?? false;
|
||||||
|
} else {
|
||||||
|
this.logger.warn(
|
||||||
|
`Trying to create/update a ldap user but the member field ${fieldNameMemberOf} is not present.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let userEmail: string | null = null;
|
||||||
|
if (fieldNameEmail in ldapEntry) {
|
||||||
|
const value = Array.isArray(ldapEntry[fieldNameEmail])
|
||||||
|
? ldapEntry[fieldNameEmail][0]
|
||||||
|
: ldapEntry[fieldNameEmail];
|
||||||
|
if (value) {
|
||||||
|
userEmail = value.toString();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.logger.warn(
|
||||||
|
`Trying to create/update a ldap user but the email field ${fieldNameEmail} is not present.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (providedCredentials.email) {
|
||||||
|
/* if LDAP does not provides an users email address, take the user provided email address instead */
|
||||||
|
userEmail = providedCredentials.email;
|
||||||
|
}
|
||||||
|
|
||||||
|
const randomId = crypto.randomUUID();
|
||||||
|
const placeholderUsername = `ldap_user_${randomId}`;
|
||||||
|
const placeholderEMail = `${randomId}@ldap.local`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await this.prisma.user.upsert({
|
const user = await this.prisma.user.upsert({
|
||||||
create: {
|
create: {
|
||||||
username,
|
username: providedCredentials.username ?? placeholderUsername,
|
||||||
email: userEmail,
|
email: userEmail ?? placeholderEMail,
|
||||||
password: passwordHash,
|
password: await argon.hash(crypto.randomUUID()),
|
||||||
isAdmin,
|
|
||||||
ldapDN: ldap.userDn,
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
username,
|
|
||||||
email: userEmail,
|
|
||||||
|
|
||||||
isAdmin,
|
isAdmin,
|
||||||
ldapDN: ldap.userDn,
|
ldapDN: ldapEntry.dn,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
isAdmin,
|
||||||
|
ldapDN: ldapEntry.dn,
|
||||||
},
|
},
|
||||||
where: {
|
where: {
|
||||||
ldapDN: ldap.userDn,
|
ldapDN: ldapEntry.dn,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (user.username === placeholderUsername) {
|
||||||
|
/* Give the user a human readable name if the user has been created with a placeholder username */
|
||||||
|
await this.prisma.user
|
||||||
|
.update({
|
||||||
|
where: {
|
||||||
|
id: user.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
username: `user_${user.id}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((newUser) => {
|
||||||
|
user.username = newUser.username;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.logger.warn(
|
||||||
|
`Failed to update users ${user.id} placeholder username: ${inspect(error)}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userEmail && userEmail !== user.email) {
|
||||||
|
/* Sync users email if it has changed */
|
||||||
|
await this.prisma.user
|
||||||
|
.update({
|
||||||
|
where: {
|
||||||
|
id: user.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
email: userEmail,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((newUser) => {
|
||||||
|
this.logger.log(
|
||||||
|
`Updated users ${user.id} email from ldap from ${user.email} to ${userEmail}.`,
|
||||||
|
);
|
||||||
|
user.email = newUser.email;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.logger.error(
|
||||||
|
`Failed to update users ${user.id} email to ${userEmail}: ${inspect(error)}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof PrismaClientKnownRequestError) {
|
if (e instanceof PrismaClientKnownRequestError) {
|
||||||
if (e.code == "P2002") {
|
if (e.code == "P2002") {
|
||||||
|
|||||||
@@ -4,15 +4,11 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
|
environment:
|
||||||
|
- TRUST_PROXY=false # Set to true if a reverse proxy is in front of the container
|
||||||
volumes:
|
volumes:
|
||||||
- "./data:/opt/app/backend/data"
|
- "./data:/opt/app/backend/data"
|
||||||
- "./data/images:/opt/app/frontend/public/img"
|
- "./data/images:/opt/app/frontend/public/img"
|
||||||
# Optional: If you add ClamAV, uncomment the following to have ClamAV start first.
|
|
||||||
# depends_on:
|
# To add ClamAV, to scan your shares for malicious files,
|
||||||
# clamav:
|
# see https://stonith404.github.io/pingvin-share/setup/integrations/#clamav-docker-only
|
||||||
# condition: service_healthy
|
|
||||||
# Optional: Add ClamAV (see README.md)
|
|
||||||
# ClamAV is currently only available for AMD64 see https://github.com/Cisco-Talos/clamav/issues/482
|
|
||||||
# clamav:
|
|
||||||
# restart: unless-stopped
|
|
||||||
# image: clamav/clamav
|
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ For installation specific configuration, you can use environment variables. The
|
|||||||
|
|
||||||
#### Backend
|
#### Backend
|
||||||
|
|
||||||
| Variable | Default Value | Description |
|
| Variable | Default Value | Description |
|
||||||
| ---------------- | -------------------------------------------------- | -------------------------------------- |
|
| ---------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||||
| `PORT` | `8080` | The port on which the backend listens. |
|
| `PORT` | `8080` | The port on which the backend listens. |
|
||||||
| `DATABASE_URL` | `file:../data/pingvin-share.db?connection_limit=1` | The URL of the SQLite database. |
|
| `DATABASE_URL` | `file:../data/pingvin-share.db?connection_limit=1` | The URL of the SQLite database. |
|
||||||
| `DATA_DIRECTORY` | `./data` | The directory where data is stored. |
|
| `DATA_DIRECTORY` | `./data` | The directory where data is stored. |
|
||||||
| `CLAMAV_HOST` | `127.0.0.1` | The IP address of the ClamAV server. |
|
| `CLAMAV_HOST` | `127.0.0.1` or `clamav` when running with Docker | The IP address of the ClamAV server. See the [ClamAV docs](integrations.md#clamav) for more information. |
|
||||||
| `CLAMAV_PORT` | `3310` | The port number of the ClamAV server. |
|
| `CLAMAV_PORT` | `3310` | The port number of the ClamAV server. |
|
||||||
|
|
||||||
#### Frontend
|
#### Frontend
|
||||||
|
|
||||||
@@ -48,3 +48,9 @@ For installation specific configuration, you can use environment variables. The
|
|||||||
| --------- | ----------------------- | ---------------------------------------- |
|
| --------- | ----------------------- | ---------------------------------------- |
|
||||||
| `PORT` | `3000` | The port on which the frontend listens. |
|
| `PORT` | `3000` | The port on which the frontend listens. |
|
||||||
| `API_URL` | `http://localhost:8080` | The URL of the backend for the frontend. |
|
| `API_URL` | `http://localhost:8080` | The URL of the backend for the frontend. |
|
||||||
|
|
||||||
|
#### Reverse Proxy (inside the Docker container)
|
||||||
|
|
||||||
|
| Variable | Default Value | Description |
|
||||||
|
| ------------- | ------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `TRUST_PROXY` | `false` | Whether Pingvin Share is behind a reverse proxy. If set to `true`, the `X-Forwarded-For` header is trusted. |
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ cd ../frontend
|
|||||||
npm install
|
npm install
|
||||||
npm run build
|
npm run build
|
||||||
API_URL=http://localhost:8080 # Set the URL of the backend, default: http://localhost:8080
|
API_URL=http://localhost:8080 # Set the URL of the backend, default: http://localhost:8080
|
||||||
pm2 start --name="pingvin-share-frontend" .next/standalone/server.js
|
pm2 start npm --name "pingvin-share-frontend" -- run start
|
||||||
```
|
```
|
||||||
|
|
||||||
**Uploading Large Files**: By default, Pingvin Share uses a built-in reverse proxy to reduce the installation steps. However, this reverse proxy is not optimized for uploading large files. If you wish to upload larger files, you can either use the Docker installation or set up your own reverse proxy. An example configuration for Caddy can be found in `./Caddyfile`.
|
**Uploading Large Files**: By default, Pingvin Share uses a built-in reverse proxy to reduce the installation steps. However, this reverse proxy is not optimized for uploading large files. If you wish to upload larger files, you can either use the Docker installation or set up your own reverse proxy. An example configuration for Caddy can be found in `./reverse-proxy/Caddyfile`.
|
||||||
|
|
||||||
The website is now listening on `http://localhost:3000`, have fun with Pingvin Share 🐧!
|
The website is now listening on `http://localhost:3000`, have fun with Pingvin Share 🐧!
|
||||||
|
|||||||
@@ -4,12 +4,39 @@ id: integrations
|
|||||||
|
|
||||||
# Integrations
|
# Integrations
|
||||||
|
|
||||||
#### ClamAV (Docker only)
|
## ClamAV
|
||||||
|
|
||||||
ClamAV is used to scan shares for malicious files and remove them if found.
|
ClamAV is used to scan shares for malicious files and remove them if found.
|
||||||
|
|
||||||
1. Add the ClamAV container to the Docker Compose stack (see `docker-compose.yml`) and start the container.
|
Please note that ClamAV needs a lot of [ressources](https://docs.clamav.net/manual/Installing/Docker.html#memory-ram-requirements).
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
If you are already running ClamAV elsewhere, you can specify the `CLAMAV_HOST` environment variable to point to that instance.
|
||||||
|
|
||||||
|
Else you have to add the ClamAV container to the Pingvin Share Docker Compose stack:
|
||||||
|
|
||||||
|
1. Add the ClamAV container to the Docker Compose stack and start the container.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
services:
|
||||||
|
pingvin-share:
|
||||||
|
image: stonith404/pingvin-share
|
||||||
|
...
|
||||||
|
+ depends_on:
|
||||||
|
+ clamav:
|
||||||
|
+ condition: service_healthy
|
||||||
|
|
||||||
|
+ clamav:
|
||||||
|
+ restart: unless-stopped
|
||||||
|
+ image: clamav/clamav
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
2. Docker will wait for ClamAV to start before starting Pingvin Share. This may take a minute or two.
|
2. Docker will wait for ClamAV to start before starting Pingvin Share. This may take a minute or two.
|
||||||
3. The Pingvin Share logs should now log "ClamAV is active"
|
3. The Pingvin Share logs should now log "ClamAV is active"
|
||||||
|
|
||||||
Please note that ClamAV needs a lot of [ressources](https://docs.clamav.net/manual/Installing/Docker.html#memory-ram-requirements).
|
### Stand-Alone
|
||||||
|
|
||||||
|
1. Install ClamAV
|
||||||
|
2. Specify the `CLAMAV_HOST` environment variable for the backend and restart the Pingvin Share backend.
|
||||||
|
|||||||
@@ -39,6 +39,6 @@ docker compose up -d
|
|||||||
cd ../frontend
|
cd ../frontend
|
||||||
npm install
|
npm install
|
||||||
npm run build
|
npm run build
|
||||||
API_URL=http://localhost:8080 # Set the URL of the backend, default: http://localhost:8080
|
|
||||||
pm2 restart pingvin-share-frontend
|
pm2 restart pingvin-share-frontend
|
||||||
```
|
```
|
||||||
|
Note that environemnt variables are not picked up when using pm2 restart, if you actually want to change configs, you need to run ````pm2 --update-env restart````
|
||||||
|
|||||||
828
docs/package-lock.json
generated
828
docs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
|||||||
"start": "docusaurus start",
|
"start": "docusaurus start",
|
||||||
"build": "docusaurus build",
|
"build": "docusaurus build",
|
||||||
"swizzle": "docusaurus swizzle",
|
"swizzle": "docusaurus swizzle",
|
||||||
"deploy": "docusaurus deploy",
|
"deploy": "GIT_USER=stonith404 docusaurus deploy",
|
||||||
"clear": "docusaurus clear",
|
"clear": "docusaurus clear",
|
||||||
"serve": "docusaurus serve",
|
"serve": "docusaurus serve",
|
||||||
"write-translations": "docusaurus write-translations",
|
"write-translations": "docusaurus write-translations",
|
||||||
@@ -15,19 +15,19 @@
|
|||||||
"typecheck": "tsc"
|
"typecheck": "tsc"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "3.4.0",
|
"@docusaurus/core": "3.5.2",
|
||||||
"@docusaurus/preset-classic": "3.4.0",
|
"@docusaurus/preset-classic": "3.5.2",
|
||||||
"@mdx-js/react": "^3.0.0",
|
"@mdx-js/react": "^3.0.1",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.1.1",
|
||||||
"prism-react-renderer": "^2.3.0",
|
"prism-react-renderer": "^2.4.0",
|
||||||
"react": "^18.0.0",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.0.0"
|
"react-dom": "^18.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/module-type-aliases": "3.4.0",
|
"@docusaurus/module-type-aliases": "3.5.2",
|
||||||
"@docusaurus/tsconfig": "3.4.0",
|
"@docusaurus/tsconfig": "3.5.2",
|
||||||
"@docusaurus/types": "3.4.0",
|
"@docusaurus/types": "3.5.2",
|
||||||
"typescript": "~5.2.2"
|
"typescript": "~5.6.2"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ const sidebars: SidebarsConfig = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
label: "Demo",
|
||||||
|
href: "https://pingvin-share.dev.eliasschneider.com",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "link",
|
type: "link",
|
||||||
label: "Discord",
|
label: "Discord",
|
||||||
|
|||||||
2
frontend/next-env.d.ts
vendored
2
frontend/next-env.d.ts
vendored
@@ -2,4 +2,4 @@
|
|||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||||
|
|||||||
3091
frontend/package-lock.json
generated
3091
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pingvin-share-frontend",
|
"name": "pingvin-share-frontend",
|
||||||
"version": "1.1.0",
|
"version": "1.1.3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"format": "prettier --end-of-line=auto --write \"src/**/*.ts*\""
|
"format": "prettier --end-of-line=auto --write \"src/**/*.ts*\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.11.4",
|
"@emotion/react": "^11.13.3",
|
||||||
"@emotion/server": "^11.11.0",
|
"@emotion/server": "^11.11.0",
|
||||||
"@mantine/core": "^6.0.21",
|
"@mantine/core": "^6.0.21",
|
||||||
"@mantine/dropzone": "^6.0.21",
|
"@mantine/dropzone": "^6.0.21",
|
||||||
@@ -18,37 +18,37 @@
|
|||||||
"@mantine/modals": "^6.0.21",
|
"@mantine/modals": "^6.0.21",
|
||||||
"@mantine/next": "^6.0.21",
|
"@mantine/next": "^6.0.21",
|
||||||
"@mantine/notifications": "^6.0.21",
|
"@mantine/notifications": "^6.0.21",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.7",
|
||||||
"cookies-next": "^2.1.2",
|
"cookies-next": "^4.2.1",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"jose": "^4.15.5",
|
"jose": "^5.9.2",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^4.0.0",
|
||||||
"markdown-to-jsx": "^7.4.7",
|
"markdown-to-jsx": "^7.5.0",
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"next": "^14.2.3",
|
"next": "^14.2.12",
|
||||||
"next-http-proxy-middleware": "^1.2.6",
|
"next-http-proxy-middleware": "^1.2.6",
|
||||||
"next-pwa": "^5.6.0",
|
"next-pwa": "^5.6.0",
|
||||||
"p-limit": "^4.0.0",
|
"p-limit": "^6.1.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-icons": "^4.12.0",
|
"react-icons": "^5.3.0",
|
||||||
"react-intl": "^6.6.8",
|
"react-intl": "^6.6.8",
|
||||||
"sharp": "^0.33.4",
|
"sharp": "^0.33.5",
|
||||||
"yup": "^1.4.0"
|
"yup": "^1.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/mime-types": "^2.1.4",
|
"@types/mime-types": "^2.1.4",
|
||||||
"@types/node": "20.12.12",
|
"@types/node": "22.5.5",
|
||||||
"@types/react": "18.3.2",
|
"@types/react": "18.3.7",
|
||||||
"@types/react-dom": "18.3.0",
|
"@types/react-dom": "18.3.0",
|
||||||
"@typescript-eslint/parser": "^7.10.0",
|
"@typescript-eslint/parser": "^8.6.0",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.7",
|
||||||
"eslint": "8.57.0",
|
"eslint": "8.57.0",
|
||||||
"eslint-config-next": "^13.5.6",
|
"eslint-config-next": "^14.2.12",
|
||||||
"eslint-config-prettier": "^8.10.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.3.3",
|
||||||
"tar": "^6.2.1",
|
"tar": "^7.4.3",
|
||||||
"typescript": "^5.4.5"
|
"typescript": "^5.6.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -370,8 +370,7 @@ const CreateUploadModalBody = ({
|
|||||||
placeholder={t("upload.modal.accordion.email.placeholder")}
|
placeholder={t("upload.modal.accordion.email.placeholder")}
|
||||||
searchable
|
searchable
|
||||||
creatable
|
creatable
|
||||||
id="recipient_email"
|
id="recipient-emails"
|
||||||
autoComplete="email"
|
|
||||||
type="email"
|
type="email"
|
||||||
getCreateLabel={(query) => `+ ${query}`}
|
getCreateLabel={(query) => `+ ${query}`}
|
||||||
onCreate={(query) => {
|
onCreate={(query) => {
|
||||||
@@ -426,7 +425,7 @@ const CreateUploadModalBody = ({
|
|||||||
"upload.modal.accordion.security.password.placeholder",
|
"upload.modal.accordion.security.password.placeholder",
|
||||||
)}
|
)}
|
||||||
label={t("upload.modal.accordion.security.password.label")}
|
label={t("upload.modal.accordion.security.password.label")}
|
||||||
autoComplete="off"
|
autoComplete="new-password"
|
||||||
{...form.getInputProps("password")}
|
{...form.getInputProps("password")}
|
||||||
/>
|
/>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "هذه الصفحة غير موجودة.",
|
"404.description": "هذه الصفحة غير موجودة.",
|
||||||
"404.button.home": "أعدني للصفحة الرئيسية",
|
"404.button.home": "أعدني للصفحة الرئيسية",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "الرابط",
|
"common.text.link": "الرابط",
|
||||||
"common.text.navigate-to-link": "الذهاب إلى الرابط",
|
"common.text.navigate-to-link": "الذهاب إلى الرابط",
|
||||||
"common.text.or": "أو",
|
"common.text.or": "أو",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "العودة",
|
"common.button.go-back": "العودة",
|
||||||
"common.button.go-home": "العودة للصفحة الرئيسية",
|
"common.button.go-home": "العودة للصفحة الرئيسية",
|
||||||
"common.notify.copied": "تم نسخ الرابط إلى الحافظة",
|
"common.notify.copied": "تم نسخ الرابط إلى الحافظة",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Oops this page doesn't exist.",
|
"404.description": "Oops this page doesn't exist.",
|
||||||
"404.button.home": "Bring me back home",
|
"404.button.home": "Bring me back home",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Link",
|
"common.text.link": "Link",
|
||||||
"common.text.navigate-to-link": "Go to the link",
|
"common.text.navigate-to-link": "Go to the link",
|
||||||
"common.text.or": "or",
|
"common.text.or": "or",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Go back",
|
"common.button.go-back": "Go back",
|
||||||
"common.button.go-home": "Go home",
|
"common.button.go-home": "Go home",
|
||||||
"common.notify.copied": "Your link was copied to the clipboard",
|
"common.notify.copied": "Your link was copied to the clipboard",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Skupina potřebná pro administrativní přístup.",
|
"admin.config.ldap.admin-groups.description": "Skupina potřebná pro administrativní přístup.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Jejda, tato stránka neexistuje.",
|
"404.description": "Jejda, tato stránka neexistuje.",
|
||||||
"404.button.home": "Bring me back home",
|
"404.button.home": "Bring me back home",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Odkaz",
|
"common.text.link": "Odkaz",
|
||||||
"common.text.navigate-to-link": "Přejít na odkaz",
|
"common.text.navigate-to-link": "Přejít na odkaz",
|
||||||
"common.text.or": "nebo",
|
"common.text.or": "nebo",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Vrátit se zpět",
|
"common.button.go-back": "Vrátit se zpět",
|
||||||
"common.button.go-home": "Jít domů",
|
"common.button.go-home": "Jít domů",
|
||||||
"common.notify.copied": "Váš odkaz byl zkopírován do schránky",
|
"common.notify.copied": "Váš odkaz byl zkopírován do schránky",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Ups! Denne side findes ikke.",
|
"404.description": "Ups! Denne side findes ikke.",
|
||||||
"404.button.home": "Gå tilbage",
|
"404.button.home": "Gå tilbage",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Link",
|
"common.text.link": "Link",
|
||||||
"common.text.navigate-to-link": "Go to the link",
|
"common.text.navigate-to-link": "Go to the link",
|
||||||
"common.text.or": "eller",
|
"common.text.or": "eller",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Gå tilbage",
|
"common.button.go-back": "Gå tilbage",
|
||||||
"common.button.go-home": "Go home",
|
"common.button.go-home": "Go home",
|
||||||
"common.notify.copied": "Linket blev kopieret til udklipsholderen",
|
"common.notify.copied": "Linket blev kopieret til udklipsholderen",
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ export default {
|
|||||||
// END /account/shares
|
// END /account/shares
|
||||||
// /account/reverseShares
|
// /account/reverseShares
|
||||||
"account.reverseShares.title": "Externe Freigaben",
|
"account.reverseShares.title": "Externe Freigaben",
|
||||||
"account.reverseShares.description": "Eine externe Freigabe erlaubt dir eine einzigartige URL zu erstellen, die externen Benutzern erlaubt Dateien hochzuladen.",
|
"account.reverseShares.description": "Eine externe Freigabe erlaubt dir eine einzigartige URL zu erstellen, die externen Benutzern erlaubt, Dateien hochzuladen.",
|
||||||
"account.reverseShares.title.empty": "Es ist leer hier 👀",
|
"account.reverseShares.title.empty": "Es ist leer hier 👀",
|
||||||
"account.reverseShares.description.empty": "Du hast keine externen Freigaben erstellt.",
|
"account.reverseShares.description.empty": "Du hast keine externen Freigaben erstellt.",
|
||||||
// showCreateReverseShareModal.tsx
|
// showCreateReverseShareModal.tsx
|
||||||
@@ -155,7 +155,7 @@ export default {
|
|||||||
"account.reverseShares.modal.simplified": "Einfacher Modus",
|
"account.reverseShares.modal.simplified": "Einfacher Modus",
|
||||||
"account.reverseShares.modal.simplified.description": "Mache es der Person einfach, die die Datei hochlädt, sie mit Dir zu teilen. Sie können nur den Namen und die Beschreibung der Freigabe ändern.",
|
"account.reverseShares.modal.simplified.description": "Mache es der Person einfach, die die Datei hochlädt, sie mit Dir zu teilen. Sie können nur den Namen und die Beschreibung der Freigabe ändern.",
|
||||||
"account.reverseShares.modal.public-access": "Öffentlicher Zugriff",
|
"account.reverseShares.modal.public-access": "Öffentlicher Zugriff",
|
||||||
"account.reverseShares.modal.public-access.description": "Make the created shares with this reverse share public. If disabled, only you and the creator of the share can view it.",
|
"account.reverseShares.modal.public-access.description": "Mache die erstellten Freigaben mit dieser Rückfreigabe öffentlich. Wenn deaktiviert, kannst nur du und der Ersteller der Freigaben diese anzeigen.",
|
||||||
"account.reverseShares.modal.max-use.label": "Maximale Nutzungen",
|
"account.reverseShares.modal.max-use.label": "Maximale Nutzungen",
|
||||||
"account.reverseShares.modal.max-use.description": "Die maximale Anzahl von Verwendungen der URL, um Dateien hochzuladen.",
|
"account.reverseShares.modal.max-use.description": "Die maximale Anzahl von Verwendungen der URL, um Dateien hochzuladen.",
|
||||||
"account.reverseShare.never-expires": "Diese externe Freigabe wird nicht ablaufen.",
|
"account.reverseShare.never-expires": "Diese externe Freigabe wird nicht ablaufen.",
|
||||||
@@ -324,7 +324,7 @@ export default {
|
|||||||
"admin.config.email.invite-subject": "Betreff für Einladung",
|
"admin.config.email.invite-subject": "Betreff für Einladung",
|
||||||
"admin.config.email.invite-subject.description": "Betreff der E-Mail, die gesendet wird, wenn ein Administrator einen Benutzer einlädt.",
|
"admin.config.email.invite-subject.description": "Betreff der E-Mail, die gesendet wird, wenn ein Administrator einen Benutzer einlädt.",
|
||||||
"admin.config.email.invite-message": "Nachricht für Einladung",
|
"admin.config.email.invite-message": "Nachricht für Einladung",
|
||||||
"admin.config.email.invite-message.description": "Message which gets sent when an admin invites a user. {url} will be replaced with the invite URL, {email} with the email and {password} with the password of the user.",
|
"admin.config.email.invite-message.description": "Nachricht welche gesendet wird, wenn der Administrator einen Nutzer einlädt. {url} wird ersetzt durch die Einladung URL, {email} mit der die E-Mail und {password} mit dem Passwort des Benutzers.",
|
||||||
"admin.config.share.allow-registration": "Registrierung erlauben",
|
"admin.config.share.allow-registration": "Registrierung erlauben",
|
||||||
"admin.config.share.allow-registration.description": "Gibt an, ob eine Registrierung erlaubt ist",
|
"admin.config.share.allow-registration.description": "Gibt an, ob eine Registrierung erlaubt ist",
|
||||||
"admin.config.share.allow-unauthenticated-shares": "Nicht authentifizierte Freigaben erlauben",
|
"admin.config.share.allow-unauthenticated-shares": "Nicht authentifizierte Freigaben erlauben",
|
||||||
@@ -416,9 +416,13 @@ export default {
|
|||||||
"admin.config.ldap.search-base": "User base",
|
"admin.config.ldap.search-base": "User base",
|
||||||
"admin.config.ldap.search-base.description": "Base location, where the user search will be performed",
|
"admin.config.ldap.search-base.description": "Base location, where the user search will be performed",
|
||||||
"admin.config.ldap.search-query": "User query",
|
"admin.config.ldap.search-query": "User query",
|
||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "Die Benutzer Abfrage wird in der \"Benutzerdatenbank\" gesucht für den LDAP Benutzer. %username% kann als Platzhalter für den Benutzer eingegeben werden.",
|
||||||
"admin.config.ldap.admin-groups": "Administratorengruppe",
|
"admin.config.ldap.admin-groups": "Administratorengruppe",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Gruppe benötigt für den Administrations Zugang.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Ups, diese Seite existiert nicht.",
|
"404.description": "Ups, diese Seite existiert nicht.",
|
||||||
"404.button.home": "Zurück zur Startseite",
|
"404.button.home": "Zurück zur Startseite",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Link",
|
"common.text.link": "Link",
|
||||||
"common.text.navigate-to-link": "Link öffnen",
|
"common.text.navigate-to-link": "Link öffnen",
|
||||||
"common.text.or": "oder",
|
"common.text.or": "oder",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Zurück",
|
"common.button.go-back": "Zurück",
|
||||||
"common.button.go-home": "Zur Startseite",
|
"common.button.go-home": "Zur Startseite",
|
||||||
"common.notify.copied": "Dein Link wurde in die Zwischenablage kopiert",
|
"common.notify.copied": "Dein Link wurde in die Zwischenablage kopiert",
|
||||||
|
|||||||
@@ -153,9 +153,9 @@ export default {
|
|||||||
"account.reverseShares.modal.send-email": "Αποστολή ειδοποιήσεων με email",
|
"account.reverseShares.modal.send-email": "Αποστολή ειδοποιήσεων με email",
|
||||||
"account.reverseShares.modal.send-email.description": "Στείλτε μια ειδοποίηση μέσω ηλεκτρονικού ταχυδρομείου όταν δημιουργείται ένας διαμοιρασμός με αυτόν τον σύνδεσμο ανάστροφης κοινοποίησης.",
|
"account.reverseShares.modal.send-email.description": "Στείλτε μια ειδοποίηση μέσω ηλεκτρονικού ταχυδρομείου όταν δημιουργείται ένας διαμοιρασμός με αυτόν τον σύνδεσμο ανάστροφης κοινοποίησης.",
|
||||||
"account.reverseShares.modal.simplified": "Απλή λειτουργία",
|
"account.reverseShares.modal.simplified": "Απλή λειτουργία",
|
||||||
"account.reverseShares.modal.simplified.description": "Make it easy for the person uploading the file to share it with you. They will be able to customize only the name and description of the share.",
|
"account.reverseShares.modal.simplified.description": "Κάντε εύκολο για το άτομο που ανεβάζει το αρχείο να το μοιραστεί μαζί σας. Θα είναι σε θέση να προσαρμόσει μόνο το όνομα και την περιγραφή της κοινοποίησης.",
|
||||||
"account.reverseShares.modal.public-access": "Public access",
|
"account.reverseShares.modal.public-access": "Δημόσια πρόσβαση",
|
||||||
"account.reverseShares.modal.public-access.description": "Make the created shares with this reverse share public. If disabled, only you and the creator of the share can view it.",
|
"account.reverseShares.modal.public-access.description": "Κάντε τις δημιουργημένες κοινοποιήσεις με αυτή την αντίστροφη κοινή χρήση δημόσιες. Εάν απενεργοποιηθεί, μόνο εσείς και ο δημιουργός της κοινής χρήσης μπορείτε να τη δείτε.",
|
||||||
"account.reverseShares.modal.max-use.label": "Μέγιστες χρήσεις",
|
"account.reverseShares.modal.max-use.label": "Μέγιστες χρήσεις",
|
||||||
"account.reverseShares.modal.max-use.description": "Ο μέγιστος αριθμός που μπορεί να χρησιμοποιηθεί αυτό το URL για τη δημιουργία ενός διαμοιρασμού.",
|
"account.reverseShares.modal.max-use.description": "Ο μέγιστος αριθμός που μπορεί να χρησιμοποιηθεί αυτό το URL για τη δημιουργία ενός διαμοιρασμού.",
|
||||||
"account.reverseShare.never-expires": "Αυτός ο αντίστροφος διαμοιρασμός δε λήγει.",
|
"account.reverseShare.never-expires": "Αυτός ο αντίστροφος διαμοιρασμός δε λήγει.",
|
||||||
@@ -174,7 +174,7 @@ export default {
|
|||||||
// /admin
|
// /admin
|
||||||
"admin.title": "Διαχείριση",
|
"admin.title": "Διαχείριση",
|
||||||
"admin.button.users": "Διαχείριση χρηστών",
|
"admin.button.users": "Διαχείριση χρηστών",
|
||||||
"admin.button.shares": "Share management",
|
"admin.button.shares": "Διαχείριση κοινοποιήσεων",
|
||||||
"admin.button.config": "Διαμόρφωση",
|
"admin.button.config": "Διαμόρφωση",
|
||||||
"admin.version": "Έκδοση",
|
"admin.version": "Έκδοση",
|
||||||
// END /admin
|
// END /admin
|
||||||
@@ -202,13 +202,13 @@ export default {
|
|||||||
"admin.users.modal.create.admin.description": "Αν ενεργοποιηθεί, ο χρήστης θα μπορεί να έχει πρόσβαση στον πίνακα διαχείρισης.",
|
"admin.users.modal.create.admin.description": "Αν ενεργοποιηθεί, ο χρήστης θα μπορεί να έχει πρόσβαση στον πίνακα διαχείρισης.",
|
||||||
// END /admin/users
|
// END /admin/users
|
||||||
// /admin/shares
|
// /admin/shares
|
||||||
"admin.shares.title": "Share management",
|
"admin.shares.title": "Διαχείριση κοινοποιήσεων",
|
||||||
"admin.shares.table.id": "Share ID",
|
"admin.shares.table.id": "Αναγνωριστικό κοινοποίησης",
|
||||||
"admin.shares.table.username": "Creator",
|
"admin.shares.table.username": "Δημιουργός",
|
||||||
"admin.shares.table.visitors": "Visitors",
|
"admin.shares.table.visitors": "Επισκέπτες",
|
||||||
"admin.shares.table.expires": "Expires At",
|
"admin.shares.table.expires": "Λήγει στις",
|
||||||
"admin.shares.edit.delete.title": "Delete share {id}",
|
"admin.shares.edit.delete.title": "Διαγραφή κοινοποίησης {id}",
|
||||||
"admin.shares.edit.delete.description": "Do you really want to delete this share?",
|
"admin.shares.edit.delete.description": "Θέλετε πραγματικά να διαγράψετε αυτή τη κοινοποίηση;",
|
||||||
// END /admin/shares
|
// END /admin/shares
|
||||||
// /upload
|
// /upload
|
||||||
"upload.title": "Μεταφόρτωση",
|
"upload.title": "Μεταφόρτωση",
|
||||||
@@ -244,9 +244,9 @@ export default {
|
|||||||
"upload.modal.expires.month-plural": "Μήνες",
|
"upload.modal.expires.month-plural": "Μήνες",
|
||||||
"upload.modal.expires.year-singular": "Έτος",
|
"upload.modal.expires.year-singular": "Έτος",
|
||||||
"upload.modal.expires.year-plural": "Έτη",
|
"upload.modal.expires.year-plural": "Έτη",
|
||||||
"upload.modal.accordion.name-and-description.title": "Name and description",
|
"upload.modal.accordion.name-and-description.title": "Όνομα και περιγραφή",
|
||||||
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
|
"upload.modal.accordion.name-and-description.name.placeholder": "Όνομα",
|
||||||
"upload.modal.accordion.name-and-description.description.placeholder": "Note for the recipients of this share",
|
"upload.modal.accordion.name-and-description.description.placeholder": "Σημείωση για τους παραλήπτες αυτής της κοινοποίησης",
|
||||||
"upload.modal.accordion.email.title": "Αποδέκτες email",
|
"upload.modal.accordion.email.title": "Αποδέκτες email",
|
||||||
"upload.modal.accordion.email.placeholder": "Εισάγετε αποδέκτες email",
|
"upload.modal.accordion.email.placeholder": "Εισάγετε αποδέκτες email",
|
||||||
"upload.modal.accordion.email.invalid-email": "Μη έγκυρη διεύθυνση e-mail",
|
"upload.modal.accordion.email.invalid-email": "Μη έγκυρη διεύθυνση e-mail",
|
||||||
@@ -259,7 +259,7 @@ export default {
|
|||||||
"upload.modal.completed.never-expires": "Αυτός ο διαμοιρασμός δεν λήγει.",
|
"upload.modal.completed.never-expires": "Αυτός ο διαμοιρασμός δεν λήγει.",
|
||||||
"upload.modal.completed.expires-on": "Αυτός ο διαμοιρασμός θα λήξει {expiration}.",
|
"upload.modal.completed.expires-on": "Αυτός ο διαμοιρασμός θα λήξει {expiration}.",
|
||||||
"upload.modal.completed.share-ready": "Κοινοποίηση έτοιμου",
|
"upload.modal.completed.share-ready": "Κοινοποίηση έτοιμου",
|
||||||
"upload.modal.completed.notified-reverse-share-creator": "We have notified the creator of the reverse share. You can also manually share this link with them through other means.",
|
"upload.modal.completed.notified-reverse-share-creator": "Έχουμε ειδοποιήσει τον δημιουργό της αντίστροφης κοινής χρήσης. Μπορείτε επίσης να μοιραστείτε χειροκίνητα αυτόν τον σύνδεσμο μαζί τους μέσω άλλων μέσων.",
|
||||||
// END /upload
|
// END /upload
|
||||||
// /share/[id]
|
// /share/[id]
|
||||||
"share.title": "Διαμοιρασμός {shareId}",
|
"share.title": "Διαμοιρασμός {shareId}",
|
||||||
@@ -269,8 +269,8 @@ export default {
|
|||||||
"share.error.removed.title": "Κοινοποίηση αφαιρέθηκε",
|
"share.error.removed.title": "Κοινοποίηση αφαιρέθηκε",
|
||||||
"share.error.not-found.title": "Η κοινοποίηση δε βρέθηκε",
|
"share.error.not-found.title": "Η κοινοποίηση δε βρέθηκε",
|
||||||
"share.error.not-found.description": "Η κοινοποίηση που ψάχνετε δεν υπάρχει.",
|
"share.error.not-found.description": "Η κοινοποίηση που ψάχνετε δεν υπάρχει.",
|
||||||
"share.error.access-denied.title": "Private share",
|
"share.error.access-denied.title": "Ιδιωτική κοινοποίηση",
|
||||||
"share.error.access-denied.description": "The current account does not have permission to access this share",
|
"share.error.access-denied.description": "Ο τρέχων λογαριασμός δεν έχει δικαίωμα πρόσβασης σε αυτήν την κοινοποίηση",
|
||||||
"share.modal.password.title": "Απαιτείται κωδικός",
|
"share.modal.password.title": "Απαιτείται κωδικός",
|
||||||
"share.modal.password.description": "Για να αποκτήσετε πρόσβαση σε αυτή την κοινοποίηση εισάγετε τον κωδικό πρόσβασης.",
|
"share.modal.password.description": "Για να αποκτήσετε πρόσβαση σε αυτή την κοινοποίηση εισάγετε τον κωδικό πρόσβασης.",
|
||||||
"share.modal.password": "Κωδικός πρόσβασης",
|
"share.modal.password": "Κωδικός πρόσβασης",
|
||||||
@@ -302,8 +302,8 @@ export default {
|
|||||||
"admin.config.general.app-url.description": "Η διεύθυνση URL όπου το Pingvin Share είναι διαθέσιμο",
|
"admin.config.general.app-url.description": "Η διεύθυνση URL όπου το Pingvin Share είναι διαθέσιμο",
|
||||||
"admin.config.general.show-home-page": "Εμφάνιση αρχικής σελίδας",
|
"admin.config.general.show-home-page": "Εμφάνιση αρχικής σελίδας",
|
||||||
"admin.config.general.show-home-page.description": "Εάν θα εμφανίζεται η αρχική σελίδα",
|
"admin.config.general.show-home-page.description": "Εάν θα εμφανίζεται η αρχική σελίδα",
|
||||||
"admin.config.general.session-duration": "Session Duration",
|
"admin.config.general.session-duration": "Διάρκεια συνεδρίας",
|
||||||
"admin.config.general.session-duration.description": "Time in hours after which a user must log in again (default: 3 months).",
|
"admin.config.general.session-duration.description": "Χρόνος σε ώρες μετά την οποία ένας χρήστης πρέπει να συνδεθεί ξανά (προεπιλογή: 3 μήνες).",
|
||||||
"admin.config.general.logo": "Λογότυπο",
|
"admin.config.general.logo": "Λογότυπο",
|
||||||
"admin.config.general.logo.description": "Αλλάξτε το λογότυπό σας ανεβάζοντας μια νέα εικόνα. Η εικόνα πρέπει να είναι PNG και αναλογία 1:1.",
|
"admin.config.general.logo.description": "Αλλάξτε το λογότυπό σας ανεβάζοντας μια νέα εικόνα. Η εικόνα πρέπει να είναι PNG και αναλογία 1:1.",
|
||||||
"admin.config.general.logo.placeholder": "Επιλέξτε εικόνα",
|
"admin.config.general.logo.placeholder": "Επιλέξτε εικόνα",
|
||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Ουπς. Αυτή η σελίδα δεν υπάρχει.",
|
"404.description": "Ουπς. Αυτή η σελίδα δεν υπάρχει.",
|
||||||
"404.button.home": "Πήγαινέ με πίσω",
|
"404.button.home": "Πήγαινέ με πίσω",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Σύνδεσμος",
|
"common.text.link": "Σύνδεσμος",
|
||||||
"common.text.navigate-to-link": "Μεταβείτε στο σύνδεσμο",
|
"common.text.navigate-to-link": "Μεταβείτε στο σύνδεσμο",
|
||||||
"common.text.or": "ή",
|
"common.text.or": "ή",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Επιστροφή",
|
"common.button.go-back": "Επιστροφή",
|
||||||
"common.button.go-home": "Μετάβαση στην αρχική",
|
"common.button.go-home": "Μετάβαση στην αρχική",
|
||||||
"common.notify.copied": "Ο σύνδεσμος σας αντιγράφηκε στο πρόχειρο",
|
"common.notify.copied": "Ο σύνδεσμος σας αντιγράφηκε στο πρόχειρο",
|
||||||
|
|||||||
@@ -585,6 +585,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
|
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Oops this page doesn't exist.",
|
"404.description": "Oops this page doesn't exist.",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Oops esta página no existe.",
|
"404.description": "Oops esta página no existe.",
|
||||||
"404.button.home": "Regrésame al inicio",
|
"404.button.home": "Regrésame al inicio",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Enlace",
|
"common.text.link": "Enlace",
|
||||||
"common.text.navigate-to-link": "Ir al enlace",
|
"common.text.navigate-to-link": "Ir al enlace",
|
||||||
"common.text.or": "o",
|
"common.text.or": "o",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Volver",
|
"common.button.go-back": "Volver",
|
||||||
"common.button.go-home": "Página de inicio",
|
"common.button.go-home": "Página de inicio",
|
||||||
"common.notify.copied": "Tu enlace se ha copiado al portapapeles",
|
"common.notify.copied": "Tu enlace se ha copiado al portapapeles",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Hups tätä sivua ei ole olemassa.",
|
"404.description": "Hups tätä sivua ei ole olemassa.",
|
||||||
"404.button.home": "Tuo minut takaisin kotiin",
|
"404.button.home": "Tuo minut takaisin kotiin",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Linkki",
|
"common.text.link": "Linkki",
|
||||||
"common.text.navigate-to-link": "Go to the link",
|
"common.text.navigate-to-link": "Go to the link",
|
||||||
"common.text.or": "tai",
|
"common.text.or": "tai",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Takaisin",
|
"common.button.go-back": "Takaisin",
|
||||||
"common.button.go-home": "Go home",
|
"common.button.go-home": "Go home",
|
||||||
"common.notify.copied": "Linkki kopioitiin leikepöydälle",
|
"common.notify.copied": "Linkki kopioitiin leikepöydälle",
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ export default {
|
|||||||
// END /
|
// END /
|
||||||
// /auth/signin
|
// /auth/signin
|
||||||
"signin.title": "Content de vous revoir",
|
"signin.title": "Content de vous revoir",
|
||||||
"signin.description": "Pas encore de compte ?",
|
"signin.description": "Vous n'avez pas encore de compte ?",
|
||||||
"signin.button.signup": "S’inscrire",
|
"signin.button.signup": "S’inscrire",
|
||||||
"signin.input.email-or-username": "Courriel ou surnom",
|
"signin.input.email-or-username": "Courriel ou nom d'utilisateur",
|
||||||
"signin.input.email-or-username.placeholder": "Votre courriel ou surnom",
|
"signin.input.email-or-username.placeholder": "Votre courriel ou nom d'utilisateur",
|
||||||
"signin.input.password": "Mot de passe",
|
"signin.input.password": "Mot de passe",
|
||||||
"signin.input.password.placeholder": "Votre mot de passe",
|
"signin.input.password.placeholder": "Votre mot de passe",
|
||||||
"signin.button.submit": "Se connecter",
|
"signin.button.submit": "Se connecter",
|
||||||
@@ -45,8 +45,8 @@ export default {
|
|||||||
"signup.title": "Créer un compte",
|
"signup.title": "Créer un compte",
|
||||||
"signup.description": "Vous avez déjà un compte ?",
|
"signup.description": "Vous avez déjà un compte ?",
|
||||||
"signup.button.signin": "Se connecter",
|
"signup.button.signin": "Se connecter",
|
||||||
"signup.input.username": "Surnom",
|
"signup.input.username": "Nom d'utilisateur",
|
||||||
"signup.input.username.placeholder": "Votre surnom",
|
"signup.input.username.placeholder": "Votre nom d'utilisateur",
|
||||||
"signup.input.email": "Adresse email",
|
"signup.input.email": "Adresse email",
|
||||||
"signup.input.email.placeholder": "Votre courriel",
|
"signup.input.email.placeholder": "Votre courriel",
|
||||||
"signup.button.submit": "Commençons",
|
"signup.button.submit": "Commençons",
|
||||||
@@ -324,7 +324,7 @@ export default {
|
|||||||
"admin.config.email.invite-subject": "Sujet d’une invitation",
|
"admin.config.email.invite-subject": "Sujet d’une invitation",
|
||||||
"admin.config.email.invite-subject.description": "Intitulé du courriel envoyé lorsqu’un administrateur invite un utilisateur.",
|
"admin.config.email.invite-subject.description": "Intitulé du courriel envoyé lorsqu’un administrateur invite un utilisateur.",
|
||||||
"admin.config.email.invite-message": "Message d’une invitation",
|
"admin.config.email.invite-message": "Message d’une invitation",
|
||||||
"admin.config.email.invite-message.description": "Message which gets sent when an admin invites a user. {url} will be replaced with the invite URL, {email} with the email and {password} with the password of the user.",
|
"admin.config.email.invite-message.description": "Message qui est envoyé lorsqu'un administrateur invite un utilisateur. {url} sera remplacé avec l'URL d'invitation, {email} avec le courriel et {password} avec le mot de passe de l'utilisateur.",
|
||||||
"admin.config.share.allow-registration": "Autoriser les inscriptions",
|
"admin.config.share.allow-registration": "Autoriser les inscriptions",
|
||||||
"admin.config.share.allow-registration.description": "Permet aux visiteurs de créer un compte.",
|
"admin.config.share.allow-registration.description": "Permet aux visiteurs de créer un compte.",
|
||||||
"admin.config.share.allow-unauthenticated-shares": "Autoriser les partages anonymes",
|
"admin.config.share.allow-unauthenticated-shares": "Autoriser les partages anonymes",
|
||||||
@@ -418,7 +418,11 @@ export default {
|
|||||||
"admin.config.ldap.search-query": "Requête utilisateur",
|
"admin.config.ldap.search-query": "Requête utilisateur",
|
||||||
"admin.config.ldap.search-query.description": "La requête utilisateur sera utilisée pour rechercher dans la ‘base d'utilisateurs’ de l'utilisateur LDAP. %username% peut être utilisé comme espace réservé pour les entrées données par l'utilisateur.",
|
"admin.config.ldap.search-query.description": "La requête utilisateur sera utilisée pour rechercher dans la ‘base d'utilisateurs’ de l'utilisateur LDAP. %username% peut être utilisé comme espace réservé pour les entrées données par l'utilisateur.",
|
||||||
"admin.config.ldap.admin-groups": "Groupe administrateur",
|
"admin.config.ldap.admin-groups": "Groupe administrateur",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Un groupe est nécessaire pour un accès administratif.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Désolé, mais cette page n’existe pas.",
|
"404.description": "Désolé, mais cette page n’existe pas.",
|
||||||
"404.button.home": "Retour à l’accueil",
|
"404.button.home": "Retour à l’accueil",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Lien",
|
"common.text.link": "Lien",
|
||||||
"common.text.navigate-to-link": "Accéder au lien",
|
"common.text.navigate-to-link": "Accéder au lien",
|
||||||
"common.text.or": "ou",
|
"common.text.or": "ou",
|
||||||
|
"common.text.redirecting": "Redirection...",
|
||||||
"common.button.go-back": "Précédent",
|
"common.button.go-back": "Précédent",
|
||||||
"common.button.go-home": "Accueil",
|
"common.button.go-home": "Accueil",
|
||||||
"common.notify.copied": "Votre lien a été copié dans le presse-papiers",
|
"common.notify.copied": "Votre lien a été copié dans le presse-papiers",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "A felhasználó lekérdezés kísérli meg az LDAP felhasználó elérését a felhasználóbázisban. %username% helyettesítheti az adott felhasználónevet.",
|
"admin.config.ldap.search-query.description": "A felhasználó lekérdezés kísérli meg az LDAP felhasználó elérését a felhasználóbázisban. %username% helyettesítheti az adott felhasználónevet.",
|
||||||
"admin.config.ldap.admin-groups": "Admin csoport",
|
"admin.config.ldap.admin-groups": "Admin csoport",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Hoppá - ez az oldal nem létezik.",
|
"404.description": "Hoppá - ez az oldal nem létezik.",
|
||||||
"404.button.home": "Vissza a Kezdőlapra",
|
"404.button.home": "Vissza a Kezdőlapra",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Hivatkozás",
|
"common.text.link": "Hivatkozás",
|
||||||
"common.text.navigate-to-link": "Ugrás a hivatkozásra",
|
"common.text.navigate-to-link": "Ugrás a hivatkozásra",
|
||||||
"common.text.or": "vagy",
|
"common.text.or": "vagy",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Vissza",
|
"common.button.go-back": "Vissza",
|
||||||
"common.button.go-home": "Kezdőlap",
|
"common.button.go-home": "Kezdőlap",
|
||||||
"common.notify.copied": "A hivatkozást a Vágólapra másoltuk",
|
"common.notify.copied": "A hivatkozást a Vágólapra másoltuk",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "La query utente verrà utilizzata per cercare la 'base utente' per l'utente LDAP. %username% può essere usato come segnaposto per l'input dato dall'utente.",
|
"admin.config.ldap.search-query.description": "La query utente verrà utilizzata per cercare la 'base utente' per l'utente LDAP. %username% può essere usato come segnaposto per l'input dato dall'utente.",
|
||||||
"admin.config.ldap.admin-groups": "Gruppo di amministrazione",
|
"admin.config.ldap.admin-groups": "Gruppo di amministrazione",
|
||||||
"admin.config.ldap.admin-groups.description": "Gruppo richiesto per l’accesso amministrativo.",
|
"admin.config.ldap.admin-groups.description": "Gruppo richiesto per l’accesso amministrativo.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Ops, questa pagina non esiste.",
|
"404.description": "Ops, questa pagina non esiste.",
|
||||||
"404.button.home": "Riportami a casa",
|
"404.button.home": "Riportami a casa",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Collegamento",
|
"common.text.link": "Collegamento",
|
||||||
"common.text.navigate-to-link": "Vai al collegamento",
|
"common.text.navigate-to-link": "Vai al collegamento",
|
||||||
"common.text.or": "o",
|
"common.text.or": "o",
|
||||||
|
"common.text.redirecting": "Reindirizzamento...",
|
||||||
"common.button.go-back": "Torna indietro",
|
"common.button.go-back": "Torna indietro",
|
||||||
"common.button.go-home": "Vai alla Home Page",
|
"common.button.go-home": "Vai alla Home Page",
|
||||||
"common.notify.copied": "Il tuo collegamento e' stato copiato negli appunti",
|
"common.notify.copied": "Il tuo collegamento e' stato copiato negli appunti",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "ユーザークエリはLDAPユーザーの「ユーザーベース」を検索するために使用されます。 %username% は、入力されたユーザーのプレースホルダとして使用できます。",
|
"admin.config.ldap.search-query.description": "ユーザークエリはLDAPユーザーの「ユーザーベース」を検索するために使用されます。 %username% は、入力されたユーザーのプレースホルダとして使用できます。",
|
||||||
"admin.config.ldap.admin-groups": "管理者グループ",
|
"admin.config.ldap.admin-groups": "管理者グループ",
|
||||||
"admin.config.ldap.admin-groups.description": "管理者アクセスに必要なグループです。",
|
"admin.config.ldap.admin-groups.description": "管理者アクセスに必要なグループです。",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "ページが見つかりません。",
|
"404.description": "ページが見つかりません。",
|
||||||
"404.button.home": "ホームに戻る",
|
"404.button.home": "ホームに戻る",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "リンク",
|
"common.text.link": "リンク",
|
||||||
"common.text.navigate-to-link": "リンクへ移動",
|
"common.text.navigate-to-link": "リンクへ移動",
|
||||||
"common.text.or": "または",
|
"common.text.or": "または",
|
||||||
|
"common.text.redirecting": "リダイレクトしています...",
|
||||||
"common.button.go-back": "戻る",
|
"common.button.go-back": "戻る",
|
||||||
"common.button.go-home": "ホームに戻る",
|
"common.button.go-home": "ホームに戻る",
|
||||||
"common.notify.copied": "リンクをクリップボードにコピーしました",
|
"common.notify.copied": "リンクをクリップボードにコピーしました",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "이런, 이 페이지는 존재하지 않습니다.",
|
"404.description": "이런, 이 페이지는 존재하지 않습니다.",
|
||||||
"404.button.home": "나를 집으로 데려다 줘",
|
"404.button.home": "나를 집으로 데려다 줘",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "링크",
|
"common.text.link": "링크",
|
||||||
"common.text.navigate-to-link": "링크로 이동",
|
"common.text.navigate-to-link": "링크로 이동",
|
||||||
"common.text.or": "또는",
|
"common.text.or": "또는",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "뒤로 가기",
|
"common.button.go-back": "뒤로 가기",
|
||||||
"common.button.go-home": "첫 페이지",
|
"common.button.go-home": "첫 페이지",
|
||||||
"common.notify.copied": "당신의 링크가 클립보드에 복사되었습니다.",
|
"common.notify.copied": "당신의 링크가 클립보드에 복사되었습니다.",
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default {
|
|||||||
"signIn.notify.totp-required.title": "Tweestapsverificatie vereist",
|
"signIn.notify.totp-required.title": "Tweestapsverificatie vereist",
|
||||||
"signIn.notify.totp-required.description": "Voer uw tweestapsverificatiecode in",
|
"signIn.notify.totp-required.description": "Voer uw tweestapsverificatiecode in",
|
||||||
"signIn.oauth.or": "OF",
|
"signIn.oauth.or": "OF",
|
||||||
"signIn.oauth.signInWith": "Sign in with",
|
"signIn.oauth.signInWith": "Registreer met",
|
||||||
"signIn.oauth.github": "GitHub",
|
"signIn.oauth.github": "GitHub",
|
||||||
"signIn.oauth.google": "Google",
|
"signIn.oauth.google": "Google",
|
||||||
"signIn.oauth.microsoft": "Microsoft",
|
"signIn.oauth.microsoft": "Microsoft",
|
||||||
@@ -151,11 +151,11 @@ export default {
|
|||||||
"account.reverseShares.modal.expiration.year-plural": "Jaren",
|
"account.reverseShares.modal.expiration.year-plural": "Jaren",
|
||||||
"account.reverseShares.modal.max-size.label": "Maximale share-grootte",
|
"account.reverseShares.modal.max-size.label": "Maximale share-grootte",
|
||||||
"account.reverseShares.modal.send-email": "Stuur e-mailnotificatie",
|
"account.reverseShares.modal.send-email": "Stuur e-mailnotificatie",
|
||||||
"account.reverseShares.modal.send-email.description": "Stuur een e-mailnotificatie wanneer er bestanden zijn gedeeld via deze omgekeerde share link.",
|
"account.reverseShares.modal.send-email.description": "Stuur een e-mail notificatie wanneer er bestanden zijn gedeeld via deze omgekeerde share link.",
|
||||||
"account.reverseShares.modal.simplified": "Simple mode",
|
"account.reverseShares.modal.simplified": "Simple mode",
|
||||||
"account.reverseShares.modal.simplified.description": "Make it easy for the person uploading the file to share it with you. They will be able to customize only the name and description of the share.",
|
"account.reverseShares.modal.simplified.description": "Maak het makkelijk voor de persoon die het bestand uploadt om het met u te delen. Ze kunnen alleen de naam en beschrijving van de share aanpassen.",
|
||||||
"account.reverseShares.modal.public-access": "Public access",
|
"account.reverseShares.modal.public-access": "Public access",
|
||||||
"account.reverseShares.modal.public-access.description": "Make the created shares with this reverse share public. If disabled, only you and the creator of the share can view it.",
|
"account.reverseShares.modal.public-access.description": "Maak de gemaakte shares met deze reverse share openbaar. Als dit is uitgeschakeld, kunnen alleen jij en de maker van de share deze bekijken.",
|
||||||
"account.reverseShares.modal.max-use.label": "Maximaal gebruikte keren",
|
"account.reverseShares.modal.max-use.label": "Maximaal gebruikte keren",
|
||||||
"account.reverseShares.modal.max-use.description": "Maximale keren dat deze URL gebruikt kan worden om een share aan te maken.",
|
"account.reverseShares.modal.max-use.description": "Maximale keren dat deze URL gebruikt kan worden om een share aan te maken.",
|
||||||
"account.reverseShare.never-expires": "Deze omgekeerde share zal nooit verlopen.",
|
"account.reverseShare.never-expires": "Deze omgekeerde share zal nooit verlopen.",
|
||||||
@@ -246,7 +246,7 @@ export default {
|
|||||||
"upload.modal.expires.year-plural": "Jaren",
|
"upload.modal.expires.year-plural": "Jaren",
|
||||||
"upload.modal.accordion.name-and-description.title": "Naam en beschrijving",
|
"upload.modal.accordion.name-and-description.title": "Naam en beschrijving",
|
||||||
"upload.modal.accordion.name-and-description.name.placeholder": "Naam",
|
"upload.modal.accordion.name-and-description.name.placeholder": "Naam",
|
||||||
"upload.modal.accordion.name-and-description.description.placeholder": "Note for the recipients of this share",
|
"upload.modal.accordion.name-and-description.description.placeholder": "Opmerking voor de ontvangers van deze share",
|
||||||
"upload.modal.accordion.email.title": "E-mail van de ontvangers",
|
"upload.modal.accordion.email.title": "E-mail van de ontvangers",
|
||||||
"upload.modal.accordion.email.placeholder": "Voer e-mail ontvangers in",
|
"upload.modal.accordion.email.placeholder": "Voer e-mail ontvangers in",
|
||||||
"upload.modal.accordion.email.invalid-email": "Ongeldig e-mailadres",
|
"upload.modal.accordion.email.invalid-email": "Ongeldig e-mailadres",
|
||||||
@@ -259,7 +259,7 @@ export default {
|
|||||||
"upload.modal.completed.never-expires": "Deze omgekeerde share zal nooit verlopen.",
|
"upload.modal.completed.never-expires": "Deze omgekeerde share zal nooit verlopen.",
|
||||||
"upload.modal.completed.expires-on": "Deze omgekeerde share verloopt op {expiration}.",
|
"upload.modal.completed.expires-on": "Deze omgekeerde share verloopt op {expiration}.",
|
||||||
"upload.modal.completed.share-ready": "Share is gereed",
|
"upload.modal.completed.share-ready": "Share is gereed",
|
||||||
"upload.modal.completed.notified-reverse-share-creator": "We have notified the creator of the reverse share. You can also manually share this link with them through other means.",
|
"upload.modal.completed.notified-reverse-share-creator": "We hebben de maker van de reverse share op de hoogte gesteld. U kunt deze link ook handmatig met hen delen via andere middelen.",
|
||||||
// END /upload
|
// END /upload
|
||||||
// /share/[id]
|
// /share/[id]
|
||||||
"share.title": "Share {shareId}",
|
"share.title": "Share {shareId}",
|
||||||
@@ -270,7 +270,7 @@ export default {
|
|||||||
"share.error.not-found.title": "Share niet gevonden",
|
"share.error.not-found.title": "Share niet gevonden",
|
||||||
"share.error.not-found.description": "De share die u zoekt kan niet gevonden worden.",
|
"share.error.not-found.description": "De share die u zoekt kan niet gevonden worden.",
|
||||||
"share.error.access-denied.title": "Private share",
|
"share.error.access-denied.title": "Private share",
|
||||||
"share.error.access-denied.description": "The current account does not have permission to access this share",
|
"share.error.access-denied.description": "Dit account heeft geen toestemming om toegang te krijgen tot deze share",
|
||||||
"share.modal.password.title": "Wachtwoord vereist",
|
"share.modal.password.title": "Wachtwoord vereist",
|
||||||
"share.modal.password.description": "Vul een wachtwoord in om toegang te krijgen tot deze share.",
|
"share.modal.password.description": "Vul een wachtwoord in om toegang te krijgen tot deze share.",
|
||||||
"share.modal.password": "Wachtwoord",
|
"share.modal.password": "Wachtwoord",
|
||||||
@@ -302,8 +302,8 @@ export default {
|
|||||||
"admin.config.general.app-url.description": "De URL waar Pingvin Share bereikbaar is",
|
"admin.config.general.app-url.description": "De URL waar Pingvin Share bereikbaar is",
|
||||||
"admin.config.general.show-home-page": "Toon startpagina",
|
"admin.config.general.show-home-page": "Toon startpagina",
|
||||||
"admin.config.general.show-home-page.description": "Toon of verberg de home pagina",
|
"admin.config.general.show-home-page.description": "Toon of verberg de home pagina",
|
||||||
"admin.config.general.session-duration": "Session Duration",
|
"admin.config.general.session-duration": "Sessieduur",
|
||||||
"admin.config.general.session-duration.description": "Time in hours after which a user must log in again (default: 3 months).",
|
"admin.config.general.session-duration.description": "Tijd in uren waarna een gebruiker zich opnieuw moet aanmelden (standaard: 3 maanden).",
|
||||||
"admin.config.general.logo": "Logo",
|
"admin.config.general.logo": "Logo",
|
||||||
"admin.config.general.logo.description": "Verander uw logo door een nieuwe afbeelding te uploaden. De afbeelding moet PNG zijn en het formaat moet 1:1 hebben.",
|
"admin.config.general.logo.description": "Verander uw logo door een nieuwe afbeelding te uploaden. De afbeelding moet PNG zijn en het formaat moet 1:1 hebben.",
|
||||||
"admin.config.general.logo.placeholder": "Afbeelding kiezen",
|
"admin.config.general.logo.placeholder": "Afbeelding kiezen",
|
||||||
@@ -324,7 +324,7 @@ export default {
|
|||||||
"admin.config.email.invite-subject": "Onderwerp voor uitnodiging",
|
"admin.config.email.invite-subject": "Onderwerp voor uitnodiging",
|
||||||
"admin.config.email.invite-subject.description": "Onderwerp van de e-mail die wordt verzonden wanneer een beheerder een gebruiker uitnodigt.",
|
"admin.config.email.invite-subject.description": "Onderwerp van de e-mail die wordt verzonden wanneer een beheerder een gebruiker uitnodigt.",
|
||||||
"admin.config.email.invite-message": "Bericht voor uitnodiging",
|
"admin.config.email.invite-message": "Bericht voor uitnodiging",
|
||||||
"admin.config.email.invite-message.description": "Message which gets sent when an admin invites a user. {url} will be replaced with the invite URL, {email} with the email and {password} with the password of the user.",
|
"admin.config.email.invite-message.description": "Bericht dat wordt verzonden wanneer een beheerder een gebruiker uitnodigt. {url} wordt vervangen door de uitnodigings-URL, {email} door het e-mailadres en {password} door het wachtwoord van de gebruiker.",
|
||||||
"admin.config.share.allow-registration": "Sta registratie toe",
|
"admin.config.share.allow-registration": "Sta registratie toe",
|
||||||
"admin.config.share.allow-registration.description": "Of registratie is toegestaan",
|
"admin.config.share.allow-registration.description": "Of registratie is toegestaan",
|
||||||
"admin.config.share.allow-unauthenticated-shares": "Ongeverifieerde shares toestaan",
|
"admin.config.share.allow-unauthenticated-shares": "Ongeverifieerde shares toestaan",
|
||||||
@@ -336,7 +336,7 @@ export default {
|
|||||||
"admin.config.share.zip-compression-level": "Zip compressie niveau",
|
"admin.config.share.zip-compression-level": "Zip compressie niveau",
|
||||||
"admin.config.share.zip-compression-level.description": "Pas het niveau aan voor evenwicht tussen bestandsgrootte en compressie snelheid. Geldige waarden variëren van 0 tot 9, waarbij 0 geen compressie is en 9 de maximale compressie is. ",
|
"admin.config.share.zip-compression-level.description": "Pas het niveau aan voor evenwicht tussen bestandsgrootte en compressie snelheid. Geldige waarden variëren van 0 tot 9, waarbij 0 geen compressie is en 9 de maximale compressie is. ",
|
||||||
"admin.config.share.chunk-size": "Chunk size",
|
"admin.config.share.chunk-size": "Chunk size",
|
||||||
"admin.config.share.chunk-size.description": "Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
|
"admin.config.share.chunk-size.description": "Pas de chunkgrootte (in bytes) voor uw uploads aan om efficiëntie en betrouwbaarheid in evenwicht te brengen op basis van uw internetverbinding. Kleinere chunks kunnen de slagingspercentages voor onstabiele verbindingen verbeteren, terwijl grotere chunks uploads voor stabiele verbindingen versnellen.",
|
||||||
"admin.config.share.auto-open-share-modal": "Auto open create share modal",
|
"admin.config.share.auto-open-share-modal": "Auto open create share modal",
|
||||||
"admin.config.share.auto-open-share-modal.description": "The share creation modal automatically appears when a user selects files, eliminating the need to manually click the button.",
|
"admin.config.share.auto-open-share-modal.description": "The share creation modal automatically appears when a user selects files, eliminating the need to manually click the button.",
|
||||||
"admin.config.smtp.enabled": "Inschakelen",
|
"admin.config.smtp.enabled": "Inschakelen",
|
||||||
@@ -352,14 +352,14 @@ export default {
|
|||||||
"admin.config.smtp.password": "Wachtwoord",
|
"admin.config.smtp.password": "Wachtwoord",
|
||||||
"admin.config.smtp.password.description": "Wachtwoord van de SMTP-server",
|
"admin.config.smtp.password.description": "Wachtwoord van de SMTP-server",
|
||||||
"admin.config.smtp.button.test": "Teste-mail verzenden",
|
"admin.config.smtp.button.test": "Teste-mail verzenden",
|
||||||
"admin.config.smtp.allow-unauthorized-certificates": "Trust unauthorized SMTP server certificates",
|
"admin.config.smtp.allow-unauthorized-certificates": "Vertrouw ongeautoriseerde SMTP-servercertificaten",
|
||||||
"admin.config.smtp.allow-unauthorized-certificates.description": "Only set this to true if you need to trust self signed certificates.",
|
"admin.config.smtp.allow-unauthorized-certificates.description": "Zet dit alleen aan als je de self signed certificates vertrouwt.",
|
||||||
"admin.config.oauth.allow-registration": "Sta registratie toe",
|
"admin.config.oauth.allow-registration": "Sta registratie toe",
|
||||||
"admin.config.oauth.allow-registration.description": "Gebruikers toestaan zich te registreren via sociale login",
|
"admin.config.oauth.allow-registration.description": "Gebruikers toestaan zich te registreren via sociale login",
|
||||||
"admin.config.oauth.ignore-totp": "TOTP negeren",
|
"admin.config.oauth.ignore-totp": "TOTP negeren",
|
||||||
"admin.config.oauth.ignore-totp.description": "TOTP negeren wanneer gebruiker sociale login gebruikt",
|
"admin.config.oauth.ignore-totp.description": "TOTP negeren wanneer gebruiker sociale login gebruikt",
|
||||||
"admin.config.oauth.disable-password": "Disable password login",
|
"admin.config.oauth.disable-password": "Zet password login uit",
|
||||||
"admin.config.oauth.disable-password.description": "Whether to disable password login\nMake sure that an OAuth provider is properly configured before activating this configuration to avoid being locked out.",
|
"admin.config.oauth.disable-password.description": "Of password login moet worden uitgeschakeld\nZorg ervoor dat een OAuth-provider correct is geconfigureerd voordat u deze configuratie activeert om te voorkomen dat u wordt buitengesloten.",
|
||||||
"admin.config.oauth.github-enabled": "GitHub",
|
"admin.config.oauth.github-enabled": "GitHub",
|
||||||
"admin.config.oauth.github-enabled.description": "Ofdat GitHub login is ingeschakeld",
|
"admin.config.oauth.github-enabled.description": "Ofdat GitHub login is ingeschakeld",
|
||||||
"admin.config.oauth.github-client-id": "GitHub Client ID",
|
"admin.config.oauth.github-client-id": "GitHub Client ID",
|
||||||
@@ -395,30 +395,34 @@ export default {
|
|||||||
"admin.config.oauth.oidc-username-claim": "OpenID Connect username claim",
|
"admin.config.oauth.oidc-username-claim": "OpenID Connect username claim",
|
||||||
"admin.config.oauth.oidc-username-claim.description": "Gebruikersnaam claim in OpenID Connect-ID-token. Laat het leeg als u niet weet wat deze configuratie is.",
|
"admin.config.oauth.oidc-username-claim.description": "Gebruikersnaam claim in OpenID Connect-ID-token. Laat het leeg als u niet weet wat deze configuratie is.",
|
||||||
"admin.config.oauth.oidc-role-path": "Path to roles in OpenID Connect token",
|
"admin.config.oauth.oidc-role-path": "Path to roles in OpenID Connect token",
|
||||||
"admin.config.oauth.oidc-role-path.description": "Must be a valid JMES path referencing an array of roles. " + "Managing access rights using OpenID Connect roles is only recommended if no other identity provider is configured and password login is disabled. " + "Leave it blank if you don't know what this config is.",
|
"admin.config.oauth.oidc-role-path.description": "Moet een geldig JMES-pad zijn dat verwijst naar een reeks rollen. " + "Het beheren van toegangsrechten met behulp van OpenID Connect-rollen wordt alleen aanbevolen als er geen andere identiteitsprovider is geconfigureerd en wachtwoordaanmelding is uitgeschakeld. " + "Laat dit leeg als u niet weet wat deze configuratie is.",
|
||||||
"admin.config.oauth.oidc-role-general-access": "OpenID Connect role for general access",
|
"admin.config.oauth.oidc-role-general-access": "OpenID Connect role voor algemene toegang",
|
||||||
"admin.config.oauth.oidc-role-general-access.description": "Role required for general access. Must be present in a user’s roles for them to log in. " + "Leave it blank if you don't know what this config is.",
|
"admin.config.oauth.oidc-role-general-access.description": "Rol vereist voor algemene toegang. Moet aanwezig zijn in de rollen van een gebruiker om in te loggen. " + "Laat het leeg als u niet weet wat deze configuratie is.",
|
||||||
"admin.config.oauth.oidc-role-admin-access": "OpenID Connect role for admin access",
|
"admin.config.oauth.oidc-role-admin-access": "OpenID Connect role voor admin toegang",
|
||||||
"admin.config.oauth.oidc-role-admin-access.description": "Role required for administrative access. Must be present in a user’s roles for them to access the admin panel. " + "Leave it blank if you don't know what this config is.",
|
"admin.config.oauth.oidc-role-admin-access.description": "Rol vereist voor administratieve toegang. Moet aanwezig zijn in de rollen van een gebruiker om toegang te krijgen tot het admin-paneel. " + "Laat dit leeg als u niet weet wat deze configuratie is.",
|
||||||
"admin.config.oauth.oidc-client-id": "Client-ID OpenID Connect",
|
"admin.config.oauth.oidc-client-id": "Client-ID OpenID Connect",
|
||||||
"admin.config.oauth.oidc-client-id.description": "Client-ID van de OpenID Connect OAuth app",
|
"admin.config.oauth.oidc-client-id.description": "Client-ID van de OpenID Connect OAuth app",
|
||||||
"admin.config.oauth.oidc-client-secret": "OpenID Connect client secret",
|
"admin.config.oauth.oidc-client-secret": "OpenID Connect client secret",
|
||||||
"admin.config.oauth.oidc-client-secret.description": "Client secret van de OpenID Connect OAuth app",
|
"admin.config.oauth.oidc-client-secret.description": "Client secret van de OpenID Connect OAuth app",
|
||||||
"admin.config.category.ldap": "LDAP",
|
"admin.config.category.ldap": "LDAP",
|
||||||
"admin.config.ldap.enabled": "Enabled LDAP",
|
"admin.config.ldap.enabled": "Enabled LDAP",
|
||||||
"admin.config.ldap.enabled.description": "Use LDAP authentication for user login",
|
"admin.config.ldap.enabled.description": "Gebruik LDAP authentication voor gebruiker login",
|
||||||
"admin.config.ldap.url": "Server URL",
|
"admin.config.ldap.url": "Server URL",
|
||||||
"admin.config.ldap.url.description": "URL of the LDAP server",
|
"admin.config.ldap.url.description": "URL van de LDAP server",
|
||||||
"admin.config.ldap.bind-dn": "Bind DN",
|
"admin.config.ldap.bind-dn": "Bind DN",
|
||||||
"admin.config.ldap.bind-dn.description": "Default user which will be used to execute the user search",
|
"admin.config.ldap.bind-dn.description": "Standaardgebruiker die zal worden gebruikt om de gebruikerszoekopdracht uit te voeren",
|
||||||
"admin.config.ldap.bind-password": "Bind password",
|
"admin.config.ldap.bind-password": "Bind password",
|
||||||
"admin.config.ldap.bind-password.description": "Password for the user search user",
|
"admin.config.ldap.bind-password.description": "Wachtwoord voor de user search gebruiker",
|
||||||
"admin.config.ldap.search-base": "User base",
|
"admin.config.ldap.search-base": "User base",
|
||||||
"admin.config.ldap.search-base.description": "Base location, where the user search will be performed",
|
"admin.config.ldap.search-base.description": "Base location, where the user search will be performed",
|
||||||
"admin.config.ldap.search-query": "User query",
|
"admin.config.ldap.search-query": "User query",
|
||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin groep",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Groep vereist voor administratieve toegang.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Oeps, deze pagina bestaat niet.",
|
"404.description": "Oeps, deze pagina bestaat niet.",
|
||||||
"404.button.home": "Breng me terug naar huis",
|
"404.button.home": "Breng me terug naar huis",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Koppeling",
|
"common.text.link": "Koppeling",
|
||||||
"common.text.navigate-to-link": "Ga naar de koppeling",
|
"common.text.navigate-to-link": "Ga naar de koppeling",
|
||||||
"common.text.or": "of",
|
"common.text.or": "of",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Ga terug",
|
"common.button.go-back": "Ga terug",
|
||||||
"common.button.go-home": "Go home",
|
"common.button.go-home": "Go home",
|
||||||
"common.notify.copied": "Uw link is gekopieerd naar het klembord",
|
"common.notify.copied": "Uw link is gekopieerd naar het klembord",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Ups! Ta strona nie istnieje.",
|
"404.description": "Ups! Ta strona nie istnieje.",
|
||||||
"404.button.home": "Wróć do strony domowej",
|
"404.button.home": "Wróć do strony domowej",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Link",
|
"common.text.link": "Link",
|
||||||
"common.text.navigate-to-link": "Przejdź do linku",
|
"common.text.navigate-to-link": "Przejdź do linku",
|
||||||
"common.text.or": "lub",
|
"common.text.or": "lub",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Wróć",
|
"common.button.go-back": "Wróć",
|
||||||
"common.button.go-home": "Wróć do ekranu głównego",
|
"common.button.go-home": "Wróć do ekranu głównego",
|
||||||
"common.notify.copied": "Link został skopiowany do schowka",
|
"common.notify.copied": "Link został skopiowany do schowka",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "A consulta do usuário será usada para pesquisar a 'base de usuários' para o usuário LDAP. %username% pode ser usado como espaço reservado para o usuário fornecido na entrada.",
|
"admin.config.ldap.search-query.description": "A consulta do usuário será usada para pesquisar a 'base de usuários' para o usuário LDAP. %username% pode ser usado como espaço reservado para o usuário fornecido na entrada.",
|
||||||
"admin.config.ldap.admin-groups": "Grupo de administração",
|
"admin.config.ldap.admin-groups": "Grupo de administração",
|
||||||
"admin.config.ldap.admin-groups.description": "Grupo necessário para acesso administrativo.",
|
"admin.config.ldap.admin-groups.description": "Grupo necessário para acesso administrativo.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Ops, esta página não existe.",
|
"404.description": "Ops, esta página não existe.",
|
||||||
"404.button.home": "Me traga de volta para casa",
|
"404.button.home": "Me traga de volta para casa",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Link",
|
"common.text.link": "Link",
|
||||||
"common.text.navigate-to-link": "Ir para o link",
|
"common.text.navigate-to-link": "Ir para o link",
|
||||||
"common.text.or": "ou",
|
"common.text.or": "ou",
|
||||||
|
"common.text.redirecting": "Redirecionando...",
|
||||||
"common.button.go-back": "Voltar",
|
"common.button.go-back": "Voltar",
|
||||||
"common.button.go-home": "Voltar para o Início",
|
"common.button.go-home": "Voltar para o Início",
|
||||||
"common.notify.copied": "O seu link foi copiado para a área de transferência",
|
"common.notify.copied": "O seu link foi copiado para a área de transferência",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Упс, этой страницы не существует.",
|
"404.description": "Упс, этой страницы не существует.",
|
||||||
"404.button.home": "Верните меня домой",
|
"404.button.home": "Верните меня домой",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Ссылка",
|
"common.text.link": "Ссылка",
|
||||||
"common.text.navigate-to-link": "Go to the link",
|
"common.text.navigate-to-link": "Go to the link",
|
||||||
"common.text.or": "или",
|
"common.text.or": "или",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Назад",
|
"common.button.go-back": "Назад",
|
||||||
"common.button.go-home": "Домой",
|
"common.button.go-home": "Домой",
|
||||||
"common.notify.copied": "Ваша ссылка скопирована в буфер обмена",
|
"common.notify.copied": "Ваша ссылка скопирована в буфер обмена",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Ups! Ta stran ne obstaja.",
|
"404.description": "Ups! Ta stran ne obstaja.",
|
||||||
"404.button.home": "Pelji me domov",
|
"404.button.home": "Pelji me domov",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Poveži",
|
"common.text.link": "Poveži",
|
||||||
"common.text.navigate-to-link": "Pojdi na povezavo",
|
"common.text.navigate-to-link": "Pojdi na povezavo",
|
||||||
"common.text.or": "ali",
|
"common.text.or": "ali",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Nazaj",
|
"common.button.go-back": "Nazaj",
|
||||||
"common.button.go-home": "Pojdi domov",
|
"common.button.go-home": "Pojdi domov",
|
||||||
"common.notify.copied": "Povezava je bila kopirana v odložišče",
|
"common.notify.copied": "Povezava je bila kopirana v odložišče",
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default {
|
|||||||
"signIn.notify.totp-required.title": "Потребна је двофакторска аутентификација",
|
"signIn.notify.totp-required.title": "Потребна је двофакторска аутентификација",
|
||||||
"signIn.notify.totp-required.description": "Унесите свој двофакторски код за аутентификацију",
|
"signIn.notify.totp-required.description": "Унесите свој двофакторски код за аутентификацију",
|
||||||
"signIn.oauth.or": "Или",
|
"signIn.oauth.or": "Или",
|
||||||
"signIn.oauth.signInWith": "Sign in with",
|
"signIn.oauth.signInWith": "Пријавите се са",
|
||||||
"signIn.oauth.github": "GitHub",
|
"signIn.oauth.github": "GitHub",
|
||||||
"signIn.oauth.google": "Google",
|
"signIn.oauth.google": "Google",
|
||||||
"signIn.oauth.microsoft": "Microsoft",
|
"signIn.oauth.microsoft": "Microsoft",
|
||||||
@@ -58,7 +58,7 @@ export default {
|
|||||||
// /auth/reset-password
|
// /auth/reset-password
|
||||||
"resetPassword.title": "Заборавили сте лозинку?",
|
"resetPassword.title": "Заборавили сте лозинку?",
|
||||||
"resetPassword.description": "Унесите своју е-пошту да бисте ресетовали лозинку.",
|
"resetPassword.description": "Унесите своју е-пошту да бисте ресетовали лозинку.",
|
||||||
"resetPassword.notify.success": "A message with a link to reset your password has been sent if the email exists.",
|
"resetPassword.notify.success": "Порука са везом за ресетовање ваше лозинке је послата ако имејл постоји.",
|
||||||
"resetPassword.button.back": "Назад на страницу за пријаву",
|
"resetPassword.button.back": "Назад на страницу за пријаву",
|
||||||
"resetPassword.text.resetPassword": "Обнови лозинку",
|
"resetPassword.text.resetPassword": "Обнови лозинку",
|
||||||
"resetPassword.text.enterNewPassword": "Унесите вашу нову лозинку",
|
"resetPassword.text.enterNewPassword": "Унесите вашу нову лозинку",
|
||||||
@@ -152,10 +152,10 @@ export default {
|
|||||||
"account.reverseShares.modal.max-size.label": "Максимална величина дељења",
|
"account.reverseShares.modal.max-size.label": "Максимална величина дељења",
|
||||||
"account.reverseShares.modal.send-email": "Пошаљите обавештење путем е-поште",
|
"account.reverseShares.modal.send-email": "Пошаљите обавештење путем е-поште",
|
||||||
"account.reverseShares.modal.send-email.description": "Пошаљите обавештење е-поштом када се креира дељење помоћу ове обрнуте везе за дељење.",
|
"account.reverseShares.modal.send-email.description": "Пошаљите обавештење е-поштом када се креира дељење помоћу ове обрнуте везе за дељење.",
|
||||||
"account.reverseShares.modal.simplified": "Simple mode",
|
"account.reverseShares.modal.simplified": "Једноставан режим",
|
||||||
"account.reverseShares.modal.simplified.description": "Make it easy for the person uploading the file to share it with you. They will be able to customize only the name and description of the share.",
|
"account.reverseShares.modal.simplified.description": "Олакшајте особи која отпрема датотеку да је подели са вама. Они ће моћи да прилагоде само име и опис дељења.",
|
||||||
"account.reverseShares.modal.public-access": "Public access",
|
"account.reverseShares.modal.public-access": "Јавни приступ",
|
||||||
"account.reverseShares.modal.public-access.description": "Make the created shares with this reverse share public. If disabled, only you and the creator of the share can view it.",
|
"account.reverseShares.modal.public-access.description": "Учините креирана дељења са овим обрнутим дељењем јавном. Ако је онемогућено, само ви и креатор дељења можете да га видите.",
|
||||||
"account.reverseShares.modal.max-use.label": "Максималан број коришћења",
|
"account.reverseShares.modal.max-use.label": "Максималан број коришћења",
|
||||||
"account.reverseShares.modal.max-use.description": "Максималан број пута који овај URL може да се користи за прављење дељења.",
|
"account.reverseShares.modal.max-use.description": "Максималан број пута који овај URL може да се користи за прављење дељења.",
|
||||||
"account.reverseShare.never-expires": "Ово обрнуто дељење никада неће истећи.",
|
"account.reverseShare.never-expires": "Ово обрнуто дељење никада неће истећи.",
|
||||||
@@ -174,7 +174,7 @@ export default {
|
|||||||
// /admin
|
// /admin
|
||||||
"admin.title": "Администрација",
|
"admin.title": "Администрација",
|
||||||
"admin.button.users": "Управљање корисницима",
|
"admin.button.users": "Управљање корисницима",
|
||||||
"admin.button.shares": "Share management",
|
"admin.button.shares": "Управљање deljenjima",
|
||||||
"admin.button.config": "Конфигурација",
|
"admin.button.config": "Конфигурација",
|
||||||
"admin.version": "Верзија",
|
"admin.version": "Верзија",
|
||||||
// END /admin
|
// END /admin
|
||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Опа - Ова страна не постоји.",
|
"404.description": "Опа - Ова страна не постоји.",
|
||||||
"404.button.home": "Врати ме на почетак",
|
"404.button.home": "Врати ме на почетак",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Линк",
|
"common.text.link": "Линк",
|
||||||
"common.text.navigate-to-link": "Go to the link",
|
"common.text.navigate-to-link": "Go to the link",
|
||||||
"common.text.or": "или",
|
"common.text.or": "или",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Иди назад",
|
"common.button.go-back": "Иди назад",
|
||||||
"common.button.go-home": "Go home",
|
"common.button.go-home": "Go home",
|
||||||
"common.notify.copied": "Ваша веза је копирана у clipboard",
|
"common.notify.copied": "Ваша веза је копирана у clipboard",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Hoppsan den här sidan finns inte.",
|
"404.description": "Hoppsan den här sidan finns inte.",
|
||||||
"404.button.home": "Ta mig tillbaka hem",
|
"404.button.home": "Ta mig tillbaka hem",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Länk",
|
"common.text.link": "Länk",
|
||||||
"common.text.navigate-to-link": "Gå till länken",
|
"common.text.navigate-to-link": "Gå till länken",
|
||||||
"common.text.or": "eller",
|
"common.text.or": "eller",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Gå tillbaka",
|
"common.button.go-back": "Gå tillbaka",
|
||||||
"common.button.go-home": "Gå hem",
|
"common.button.go-home": "Gå hem",
|
||||||
"common.notify.copied": "Din länk har kopierats till urklipp",
|
"common.notify.copied": "Din länk har kopierats till urklipp",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "ไม่พบหน้าที่คุณกำลังมองหา",
|
"404.description": "ไม่พบหน้าที่คุณกำลังมองหา",
|
||||||
"404.button.home": "หน้าแรก",
|
"404.button.home": "หน้าแรก",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "ลิงค์",
|
"common.text.link": "ลิงค์",
|
||||||
"common.text.navigate-to-link": "Go to the link",
|
"common.text.navigate-to-link": "Go to the link",
|
||||||
"common.text.or": "หรือ",
|
"common.text.or": "หรือ",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "ย้อนกลับ",
|
"common.button.go-back": "ย้อนกลับ",
|
||||||
"common.button.go-home": "Go home",
|
"common.button.go-home": "Go home",
|
||||||
"common.notify.copied": "คัดลอกไปยังคลิปบอร์ดแล้ว",
|
"common.notify.copied": "คัดลอกไปยังคลิปบอร์ดแล้ว",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Haydaa, böyle bir sayfa yok.",
|
"404.description": "Haydaa, böyle bir sayfa yok.",
|
||||||
"404.button.home": "Beni eve götür",
|
"404.button.home": "Beni eve götür",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Bağlantı",
|
"common.text.link": "Bağlantı",
|
||||||
"common.text.navigate-to-link": "Bağlantıya git",
|
"common.text.navigate-to-link": "Bağlantıya git",
|
||||||
"common.text.or": "ya da",
|
"common.text.or": "ya da",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Geri dön",
|
"common.button.go-back": "Geri dön",
|
||||||
"common.button.go-home": "Ana sayfaya dön",
|
"common.button.go-home": "Ana sayfaya dön",
|
||||||
"common.notify.copied": "Bağlantınız kopyalandı",
|
"common.notify.copied": "Bağlantınız kopyalandı",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Бляха, цієї строрінки не існує.",
|
"404.description": "Бляха, цієї строрінки не існує.",
|
||||||
"404.button.home": "Поверни мене додому",
|
"404.button.home": "Поверни мене додому",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Посилання",
|
"common.text.link": "Посилання",
|
||||||
"common.text.navigate-to-link": "Перейти до посилання",
|
"common.text.navigate-to-link": "Перейти до посилання",
|
||||||
"common.text.or": "або",
|
"common.text.or": "або",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Назад",
|
"common.button.go-back": "Назад",
|
||||||
"common.button.go-home": "Перейти додому",
|
"common.button.go-home": "Перейти додому",
|
||||||
"common.notify.copied": "Ваше посилання скопійовано в буфер обміну",
|
"common.notify.copied": "Ваше посилання скопійовано в буфер обміну",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "Oops this page doesn't exist.",
|
"404.description": "Oops this page doesn't exist.",
|
||||||
"404.button.home": "Về trang chủ",
|
"404.button.home": "Về trang chủ",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "Link",
|
"common.text.link": "Link",
|
||||||
"common.text.navigate-to-link": "Go to the link",
|
"common.text.navigate-to-link": "Go to the link",
|
||||||
"common.text.or": "hoặc",
|
"common.text.or": "hoặc",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "Quay lại",
|
"common.button.go-back": "Quay lại",
|
||||||
"common.button.go-home": "Về trang chủ",
|
"common.button.go-home": "Về trang chủ",
|
||||||
"common.notify.copied": "Đã sao chép liên kết vào bộ nhớ",
|
"common.notify.copied": "Đã sao chép liên kết vào bộ nhớ",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "将用于在 'User base'中搜索 LDAP 用户。%username% 可以作为用户输入的占位符。",
|
"admin.config.ldap.search-query.description": "将用于在 'User base'中搜索 LDAP 用户。%username% 可以作为用户输入的占位符。",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "当前的页面走丢啦",
|
"404.description": "当前的页面走丢啦",
|
||||||
"404.button.home": "返回主页",
|
"404.button.home": "返回主页",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "链接",
|
"common.text.link": "链接",
|
||||||
"common.text.navigate-to-link": "访问链接",
|
"common.text.navigate-to-link": "访问链接",
|
||||||
"common.text.or": "或",
|
"common.text.or": "或",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "返回",
|
"common.button.go-back": "返回",
|
||||||
"common.button.go-home": "返回主页",
|
"common.button.go-home": "返回主页",
|
||||||
"common.notify.copied": "已复制到剪贴板",
|
"common.notify.copied": "已复制到剪贴板",
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ export default {
|
|||||||
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
"admin.config.ldap.search-query.description": "The user query will be used to search the 'User base' for the LDAP user. %username% can be used as the placeholder for the user given input.",
|
||||||
"admin.config.ldap.admin-groups": "Admin group",
|
"admin.config.ldap.admin-groups": "Admin group",
|
||||||
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
"admin.config.ldap.admin-groups.description": "Group required for administrative access.",
|
||||||
|
"admin.config.ldap.field-name-member-of": "User groups attribute name",
|
||||||
|
"admin.config.ldap.field-name-member-of.description": "LDAP attribute name for the groups, an user is a member of. This is used when checking for the admin group.",
|
||||||
|
"admin.config.ldap.field-name-email": "User email attribute name",
|
||||||
|
"admin.config.ldap.field-name-email.description": "LDAP attribute name for the email of an user.",
|
||||||
// 404
|
// 404
|
||||||
"404.description": "查無此頁",
|
"404.description": "查無此頁",
|
||||||
"404.button.home": "返回主頁",
|
"404.button.home": "返回主頁",
|
||||||
@@ -456,6 +460,7 @@ export default {
|
|||||||
"common.text.link": "聯結",
|
"common.text.link": "聯結",
|
||||||
"common.text.navigate-to-link": "Go to the link",
|
"common.text.navigate-to-link": "Go to the link",
|
||||||
"common.text.or": "或",
|
"common.text.or": "或",
|
||||||
|
"common.text.redirecting": "Redirecting...",
|
||||||
"common.button.go-back": "返回",
|
"common.button.go-back": "返回",
|
||||||
"common.button.go-home": "Go home",
|
"common.button.go-home": "Go home",
|
||||||
"common.notify.copied": "已複製到剪貼簿",
|
"common.notify.copied": "已複製到剪貼簿",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import jwtDecode from "jwt-decode";
|
import { jwtDecode } from "jwt-decode";
|
||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import configService from "./services/config.service";
|
import configService from "./services/config.service";
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
Center,
|
Center,
|
||||||
Container,
|
Container,
|
||||||
@@ -14,7 +15,7 @@ import {
|
|||||||
import { useForm, yupResolver } from "@mantine/form";
|
import { useForm, yupResolver } from "@mantine/form";
|
||||||
import { useModals } from "@mantine/modals";
|
import { useModals } from "@mantine/modals";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Tb2Fa } from "react-icons/tb";
|
import { TbAuth2Fa } from "react-icons/tb";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import Meta from "../../components/Meta";
|
import Meta from "../../components/Meta";
|
||||||
@@ -142,6 +143,9 @@ const Account = () => {
|
|||||||
<Paper withBorder p="xl">
|
<Paper withBorder p="xl">
|
||||||
<Title order={5} mb="xs">
|
<Title order={5} mb="xs">
|
||||||
<FormattedMessage id="account.card.info.title" />
|
<FormattedMessage id="account.card.info.title" />
|
||||||
|
{user?.isLdap ? (
|
||||||
|
<Badge style={{ marginLeft: "1em" }}>LDAP</Badge>
|
||||||
|
) : null}
|
||||||
</Title>
|
</Title>
|
||||||
<form
|
<form
|
||||||
onSubmit={accountForm.onSubmit((values) =>
|
onSubmit={accountForm.onSubmit((values) =>
|
||||||
@@ -162,13 +166,16 @@ const Account = () => {
|
|||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={t("account.card.info.email")}
|
label={t("account.card.info.email")}
|
||||||
|
disabled={user?.isLdap}
|
||||||
{...accountForm.getInputProps("email")}
|
{...accountForm.getInputProps("email")}
|
||||||
/>
|
/>
|
||||||
<Group position="right">
|
{!user?.isLdap && (
|
||||||
<Button type="submit">
|
<Group position="right">
|
||||||
<FormattedMessage id="common.button.save" />
|
<Button type="submit">
|
||||||
</Button>
|
<FormattedMessage id="common.button.save" />
|
||||||
</Group>
|
</Button>
|
||||||
|
</Group>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</form>
|
</form>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -293,7 +300,7 @@ const Account = () => {
|
|||||||
|
|
||||||
<Tabs defaultValue="totp">
|
<Tabs defaultValue="totp">
|
||||||
<Tabs.List>
|
<Tabs.List>
|
||||||
<Tabs.Tab value="totp" icon={<Tb2Fa size={14} />}>
|
<Tabs.Tab value="totp" icon={<TbAuth2Fa size={14} />}>
|
||||||
TOTP
|
TOTP
|
||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
</Tabs.List>
|
</Tabs.List>
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pingvin-share",
|
"name": "pingvin-share",
|
||||||
"version": "1.1.0",
|
"version": "1.1.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pingvin-share",
|
"name": "pingvin-share",
|
||||||
"version": "1.1.0",
|
"version": "1.1.3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"conventional-changelog-cli": "^3.0.0"
|
"conventional-changelog-cli": "^3.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pingvin-share",
|
"name": "pingvin-share",
|
||||||
"version": "1.1.0",
|
"version": "1.1.3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"format": "cd frontend && npm run format && cd ../backend && npm run format",
|
"format": "cd frontend && npm run format && cd ../backend && npm run format",
|
||||||
"lint": "cd frontend && npm run lint && cd ../backend && npm run lint",
|
"lint": "cd frontend && npm run lint && cd ../backend && npm run lint",
|
||||||
|
|||||||
7
reverse-proxy/Caddyfile
Normal file
7
reverse-proxy/Caddyfile
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
:3000 {
|
||||||
|
# Reverse proxy for /api
|
||||||
|
reverse_proxy /api/* http://localhost:8080
|
||||||
|
|
||||||
|
# Reverse proxy for all other requests
|
||||||
|
reverse_proxy http://localhost:3333
|
||||||
|
}
|
||||||
14
reverse-proxy/Caddyfile.trust-proxy
Normal file
14
reverse-proxy/Caddyfile.trust-proxy
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
:3000 {
|
||||||
|
reverse_proxy /* http://localhost:3333 {
|
||||||
|
trusted_proxies 0.0.0.0/0
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_proxy /api/* http://localhost:8080 {
|
||||||
|
trusted_proxies 0.0.0.0/0
|
||||||
|
}
|
||||||
|
|
||||||
|
log {
|
||||||
|
output file /var/log/caddy/access.log
|
||||||
|
level WARN
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,10 +4,17 @@
|
|||||||
cp -rn /tmp/img/* /opt/app/frontend/public/img
|
cp -rn /tmp/img/* /opt/app/frontend/public/img
|
||||||
|
|
||||||
# Start Caddy
|
# Start Caddy
|
||||||
caddy start --config /etc/caddy/Caddyfile &
|
if [ "$TRUST_PROXY" = "true" ]; then
|
||||||
|
caddy start --config /etc/caddy/Caddyfile.trust-proxy &
|
||||||
|
else
|
||||||
|
caddy start --config /etc/caddy/Caddyfile &
|
||||||
|
fi
|
||||||
|
|
||||||
# Run the frontend server
|
# Run the frontend server
|
||||||
PORT=3333 HOSTNAME=0.0.0.0 node frontend/server.js &
|
PORT=3333 HOSTNAME=0.0.0.0 node frontend/server.js &
|
||||||
|
|
||||||
# Run the backend server
|
# Run the backend server
|
||||||
cd backend && npm run prod
|
cd backend && npm run prod
|
||||||
|
|
||||||
# Wait for all processes to finish
|
# Wait for all processes to finish
|
||||||
wait -n
|
wait -n
|
||||||
|
|||||||
Reference in New Issue
Block a user