webdav fix
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
DROP POLICY IF EXISTS tenant_webdav_token_policy ON tenant.webdav_tokens;
|
||||||
|
ALTER TABLE tenant.webdav_tokens NO FORCE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE tenant.webdav_tokens DISABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
DROP FUNCTION IF EXISTS shared.current_webdav_token_prefix();
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
CREATE OR REPLACE FUNCTION shared.current_webdav_token_prefix() RETURNS text AS $$
|
||||||
|
SELECT NULLIF(current_setting('papercrate.webdav_token_prefix', true), '')
|
||||||
|
$$ LANGUAGE SQL STABLE;
|
||||||
|
|
||||||
|
ALTER TABLE tenant.webdav_tokens ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE tenant.webdav_tokens FORCE ROW LEVEL SECURITY;
|
||||||
|
CREATE POLICY tenant_webdav_token_policy ON tenant.webdav_tokens
|
||||||
|
USING (
|
||||||
|
tenant_id = shared.current_tenant_id()
|
||||||
|
OR (
|
||||||
|
shared.current_webdav_token_prefix() IS NOT NULL
|
||||||
|
AND token_prefix = shared.current_webdav_token_prefix()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
WITH CHECK (tenant_id = shared.current_tenant_id());
|
||||||
@@ -13,6 +13,7 @@ use crate::{
|
|||||||
models::{NewWebdavToken, WebdavToken},
|
models::{NewWebdavToken, WebdavToken},
|
||||||
schema::webdav_tokens,
|
schema::webdav_tokens,
|
||||||
state::PgPooledConnection,
|
state::PgPooledConnection,
|
||||||
|
tenants::{apply_webdav_token_prefix, clear_webdav_token_prefix},
|
||||||
};
|
};
|
||||||
|
|
||||||
const TOKEN_PREFIX_LENGTH: usize = 12;
|
const TOKEN_PREFIX_LENGTH: usize = 12;
|
||||||
@@ -84,6 +85,7 @@ pub fn find_active_token_by_secret(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let prefix = &secret[..TOKEN_PREFIX_LENGTH];
|
let prefix = &secret[..TOKEN_PREFIX_LENGTH];
|
||||||
|
apply_webdav_token_prefix(conn, prefix)?;
|
||||||
let mut query = webdav_tokens::table
|
let mut query = webdav_tokens::table
|
||||||
.filter(webdav_tokens::user_id.eq(user_id))
|
.filter(webdav_tokens::user_id.eq(user_id))
|
||||||
.filter(webdav_tokens::token_prefix.eq(prefix))
|
.filter(webdav_tokens::token_prefix.eq(prefix))
|
||||||
@@ -101,7 +103,10 @@ pub fn find_active_token_by_secret(
|
|||||||
query = query.filter(webdav_tokens::tenant_id.eq(tenant_id));
|
query = query.filter(webdav_tokens::tenant_id.eq(tenant_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
let candidates = query.load::<WebdavToken>(conn)?;
|
let load_result = query.load::<WebdavToken>(conn);
|
||||||
|
let clear_result = clear_webdav_token_prefix(conn);
|
||||||
|
clear_result?;
|
||||||
|
let candidates = load_result?;
|
||||||
|
|
||||||
for token in candidates {
|
for token in candidates {
|
||||||
if verify_token_secret(secret, &token.token_hash)? {
|
if verify_token_secret(secret, &token.token_hash)? {
|
||||||
|
|||||||
+17
-1
@@ -148,7 +148,8 @@ pub fn clear_tenant_context(conn: &mut PgConnection) -> AppResult<()> {
|
|||||||
"SELECT \
|
"SELECT \
|
||||||
set_config('papercrate.tenant_id', '', false), \
|
set_config('papercrate.tenant_id', '', false), \
|
||||||
set_config('papercrate.user_id', '', false), \
|
set_config('papercrate.user_id', '', false), \
|
||||||
set_config('papercrate.refresh_token_hash', '', false)"
|
set_config('papercrate.refresh_token_hash', '', false), \
|
||||||
|
set_config('papercrate.webdav_token_prefix', '', false)"
|
||||||
)
|
)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
@@ -177,6 +178,21 @@ pub fn clear_refresh_token_hash(conn: &mut PgConnection) -> AppResult<()> {
|
|||||||
.map_err(AppError::from)
|
.map_err(AppError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn apply_webdav_token_prefix(conn: &mut PgConnection, prefix: &str) -> AppResult<()> {
|
||||||
|
diesel::sql_query("SELECT set_config('papercrate.webdav_token_prefix', $1, false)")
|
||||||
|
.bind::<Text, _>(prefix)
|
||||||
|
.execute(conn)
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(AppError::from)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_webdav_token_prefix(conn: &mut PgConnection) -> AppResult<()> {
|
||||||
|
diesel::sql_query("SELECT set_config('papercrate.webdav_token_prefix', '', false)")
|
||||||
|
.execute(conn)
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(AppError::from)
|
||||||
|
}
|
||||||
|
|
||||||
fn normalize_storage_root(raw: Option<&str>, tenant_id: Uuid) -> String {
|
fn normalize_storage_root(raw: Option<&str>, tenant_id: Uuid) -> String {
|
||||||
match raw.map(str::trim) {
|
match raw.map(str::trim) {
|
||||||
Some(root) if !root.is_empty() => {
|
Some(root) if !root.is_empty() => {
|
||||||
|
|||||||
@@ -57,6 +57,19 @@ impl JobHandler for ProvisionTenantJob {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
drop(conn);
|
||||||
|
|
||||||
|
let mut conn = match state.db_for_tenant(tenant.id) {
|
||||||
|
Ok(conn) => conn,
|
||||||
|
Err(err) => {
|
||||||
|
warn!(job_id = %job.id, error = ?err, "failed to scope connection for tenant provisioning");
|
||||||
|
return JobExecution::Retry {
|
||||||
|
delay: std::time::Duration::from_secs(30),
|
||||||
|
error: "tenant connection unavailable".into(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if tenant.status == TenantStatus::Active {
|
if tenant.status == TenantStatus::Active {
|
||||||
warn!(
|
warn!(
|
||||||
job_id = %job.id,
|
job_id = %job.id,
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
{{- $config := dict "databaseUrl" .Values.backend.env.databaseUrl -}}
|
{{- $config := dict "databaseUrl" .Values.backend.env.databaseUrl -}}
|
||||||
{{- if not (index $config "databaseUrl") -}}
|
{{- if not (index $config "databaseUrl") -}}
|
||||||
{{- if .Values.postgres.enabled -}}
|
{{- if .Values.postgres.enabled -}}
|
||||||
{{- $dbUser := required "postgres.auth.username is required when postgres.enabled" .Values.postgres.auth.username -}}
|
{{- $appUser := default .Values.postgres.auth.username .Values.postgres.auth.appUsername -}}
|
||||||
{{- $dbPass := required "postgres.auth.password is required when postgres.enabled" .Values.postgres.auth.password -}}
|
{{- $appPass := default .Values.postgres.auth.password .Values.postgres.auth.appPassword -}}
|
||||||
|
{{- $dbUser := required "postgres auth appUsername/password (or username/password) must be provided when postgres.enabled" $appUser -}}
|
||||||
|
{{- $dbPass := required "postgres auth appUsername/password (or username/password) must be provided when postgres.enabled" $appPass -}}
|
||||||
{{- $dbName := default "papercrate" .Values.backend.env.databaseName -}}
|
{{- $dbName := default "papercrate" .Values.backend.env.databaseName -}}
|
||||||
{{- $dbHost := printf "%s-postgres" (include "papercrate.fullname" .) -}}
|
{{- $dbHost := printf "%s-postgres" (include "papercrate.fullname" .) -}}
|
||||||
{{- $_ := set $config "databaseUrl" (printf "postgres://%s:%s@%s:5432/%s" $dbUser $dbPass $dbHost $dbName) -}}
|
{{- $_ := set $config "databaseUrl" (printf "postgres://%s:%s@%s:5432/%s" $dbUser $dbPass $dbHost $dbName) -}}
|
||||||
|
|||||||
@@ -17,6 +17,44 @@ data:
|
|||||||
-c "CREATE DATABASE \"{{ $name }}\"";
|
-c "CREATE DATABASE \"{{ $name }}\"";
|
||||||
fi
|
fi
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- $appRole := default "" .Values.postgres.auth.appRole }}
|
||||||
|
{{- $appUser := default "" .Values.postgres.auth.appUsername }}
|
||||||
|
{{- $appPassword := default "" .Values.postgres.auth.appPassword }}
|
||||||
|
APP_ROLE="{{ $appRole }}"
|
||||||
|
APP_USER="{{ $appUser }}"
|
||||||
|
APP_PASSWORD="{{ $appPassword }}"
|
||||||
|
APP_DATABASE="{{ default "papercrate" .Values.backend.env.databaseName }}"
|
||||||
|
if [ -n "$APP_ROLE" ]; then
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname postgres <<-EOSQL
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '$APP_ROLE') THEN
|
||||||
|
CREATE ROLE "$APP_ROLE" NOLOGIN;
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
EOSQL
|
||||||
|
fi
|
||||||
|
if [ -n "$APP_USER" ] && [ -n "$APP_PASSWORD" ]; then
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname postgres <<-EOSQL
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '$APP_USER') THEN
|
||||||
|
CREATE ROLE "$APP_USER" LOGIN PASSWORD '$APP_PASSWORD';
|
||||||
|
ELSE
|
||||||
|
ALTER ROLE "$APP_USER" WITH LOGIN PASSWORD '$APP_PASSWORD';
|
||||||
|
END IF;
|
||||||
|
IF '$APP_ROLE' <> '' THEN
|
||||||
|
GRANT "$APP_ROLE" TO "$APP_USER";
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
GRANT CONNECT ON DATABASE "$APP_DATABASE" TO "$APP_USER";
|
||||||
|
GRANT USAGE ON SCHEMA public TO "$APP_USER";
|
||||||
|
ALTER ROLE "$APP_USER" SET search_path = 'tenant, shared, public';
|
||||||
|
ALTER ROLE "$APP_USER" INHERIT;
|
||||||
|
EOSQL
|
||||||
|
fi
|
||||||
if [ -n "$PGDATA" ] && [ -f "$PGDATA/postgresql.conf" ]; then
|
if [ -n "$PGDATA" ] && [ -f "$PGDATA/postgresql.conf" ]; then
|
||||||
if grep -q "^max_connections" "$PGDATA/postgresql.conf"; then
|
if grep -q "^max_connections" "$PGDATA/postgresql.conf"; then
|
||||||
sed -i "s/^max_connections.*/max_connections = {{ .Values.postgres.maxConnections | default 200 }}/" "$PGDATA/postgresql.conf"
|
sed -i "s/^max_connections.*/max_connections = {{ .Values.postgres.maxConnections | default 200 }}/" "$PGDATA/postgresql.conf"
|
||||||
|
|||||||
@@ -35,10 +35,7 @@ spec:
|
|||||||
{{- fail "quickwit.env.storageUri must be set, or provide global.s3.bucket" -}}
|
{{- fail "quickwit.env.storageUri must be set, or provide global.s3.bucket" -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- if and (not (index $qw "metastoreUri")) .Values.postgres.enabled -}}
|
{{- if and (not (index $qw "metastoreUri")) .Values.postgres.enabled -}}
|
||||||
{{- $dbUser := required "postgres.auth.username is required when postgres.enabled" .Values.postgres.auth.username -}}
|
{{- $_ := fail "quickwit.env.metastoreSecret must be provided when using chart-managed Postgres" -}}
|
||||||
{{- $dbPass := required "postgres.auth.password is required when postgres.enabled" .Values.postgres.auth.password -}}
|
|
||||||
{{- $dbHost := printf "%s-postgres" (include "papercrate.fullname" .) -}}
|
|
||||||
{{- $_ := set $qw "metastoreUri" (printf "postgres://%s:%s@%s:5432/quickwit" $dbUser $dbPass $dbHost) -}}
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- if not (index $qw "metastoreUri") -}}
|
{{- if not (index $qw "metastoreUri") -}}
|
||||||
{{- fail "quickwit.env.metastoreUri must be set when not using bundled Postgres" -}}
|
{{- fail "quickwit.env.metastoreUri must be set when not using bundled Postgres" -}}
|
||||||
@@ -55,8 +52,16 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: QW_STORAGE_URI
|
- name: QW_STORAGE_URI
|
||||||
value: {{ index $qw "storageUri" | quote }}
|
value: {{ index $qw "storageUri" | quote }}
|
||||||
|
{{- if .Values.quickwit.env.metastoreSecret }}
|
||||||
|
- name: QW_METASTORE_URI
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ .Values.quickwit.env.metastoreSecret }}
|
||||||
|
key: metastoreUri
|
||||||
|
{{- else }}
|
||||||
- name: QW_METASTORE_URI
|
- name: QW_METASTORE_URI
|
||||||
value: {{ index $qw "metastoreUri" | quote }}
|
value: {{ index $qw "metastoreUri" | quote }}
|
||||||
|
{{- end }}
|
||||||
{{- with .Values.global.s3.endpoint }}
|
{{- with .Values.global.s3.endpoint }}
|
||||||
- name: AWS_ENDPOINT_URL
|
- name: AWS_ENDPOINT_URL
|
||||||
value: {{ . | quote }}
|
value: {{ . | quote }}
|
||||||
|
|||||||
@@ -108,6 +108,9 @@ postgres:
|
|||||||
auth:
|
auth:
|
||||||
username: papercrate
|
username: papercrate
|
||||||
password: papercrate_dev
|
password: papercrate_dev
|
||||||
|
appRole: papercrate_app
|
||||||
|
appUsername: papercrate_app_login
|
||||||
|
appPassword: papercrate_app
|
||||||
databases:
|
databases:
|
||||||
papercrate: {}
|
papercrate: {}
|
||||||
quickwit: {}
|
quickwit: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user