Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f8e926f0c
|
||
|
|
4741285e96 | ||
|
|
4cf6ed9d83 | ||
|
|
21d5172fc4 | ||
|
|
5871f32b77
|
||
|
|
97a79e031d | ||
|
|
6ffcd32f99
|
||
|
|
64d23b03af |
No files matched your search
@@ -1,7 +1,7 @@
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
qqq-orb: kingsrook/qqq-orb@0.6.8
|
||||
qqq-orb: kingsrook/qqq-orb@0.6.9
|
||||
|
||||
commands:
|
||||
configure-package-install:
|
||||
|
||||
@@ -5,6 +5,7 @@ All notable changes to this project are documented here. The format follows Keep
|
||||
## [0.1.0] - Unreleased
|
||||
|
||||
### Added
|
||||
- `StorageBucket.maxUploadBytes()` in the `api` package: the bucket's upload limit in bytes (null when none), so other qbits need not call `config()`, which returns an internal type.
|
||||
- **The service (P1).** `ObjectStorage.bucket(alias)` and `ObjectStorage.asSystem(caller, runId)`: put (multipart above the part size), get with ranges, head, copy (in parts for very large objects), header and metadata changes, delete (delete marker, private trash, or permanent), restore, list, presigned GET, PUT and POST, public URLs, tags. Key building and URL encoding, the header policy (`object_storage_header_rule`), `PublicUrlResolver`, `StorageChangeListener`, `StorageReferenceProvider`, `StorageAlertSink`.
|
||||
- Configuration in code, upserted into visible `object_storage_*` tables; secret references with an allow-list; per-connection rate limits; per-bucket and per-connection record security locks.
|
||||
- The capability model and the Test connection probe (read-only by default, write tests on request, clock skew, presign host), with seeded provider defaults.
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<properties>
|
||||
<qbit.guardrails.enforce>true</qbit.guardrails.enforce>
|
||||
<qbit.guardrails.strictUiApiRoutes>true</qbit.guardrails.strictUiApiRoutes>
|
||||
<revision>0.1.0-SNAPSHOT</revision>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
@@ -27,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.kingsrook</groupId>
|
||||
<artifactId>qbit-build-parent</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.kingsrook.qbits</groupId>
|
||||
@@ -246,7 +248,7 @@
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<qqq.snapshot.version>4.1.0-RC.5</qqq.snapshot.version>
|
||||
<qqq.snapshot.version>4.1.0-RC.6</qqq.snapshot.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
@@ -128,6 +128,18 @@ public final class StorageBucket
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** The largest object this bucket accepts on upload, in bytes, or null when
|
||||
** the bucket sets no limit. Callers outside this qbit use this instead of
|
||||
** config(), which returns an internal type.
|
||||
*******************************************************************************/
|
||||
public Long maxUploadBytes()
|
||||
{
|
||||
return (bucket.getMaxUploadBytes());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** The bucket configuration.
|
||||
*******************************************************************************/
|
||||
|
||||
@@ -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,30 +131,15 @@ public final class Db
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** A session that holds every permission and every all-access security key of
|
||||
** the given instance (computed per instance, never cached across instances).
|
||||
** 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.
|
||||
*******************************************************************************/
|
||||
private static QSession systemSession(QInstance 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);
|
||||
return (new QSystemUserSession(instance));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ class StandaloneTest
|
||||
}
|
||||
ObjectStorage.bucket("files").delete(DeleteRequest.of(key));
|
||||
assertThat(ObjectStorage.bucket("files").head(key)).isEmpty();
|
||||
assertThat(ObjectStorage.bucket("files").maxUploadBytes()).isEqualTo(ObjectStorage.bucket("files").config().getMaxUploadBytes());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user