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},
|
||||
schema::webdav_tokens,
|
||||
state::PgPooledConnection,
|
||||
tenants::{apply_webdav_token_prefix, clear_webdav_token_prefix},
|
||||
};
|
||||
|
||||
const TOKEN_PREFIX_LENGTH: usize = 12;
|
||||
@@ -84,6 +85,7 @@ pub fn find_active_token_by_secret(
|
||||
}
|
||||
|
||||
let prefix = &secret[..TOKEN_PREFIX_LENGTH];
|
||||
apply_webdav_token_prefix(conn, prefix)?;
|
||||
let mut query = webdav_tokens::table
|
||||
.filter(webdav_tokens::user_id.eq(user_id))
|
||||
.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));
|
||||
}
|
||||
|
||||
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 {
|
||||
if verify_token_secret(secret, &token.token_hash)? {
|
||||
|
||||
+17
-1
@@ -148,7 +148,8 @@ pub fn clear_tenant_context(conn: &mut PgConnection) -> AppResult<()> {
|
||||
"SELECT \
|
||||
set_config('papercrate.tenant_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)
|
||||
.map(|_| ())
|
||||
@@ -177,6 +178,21 @@ pub fn clear_refresh_token_hash(conn: &mut PgConnection) -> AppResult<()> {
|
||||
.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 {
|
||||
match raw.map(str::trim) {
|
||||
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 {
|
||||
warn!(
|
||||
job_id = %job.id,
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
{{- $config := dict "databaseUrl" .Values.backend.env.databaseUrl -}}
|
||||
{{- if not (index $config "databaseUrl") -}}
|
||||
{{- if .Values.postgres.enabled -}}
|
||||
{{- $dbUser := required "postgres.auth.username is required when postgres.enabled" .Values.postgres.auth.username -}}
|
||||
{{- $dbPass := required "postgres.auth.password is required when postgres.enabled" .Values.postgres.auth.password -}}
|
||||
{{- $appUser := default .Values.postgres.auth.username .Values.postgres.auth.appUsername -}}
|
||||
{{- $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 -}}
|
||||
{{- $dbHost := printf "%s-postgres" (include "papercrate.fullname" .) -}}
|
||||
{{- $_ := set $config "databaseUrl" (printf "postgres://%s:%s@%s:5432/%s" $dbUser $dbPass $dbHost $dbName) -}}
|
||||
|
||||
@@ -17,6 +17,44 @@ data:
|
||||
-c "CREATE DATABASE \"{{ $name }}\"";
|
||||
fi
|
||||
{{- 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 grep -q "^max_connections" "$PGDATA/postgresql.conf"; then
|
||||
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" -}}
|
||||
{{- end -}}
|
||||
{{- if and (not (index $qw "metastoreUri")) .Values.postgres.enabled -}}
|
||||
{{- $dbUser := required "postgres.auth.username is required when postgres.enabled" .Values.postgres.auth.username -}}
|
||||
{{- $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) -}}
|
||||
{{- $_ := fail "quickwit.env.metastoreSecret must be provided when using chart-managed Postgres" -}}
|
||||
{{- end -}}
|
||||
{{- if not (index $qw "metastoreUri") -}}
|
||||
{{- fail "quickwit.env.metastoreUri must be set when not using bundled Postgres" -}}
|
||||
@@ -55,8 +52,16 @@ spec:
|
||||
env:
|
||||
- name: QW_STORAGE_URI
|
||||
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
|
||||
value: {{ index $qw "metastoreUri" | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.global.s3.endpoint }}
|
||||
- name: AWS_ENDPOINT_URL
|
||||
value: {{ . | quote }}
|
||||
|
||||
@@ -108,6 +108,9 @@ postgres:
|
||||
auth:
|
||||
username: papercrate
|
||||
password: papercrate_dev
|
||||
appRole: papercrate_app
|
||||
appUsername: papercrate_app_login
|
||||
appPassword: papercrate_app
|
||||
databases:
|
||||
papercrate: {}
|
||||
quickwit: {}
|
||||
|
||||
Reference in New Issue
Block a user