diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..98825dd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + web: + name: web (Ubuntu) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 10 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + - run: pnpm install --frozen-lockfile + - run: pnpm typecheck + - run: pnpm test -- --run + - run: pnpm build + + rust-linux: + name: rust (Linux) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - name: install keyring deps + run: sudo apt-get install -y libdbus-1-dev + - run: cargo test --workspace + - run: cargo build -p projectus-server --release + + rust-macos: + name: rust (macOS) + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - run: cargo test --workspace + - run: cargo build -p projectus-server --release diff --git a/Cargo.lock b/Cargo.lock index bce6323..a817eb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1201,6 +1201,16 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "dbus-secret-service" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "708b509edf7889e53d7efb0ffadd994cc6c2345ccb62f55cfd6b0682165e4fa6" +dependencies = [ + "dbus", + "zeroize", +] + [[package]] name = "der" version = "0.7.10" @@ -2656,6 +2666,7 @@ version = "3.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c" dependencies = [ + "dbus-secret-service", "log", "security-framework 2.11.1", "security-framework 3.7.0", @@ -6347,6 +6358,20 @@ name = "zeroize" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "zerotrie" diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index 8b409eb..0f20b6e 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -55,11 +55,14 @@ export function App() { setOpenProject(null) } + const dataRootLabel = workspace.capacidades?.data_root_label || undefined + return ( message('erro', text)} > @@ -86,7 +89,7 @@ export function App() { {screen === 'ideias' && ( )} - {screen === 'backup' && } + {screen === 'backup' && } {screen === 'arquivo' && ( )} diff --git a/apps/web/src/features/backup/BackupView.tsx b/apps/web/src/features/backup/BackupView.tsx index 55a7e3e..9a18c53 100644 --- a/apps/web/src/features/backup/BackupView.tsx +++ b/apps/web/src/features/backup/BackupView.tsx @@ -7,9 +7,11 @@ import type { Config, Snapshot } from '../../lib/types' export function BackupView({ config, + dataRootLabel, onMessage, }: { config: Config + dataRootLabel?: string onMessage: (type: 'ok' | 'erro', text: string) => void }) { const [snapshots, setSnapshots] = useState([]) @@ -45,7 +47,7 @@ export function BackupView({ />

- cada snapshot envia a pasta integral ~/Documents/PROJECTUS: configurações, kanbans, ideias, + cada snapshot envia a pasta integral {dataRootLabel ?? '~/Documents/PROJECTUS'}: configurações, kanbans, ideias, Arquivo, históricos e anexos.

{!config.r2.configurado ? ( diff --git a/apps/web/src/features/settings/SettingsView.tsx b/apps/web/src/features/settings/SettingsView.tsx index 1ef7390..034e71e 100644 --- a/apps/web/src/features/settings/SettingsView.tsx +++ b/apps/web/src/features/settings/SettingsView.tsx @@ -86,13 +86,16 @@ export function SettingsView({ setDirty(true) } + const credentialStore = credentialStatus?.store_nome ?? 'cofre do sistema' + const saveCredentials = async () => { try { await api.saveCredentials({ access_key_id: accessKey.trim(), secret_access_key: secretKey.trim() }) setAccessKey('') setSecretKey('') - setCredentialStatus(await api.credentialStatus()) - onMessage('ok', 'credenciais R2 fixadas no Keychain') + const updated = await api.credentialStatus() + setCredentialStatus(updated) + onMessage('ok', `credenciais R2 fixadas no ${updated.store_nome}`) } catch (error) { onMessage('erro', error instanceof Error ? error.message : 'não foi possível salvar credenciais') } @@ -300,10 +303,10 @@ export function SettingsView({ value={secretKey} onChange={(event) => setSecretKey(event.target.value)} /> - logo abaixo, "Secret Access Key". Salva no Keychain do macOS. + logo abaixo, "Secret Access Key". Salva no {credentialStore}.
- KEYCHAIN + {credentialStore.toUpperCase()} {credentialStatus?.fixadas ? `credenciais fixadas (${credentialStatus.access_key_id_mascarada})` @@ -316,7 +319,7 @@ export function SettingsView({ disabled={!accessKey.trim() || !secretKey.trim() || dirty || saving || !validR2Endpoint} onClick={() => void saveCredentials()} > - fixar credenciais no Keychain + fixar credenciais no {credentialStore}
@@ -334,10 +337,12 @@ export function SettingsView({

{daemon?.instalado - ? 'autostart instalado.' + ? `autostart instalado via ${daemon.autostart_nome}.` : daemon?.instalacao_disponivel - ? 'autostart ainda não instalado.' - : 'para manter o backend ativo com a janela fechada, execute ./scripts/instalar-autostart.sh.'} + ? `autostart ainda não instalado.` + : daemon?.suportado === false + ? 'autostart não disponível nesta plataforma.' + : `para manter o backend ativo com a janela fechada, use o botão instalar${daemon?.instalacao_manual ? ` ou ${daemon.instalacao_manual}` : ''}.`}

{!daemon?.instalado && daemon?.instalacao_disponivel && (