Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed1bbcfdf9
|
No files matched your search
@@ -40,8 +40,8 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.security.QSecurityKeyType;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSystemUserSession;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -131,15 +131,30 @@ public final class Db
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** The core system-user session (every permission and every all-access
|
||||
** security key of the given instance, read per instance). It must be a
|
||||
** QSystemUserSession: token-based authentication modules (OAuth2, Auth0)
|
||||
** accept that class without a token and reject any other tokenless session,
|
||||
** which made every system read and write fail on such hosts.
|
||||
** A session that holds every permission and every all-access security key of
|
||||
** the given instance (computed per instance, never cached across instances).
|
||||
*******************************************************************************/
|
||||
private static QSession systemSession(QInstance instance)
|
||||
{
|
||||
return (new QSystemUserSession(instance));
|
||||
QSession session = new QSession()
|
||||
{
|
||||
/*******************************************************************************
|
||||
** The system user holds every permission.
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public boolean hasPermission(String permissionName)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
for(QSecurityKeyType keyType : instance.getSecurityKeyTypes().values())
|
||||
{
|
||||
if(keyType.getAllAccessKeyName() != null)
|
||||
{
|
||||
session.withSecurityKeyValue(keyType.getAllAccessKeyName(), true);
|
||||
}
|
||||
}
|
||||
return (session);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -52,14 +52,17 @@ public final class ObjectStorageSchema
|
||||
ObjectStorageTables.OBJECT, List.of(List.of("bucketId", "objectKey")),
|
||||
ObjectStorageTables.USAGE_DAILY, List.of(List.of("bucketId", "snapshotDate")));
|
||||
|
||||
/** Browse and lookup indexes: table to column lists. */
|
||||
/** Browse and lookup indexes: table to column lists. New entries go at the end of
|
||||
** a table's list, so the generated names (ix_<table>_<n>) of existing ones never change.
|
||||
** The child lists on record pages (folder -> objects, object -> versions and references)
|
||||
** filter on the parent id alone, so those columns lead an index of their own. */
|
||||
private static final Map<String, List<List<String>>> INDEXES = Map.of(
|
||||
ObjectStorageTables.OBJECT, List.of(List.of("bucketId", "folderId"), List.of("bucketId", "lastModified"), List.of("bucketId", "size"), List.of("bucketId", "contentType"),
|
||||
List.of("bucketId", "deleted", "referenceCount"), List.of("bucketId", "headersKnown", "deleted")),
|
||||
ObjectStorageTables.OBJECT_REFERENCE, List.of(List.of("bucketId", "objectId"), List.of("bucketId", "missing")),
|
||||
List.of("bucketId", "deleted", "referenceCount"), List.of("bucketId", "headersKnown", "deleted"), List.of("folderId")),
|
||||
ObjectStorageTables.OBJECT_REFERENCE, List.of(List.of("bucketId", "objectId"), List.of("bucketId", "missing"), List.of("objectId")),
|
||||
ObjectStorageTables.OPERATION, List.of(List.of("bucketId", "occurredAt"), List.of("objectKey", "occurredAt")),
|
||||
ObjectStorageTables.FOLDER, List.of(List.of("parentFolderId")),
|
||||
ObjectStorageTables.OBJECT_VERSION, List.of(List.of("bucketId", "objectKey")));
|
||||
ObjectStorageTables.OBJECT_VERSION, List.of(List.of("bucketId", "objectKey"), List.of("objectId")));
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2025. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qbits.objectstorage.internal;
|
||||
|
||||
|
||||
import com.kingsrook.qbits.objectstorage.ObjectStorageQBitConfig;
|
||||
import com.kingsrook.qbits.objectstorage.testsupport.StorageTestSupport;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.security.QSecurityKeyType;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSystemUserSession;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Db.asSystem runs work as the core system user. Token-based authentication
|
||||
** modules (OAuth2, Auth0) accept a QSystemUserSession without a token and
|
||||
** reject any other tokenless session, so the class matters, not just the
|
||||
** permissions.
|
||||
*******************************************************************************/
|
||||
class DbSystemSessionTest
|
||||
{
|
||||
/*******************************************************************************
|
||||
** Reset the runtime and context after each test.
|
||||
*******************************************************************************/
|
||||
@AfterEach
|
||||
void tearDown()
|
||||
{
|
||||
StorageTestSupport.tearDown();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** The work sees a QSystemUserSession with every all-access key, and the
|
||||
** caller's session is restored afterwards.
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testAsSystemUsesCoreSystemUserSession() throws Exception
|
||||
{
|
||||
ObjectStorageQBitConfig config = new ObjectStorageQBitConfig().withBackendName(StorageTestSupport.MEMORY).withBucketScoping(false);
|
||||
StorageTestSupport.setUp(config, instance -> instance.addSecurityKeyType(new QSecurityKeyType().withName("tenant").withAllAccessKeyName("tenantAllAccess")));
|
||||
QSession caller = QContext.getQSession();
|
||||
|
||||
QSession inside = Db.asSystem(QContext::getQSession);
|
||||
|
||||
assertThat(inside).isInstanceOf(QSystemUserSession.class);
|
||||
assertThat(inside.hasPermission("anything")).isTrue();
|
||||
assertThat(inside.hasSecurityKeyValue("tenantAllAccess", true)).isTrue();
|
||||
assertThat(QContext.getQSession()).isSameAs(caller);
|
||||
}
|
||||
}
|
||||
@@ -129,6 +129,25 @@ class TablesAndConfigTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** The record-page child lists filter on the parent id alone (folder ->
|
||||
** objects, object -> versions and references), so the generated schema
|
||||
** gives each of those columns its own index, appended so existing generated
|
||||
** index names keep their numbers.
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testChildListColumnsAreIndexed()
|
||||
{
|
||||
String schema = String.join("\n", com.kingsrook.qbits.objectstorage.model.ObjectStorageSchema.postgresStatements(new ObjectStorageQBitConfig().withBackendName("rdbms")));
|
||||
assertThat(schema)
|
||||
.contains("ix_object_storage_object_1 ON object_storage_object (bucket_id, folder_id)")
|
||||
.contains("ix_object_storage_object_7 ON object_storage_object (folder_id)")
|
||||
.contains("ix_object_storage_object_version_2 ON object_storage_object_version (object_id)")
|
||||
.contains("ix_object_storage_object_reference_3 ON object_storage_object_reference (object_id)");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Owner naming rules: every table is lowercase snake_case with the full qbit
|
||||
** name as prefix; no table has a field that could hold a secret value; the nav
|
||||
|
||||
Reference in new issue
Block a user