diff --git a/.github/workflows/push-json-to-pocketbase.yml b/.github/workflows/push-json-to-pocketbase.yml index 0b5618194..3e77f1a55 100644 --- a/.github/workflows/push-json-to-pocketbase.yml +++ b/.github/workflows/push-json-to-pocketbase.yml @@ -105,7 +105,11 @@ jobs: const typesRes = await request(apiBase + '/collections/z_ref_script_types/records?perPage=500', { headers: { 'Authorization': token } }); if (typesRes.ok) { const typesData = JSON.parse(typesRes.body); - (typesData.items || []).forEach(function(item) { if (item.type) typeValueToId[item.type] = item.id; }); + (typesData.items || []).forEach(function(item) { + if (item.type != null) typeValueToId[item.type] = item.id; + if (item.name != null) typeValueToId[item.name] = item.id; + if (item.value != null) typeValueToId[item.value] = item.id; + }); } } catch (e) { console.warn('Could not fetch z_ref_script_types:', e.message); } try { @@ -115,6 +119,33 @@ jobs: (catData.items || []).forEach(function(item) { if (item.name) categoryNameToPbId[item.name] = item.id; }); } } catch (e) { console.warn('Could not fetch script_categories:', e.message); } + var noteTypeToId = {}; + var installMethodTypeToId = {}; + var osToId = {}; + var osVersionToId = {}; + try { + const res = await request(apiBase + '/collections/z_ref_note_types/records?perPage=500', { headers: { 'Authorization': token } }); + if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.type != null) noteTypeToId[item.type] = item.id; }); + } catch (e) { console.warn('z_ref_note_types:', e.message); } + try { + const res = await request(apiBase + '/collections/z_ref_install_method_types/records?perPage=500', { headers: { 'Authorization': token } }); + if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.type != null) installMethodTypeToId[item.type] = item.id; }); + } catch (e) { console.warn('z_ref_install_method_types:', e.message); } + try { + const res = await request(apiBase + '/collections/z_ref_os/records?perPage=500', { headers: { 'Authorization': token } }); + if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.os != null) osToId[item.os] = item.id; }); + } catch (e) { console.warn('z_ref_os:', e.message); } + try { + const res = await request(apiBase + '/collections/z_ref_os_version/records?perPage=500&expand=os', { headers: { 'Authorization': token } }); + if (res.ok) { + (JSON.parse(res.body).items || []).forEach(function(item) { + var osName = item.expand && item.expand.os && item.expand.os.os != null ? item.expand.os.os : null; + if (osName != null && item.version != null) osVersionToId[osName + '|' + item.version] = item.id; + }); + } + } catch (e) { console.warn('z_ref_os_version:', e.message); } + var notesCollUrl = apiBase + '/collections/script_notes/records'; + var installMethodsCollUrl = apiBase + '/collections/script_install_methods/records'; for (const file of files) { if (!fs.existsSync(file)) continue; const data = JSON.parse(fs.readFileSync(file, 'utf8')); @@ -137,6 +168,7 @@ jobs: is_dev: false }; var resolvedType = typeValueToId[data.type]; + if (resolvedType == null && data.type === 'ct') resolvedType = typeValueToId['lxc']; if (resolvedType) payload.type = resolvedType; var resolvedCats = (data.categories || []).map(function(n) { return categoryNameToPbId[categoryIdToName[n]]; }).filter(Boolean); if (resolvedCats.length) payload.categories = resolvedCats; @@ -149,7 +181,49 @@ jobs: }); const list = JSON.parse(listRes.body); const existingId = list.items && list.items[0] && list.items[0].id; + async function resolveNotesAndInstallMethods(scriptId) { + var noteIds = []; + for (var i = 0; i < (data.notes || []).length; i++) { + var note = data.notes[i]; + var typeId = noteTypeToId[note.type]; + if (typeId == null) continue; + var postRes = await request(notesCollUrl, { + method: 'POST', + headers: { 'Authorization': token, 'Content-Type': 'application/json' }, + body: JSON.stringify({ text: note.text || '', type: typeId }) + }); + if (postRes.ok) noteIds.push(JSON.parse(postRes.body).id); + } + var installMethodIds = []; + for (var j = 0; j < (data.install_methods || []).length; j++) { + var im = data.install_methods[j]; + var typeId = installMethodTypeToId[im.type]; + var res = im.resources || {}; + var osId = osToId[res.os]; + var osVersionKey = (res.os != null && res.version != null) ? res.os + '|' + res.version : null; + var osVersionId = osVersionKey ? osVersionToId[osVersionKey] : null; + var imBody = { + script: scriptId, + resources_cpu: res.cpu != null ? res.cpu : 0, + resources_ram: res.ram != null ? res.ram : 0, + resources_hdd: res.hdd != null ? res.hdd : 0 + }; + if (typeId) imBody.type = typeId; + if (osId) imBody.os = osId; + if (osVersionId) imBody.os_version = osVersionId; + var imPostRes = await request(installMethodsCollUrl, { + method: 'POST', + headers: { 'Authorization': token, 'Content-Type': 'application/json' }, + body: JSON.stringify(imBody) + }); + if (imPostRes.ok) installMethodIds.push(JSON.parse(imPostRes.body).id); + } + return { noteIds: noteIds, installMethodIds: installMethodIds }; + } if (existingId) { + var resolved = await resolveNotesAndInstallMethods(existingId); + payload.notes = resolved.noteIds; + payload.install_methods = resolved.installMethodIds; console.log('Updating', file, '(slug=' + data.slug + ')'); const r = await request(recordsUrl + '/' + existingId, { method: 'PATCH', @@ -165,6 +239,14 @@ jobs: body: JSON.stringify(payload) }); if (!r.ok) throw new Error('POST failed: ' + r.body); + var scriptId = JSON.parse(r.body).id; + var resolved = await resolveNotesAndInstallMethods(scriptId); + var patchRes = await request(recordsUrl + '/' + scriptId, { + method: 'PATCH', + headers: { 'Authorization': token, 'Content-Type': 'application/json' }, + body: JSON.stringify({ install_methods: resolved.installMethodIds, notes: resolved.noteIds }) + }); + if (!patchRes.ok) throw new Error('PATCH relations failed: ' + patchRes.body); } } console.log('Done.'); diff --git a/frontend/public/json/2fauth.json b/frontend/public/json/2fauth.json index f3686ea16..2bdfd2da5 100644 --- a/frontend/public/json/2fauth.json +++ b/frontend/public/json/2fauth.json @@ -13,7 +13,7 @@ "website": "https://2fauth.app/", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/2fauth.webp", "config_path": "cat /opt/2fauth/.env", - "description": "2FAuth is a web based self-hosted alternative to One Time Passcode (OTP) generators like Google Authenticator, designed for both mobile and desktop. It aims to ease you perform your 2FA authentication steps whatever the device you handle, with a clean and suitable interface. - Workflow - Test", + "description": "2FAuth is a web based self-hosted alternative to One Time Passcode (OTP) generators like Google Authenticator, designed for both mobile and desktop. It aims to ease you perform your 2FA authentication steps whatever the device you handle, with a clean and suitable interface.", "install_methods": [ { "type": "default",